⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alu_rtl.vhd

📁 Intel微处理器8088的VHDL实现
💻 VHD
📖 第 1 页 / 共 3 页
字号:
                            =>  cbus_s(0) <= '0';
            when ALU_SBB | ALU_SBB_SE   
                            =>  cbus_s(0) <= not CFLAG;
            when ALU_SUB | ALU_SUB_SE | ALU_DEC | ALU_PUSH | ALU_CMP | ALU_CMP_SE 
                         | ALU_CMPS   | ALU_SCAS    
                            =>  cbus_s(0) <= '1';
            when others     =>  cbus_s(0) <= CFLAG;     -- ALU_ADC, ALU_SUB, ALU_SBB
        end case;
end process; 

----------------------------------------------------------------------------
-- Carry Out logic
-- cout is inverted for ALU_SUB and ALU_SBB before written to psrreg_s
----------------------------------------------------------------------------
process (aluopr, w, psrreg_s, cbus_s, alu_inbusa)
    begin 
        case aluopr is  
            when ALU_ADD | ALU_ADD_SE | ALU_ADC | ALU_ADC_SE | ALU_SUB | ALU_SUB_SE | ALU_SBB | ALU_SBB_SE |
                 ALU_CMP | ALU_CMP_SE | ALU_CMPS| ALU_SCAS => 
                if (w='1') then cout_s <= cbus_s(16); 
                    else cout_s <= cbus_s(8); 
                end if;
            when ALU_NEG =>                             -- CF=0 if operand=0, else 1
                if (alu_inbusa=X"0000") then
                    cout_s <= '1';                      -- Note CFLAG=NOT(cout_s)
                else
                    cout_s <= '0';                      -- Note CFLAG=NOT(cout_s)
                end if;         
            when others  => 
                cout_s <= CFLAG;                        -- Keep previous value
        end case;       
end process;

----------------------------------------------------------------------------
-- Overflow Logic
----------------------------------------------------------------------------
process (aluopr, w, psrreg_s, cbus_s, alureg_s, alucout_s, zflaghigh_s, zflagdx_s,hflagdx_s,zflagah_s,
         hflagah_s, wl_s, product_s, c1flag_s)
    begin 
        case aluopr is          
            when ALU_ADD | ALU_ADD_SE | ALU_ADC | ALU_ADC_SE | ALU_INC | ALU_DEC | ALU_SUB | ALU_SUB_SE |  
                 ALU_SBB | ALU_SBB_SE | ALU_CMP | ALU_CMP_SE | ALU_CMPS | ALU_SCAS | ALU_NEG =>
                if w='1' then                       -- 16 bits
                    overflow_s  <= cbus_s(16) xor cbus_s(15);
                else 
                    overflow_s  <= cbus_s(8) xor cbus_s(7);             
                end if;

            when ALU_ROL1 | ALU_RCL1 | ALU_SHL1 =>          -- count=1 using constants as in rcl bx,1
                if (((w='1') and (alureg_s(15)/=alucout_s)) or
                    ((w='0') and (alureg_s(7) /=alucout_s))) then
                    overflow_s <= '1';  
                else
                    overflow_s <= '0'; 
                end if;
            when ALU_ROL | ALU_RCL | ALU_SHL =>             -- cl/cx=1              
                if (( c1flag_s='1' and w='1' and (alureg_s(15)/=alucout_s)) or
                    ( c1flag_s='1' and w='0' and (alureg_s(7) /=alucout_s))) then
                    overflow_s <= '1';  
                else
                    overflow_s <= '0'; 
                end if;


            when ALU_ROR1 | ALU_RCR1 | ALU_SHR1 | ALU_SAR1 => 
                if (((w='1') and (alureg_s(15)/=alureg_s(14))) or
                    ((w='0') and (alureg_s(7) /=alureg_s(6)))) then 
                    overflow_s <= '1';  
                else
                    overflow_s <= '0'; 
                end if;     
            when ALU_ROR | ALU_RCR | ALU_SHR | ALU_SAR =>           -- if cl/cx=1
                if ((c1flag_s='1' and w='1' and (alureg_s(15)/=alureg_s(14))) or
                    (c1flag_s='1' and w='0' and (alureg_s(7) /=alureg_s(6)))) then  
                    overflow_s <= '1';  
                else
                    overflow_s <= '0'; 
                end if;     
                
                        
            when ALU_MUL | ALU_MUL2 => 
                if (wl_s='0') then
                    overflow_s <= zflaghigh_s;  
                else
                    overflow_s <= zflagdx_s;    -- MSW multiply/divide result
                end if;
            when ALU_IMUL | ALU_IMUL2 =>        -- if MSbit(1)='1' & AH=FF/DX=FFFF 
                if ((wl_s='0' and product_s(7)='1'  and hflagah_s='1') or
                    (wl_s='0' and product_s(7)='0'  and zflagah_s='0') or
                    (wl_s='1' and product_s(15)='1' and hflagdx_s='1') or
                    (wl_s='1' and product_s(15)='0' and zflagdx_s='0')) then
                    overflow_s <= '0';  
                else
                    overflow_s <= '1';                  
                end if;
            when others     =>  
                overflow_s <= OFLAG;                -- Keep previous value
        end case;
end process;

----------------------------------------------------------------------------
-- Zeroflag set if result=0, zflagdx_s=1 when dx/=0, zflagah_s=1 when ah/=0
----------------------------------------------------------------------------
zflaglow_s  <=  alubus_s(7)  or alubus_s(6)  or alubus_s(5)  or alubus_s(4)  or
                alubus_s(3)  or alubus_s(2)  or alubus_s(1)  or alubus_s(0);
zflaghigh_s <=  alubus_s(15) or alubus_s(14) or alubus_s(13) or alubus_s(12) or
                alubus_s(11) or alubus_s(10) or alubus_s(9)  or alubus_s(8);
zeroflag_s  <= not(zflaghigh_s or zflaglow_s) when w='1' else not(zflaglow_s);

zflagdx_s   <=  product_s(31) or product_s(30) or product_s(29) or product_s(28) or
                product_s(27) or product_s(26) or product_s(25) or product_s(24) or
                product_s(23) or product_s(22) or product_s(21) or product_s(20) or
                product_s(19) or product_s(18) or product_s(17) or product_s(16);

zflagah_s   <=  product_s(15) or product_s(14) or product_s(13) or product_s(12) or
                product_s(11) or product_s(10) or product_s(09) or product_s(08);

----------------------------------------------------------------------------
-- hflag set if IMUL result AH=FF or DX=FFFF 
----------------------------------------------------------------------------
hflagah_s  <=   product_s(15) and product_s(14) and product_s(13) and product_s(12) and
                product_s(11) and product_s(10) and product_s(9)  and product_s(8);

hflagdx_s  <=   product_s(31) and product_s(30) and product_s(29) and product_s(28) and
                product_s(27) and product_s(26) and product_s(25) and product_s(24) and
                product_s(23) and product_s(22) and product_s(21) and product_s(20) and
                product_s(19) and product_s(18) and product_s(17) and product_s(16);

----------------------------------------------------------------------------
-- Parity flag set if even number of bits in LSB
----------------------------------------------------------------------------
parityflag_s <=not(alubus_s(7) xor alubus_s(6) xor alubus_s(5) xor alubus_s(4)  xor
                   alubus_s(3) xor alubus_s(2) xor alubus_s(1) xor alubus_s(0));

----------------------------------------------------------------------------
-- Sign flag
----------------------------------------------------------------------------
signflag_s <= alubus_s(15) when w='1' else alubus_s(7);

----------------------------------------------------------------------------
-- c1flag asserted if CL or CX=1, used to update the OF flags during
-- rotate/shift instructions
----------------------------------------------------------------------------
c1flag_s  <= '1' when (cx_s=X"0001" and w='1') OR (cx_s(7 downto 0)=X"01" and w='0') else '0';

----------------------------------------------------------------------------
-- Temp/ScratchPad Register
-- alureg_s can also be used as temp storage
-- temp<=bbus; 
----------------------------------------------------------------------------
process (clk, reset)
    begin 
        if reset='1' then
            alu_temp_s<= (others => '0');
        elsif rising_edge(clk) then
            if (wrtemp='1') then 
                alu_temp_s <= bbus_s;
            end if;
        end if;
end process;


----------------------------------------------------------------------------
-- ALU Register used for xchg and rotate/shift instruction
-- latch Carry Out alucout_s signal
----------------------------------------------------------------------------
process (clk, reset)
    begin 
        if reset='1' then
            alureg_s <= (others => '0'); 
            alucout_s<= '0';                                              
            wl_s     <= '0';        
        elsif rising_edge(clk) then
            if (wralu='1') then 
                alureg_s(31 downto 16) <= abus_s;   -- alu_inbusa;
                wl_s <= w;                          -- Latched w version
                if w='1' then                       -- word operation
                    case aluopr is
                        when ALU_ROL | ALU_ROL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 0) & alureg_s(15);
                                                   alucout_s<= alureg_s(15); 
                        when ALU_ROR | ALU_ROR1 => alureg_s(15 downto 0) <= alureg_s(0) & alureg_s(15 downto 1); 
                                                   alucout_s<= alureg_s(0);     
                        when ALU_RCL | ALU_RCL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 0) & alucout_s; -- shift carry in
                                                   alucout_s<= alureg_s(15);    
                        when ALU_RCR | ALU_RCR1 => alureg_s(15 downto 0) <= alucout_s & alureg_s(15 downto 1);
                                                   alucout_s<= alureg_s(0);     
                        when ALU_SHL | ALU_SHL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 0) & '0';
                                                   alucout_s<= alureg_s(15);    
                        when ALU_SHR | ALU_SHR1 => alureg_s(15 downto 0) <= '0' & alureg_s(15 downto 1);
                                                   alucout_s<= alureg_s(0);     
                        when ALU_SAR | ALU_SAR1 => alureg_s(15 downto 0) <= alureg_s(15) & alureg_s(15 downto 1);
                                                   alucout_s<= alureg_s(0); 
                       when ALU_TEMP            => alureg_s(15 downto 0) <= bbus_s;
                                                   alucout_s<= '-';         -- Don't care!
                        when ALU_AAM            => alureg_s(15 downto 0) <= X"000A";
                                                   alucout_s<= '-';         -- Don't care!
                        
                        when others => alureg_s(15 downto 0) <= bbus_s ;--alu_inbusb;           -- ALU_PASSB
                                                   alucout_s<= CFLAG; 
                    end case; 
                else
                    case aluopr is                    -- To aid resource sharing add MSB byte as above
                        when ALU_ROL | ALU_ROL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 7)               & (alureg_s(6 downto 0) & alureg_s(7)); 
                                                   alucout_s<= alureg_s(7);
                        when ALU_ROR | ALU_ROR1 => alureg_s(15 downto 0) <= alureg_s(0) & alureg_s(15 downto 9) & (alureg_s(0) & alureg_s(7 downto 1));     
                                                   alucout_s<= alureg_s(0);
                        when ALU_RCL | ALU_RCL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 7)               & (alureg_s(6 downto 0) & alucout_s); -- shift carry in 
                                                   alucout_s<= alureg_s(7);
                        when ALU_RCR | ALU_RCR1 => alureg_s(15 downto 0) <= alucout_s & alureg_s(15 downto 9) & (psrreg_s(0) & alureg_s(7 downto 1));   
                                                   alucout_s<= alureg_s(0);
                        when ALU_SHL | ALU_SHL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 7)               & (alureg_s(6 downto 0) & '0'); 
                                                   alucout_s<= alureg_s(7);
                        when ALU_SHR | ALU_SHR1 => alureg_s(15 downto 0) <= '0' & alureg_s(15 downto 9)         & ('0' & alureg_s(7 downto 1)); 
                                                   alucout_s<= alureg_s(0);
                        when ALU_SAR | ALU_SAR1 => alureg_s(15 downto 0) <= alureg_s(15) & alureg_s(15 downto 9)& (alureg_s(7) & alureg_s(7 downto 1)); 
                                                   alucout_s<= alureg_s(0);
                        when ALU_TEMP           => alureg_s(15 downto 0) <= bbus_s;
                                                   alucout_s<= '-';         -- Don't care!
                        when ALU_AAM            => alureg_s(15 downto 0) <= X"000A";
                                                   alucout_s<= '-';         -- Don't care!
                        when others => alureg_s(15 downto 0) <= bbus_s ;--alu_inbusb            -- ALU_PASSB
                                                   alucout_s<= CFLAG;
                    end case; 
                end if;
            end if; 
        end if; 
end process;  

----------------------------------------------------------------------------
-- AAS Instruction  3F
----------------------------------------------------------------------------
-- if (((AL = AL & 0x0F) > 9) || (AF == 1))     
--      AL = (AL - 6) & 0x0F;
--      AH = AH - 1;
--      CF=1, AF=1;
-- else CF=0, AF=0;
----------------------------------------------------------------------------
process (alu_inbusa,psrreg_s,aas1bus_s)
    begin
    	aas1bus_s<=alu_inbusa-X"0106"; 
        if ((alu_inbusa(3 downto 0) > "1001") or (psrreg_s(4)='1')) then    
            aasbus_s <= aas1bus_s(15 downto 8)&X"0"&aas1bus_s(3 downto 0);
            setaas_s <= '1';                    -- Set CF and AF flag
        else
            aasbus_s(7 downto 0) <= X"0"&(alu_inbusa(3 downto 0));  -- AL=AL&0Fh
            aasbus_s(15 downto 8)<= alu_inbusa(15 downto 8); -- leave AH unchanged
            setaas_s <= '0';                    -- Clear CF and AF flag
        end if;
end process;

----------------------------------------------------------------------------
-- AAA Instruction  37
----------------------------------------------------------------------------
-- if (((AL = AL & 0x0F) > 9) || (AF == 1))
--      AL = (AL + 6) & 0x0F;
--      AH = AH + 1;
--      CF=1, AF=1;
-- else CF=0, AF=0;
----------------------------------------------------------------------------
process (alu_inbusa,psrreg_s,aaa1bus_s)
    begin
    	aaa1bus_s<=alu_inbusa+X"0106";
        if ((alu_inbusa(3 downto 0) > "1001") or (psrreg_s(4)='1')) then   
            aaabus_s <= aaa1bus_s(15 downto 8)&X"0"&aaa1bus_s(3 downto 0);
            setaaa_s <= '1';                    -- Set CF and AF flag
        else
            aaabus_s(7 downto 0) <= X"0"&alu_inbusa(3 downto 0); -- AL=AL&0Fh
            aaabus_s(15 downto 8)<= alu_inbusa(15 downto 8);    -- AH Unchanged
            setaaa_s <= '0';                    -- Clear CF and AF flag
        end if;
end process;

----------------------------------------------------------------------------
-- DAA Instruction  27
----------------------------------------------------------------------------
-- if (((AL & 0x0F) > 9) || (AF == 1))
--      AL = AL + 6;
--      AF = 1;
-- else AF = 0;
-- if ((AL > 0x9F) || (CF == 1))
--      AL = AL + 0x60;
--      CF = 1;
-- else CF = 0;
----------------------------------------------------------------------------
process (alu_inbusa,psrreg_s,setdaa_s)
    begin
        if ((alu_inbusa(3 downto 0) > X"9") or (psrreg_s(4)='1')) then  
            setdaa_s(0) <= '1';     -- set AF
        else
            setdaa_s(0) <= '0';     -- clr AF

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -