proc_rtl.vhd

来自「Intel微处理器8088的VHDL实现」· VHDL 代码 · 共 950 行 · 第 1/5 页

VHD
950
字号

                    if instr.xmod="11" then                             -- Register to Register  rm=reg field
                        second_pass_s <= '0';

                        if (instr.ireg(1)='1') then                     -- Check 'd' bit, if 1 dest=reg else r/m
                            path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.reg; -- dimux & w & seldreg    Note REG=Destination!
                            -- Note aluopr = bit 5 to 3 of opcode
                            -- Note ALU_ADD(6 downto 4) is generic for all sub types
                            -- Note the selalua and selalub values are important for the SUB and CMP instructions!  
                            -- It would have been nice if the position was fixed in the opcode!                     
                            path_s.alu_operation<= '0'&instr.reg & '0'&instr.rm & ALU_ADD(6 downto 4)&instr.ireg(7)&instr.ireg(5 downto 3);-- selalua & selalub & aluopr
                        else
                            path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm; -- dimux & w & seldreg Note RM=Destination!
                            path_s.alu_operation<= '0'&instr.rm & '0'&instr.reg & ALU_ADD(6 downto 4)&instr.ireg(7)&instr.ireg(5 downto 3);-- selalua & selalub & aluopr
                        end if;

                        path_s.ea_output    <= NB_CS_IP;                -- IPREG+NB ADDR=CS:IP
                        
                        --if (instr.ireg(7 downto 2)/="001110") then        -- Check if not CMP or TEST Instruction
                        if ((instr.ireg(5 downto 3)/="111") and (instr.ireg(7)='0')) then       -- Check if not CMP or TEST Instruction
                            wrpath_s.wrd    <= '1';                     -- Write Data Register to Data Register
                        end if; 
                        wrpath_s.wrcc       <= '1';                     -- Update Status Register                                                                   
                        wrpath_s.wrip       <= '1';                     -- Update IP+nbreq register
                        
                        next_state <= Sexecute;

                    else                                                -- Source/dest is memory       
                        if instr.ireg(1)='0' then                       -- Check 'd' bit ->0  SRC=Reg, DEST=rm, Read & Write Cycle  (mem<- mem,  reg, AND) 
                            
                            path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg (only w)
                                                                        
                            path_s.alu_operation<= REG_MDBUS & '0'&instr.reg & ALU_ADD(6 downto 4)&instr.ireg(7)&instr.ireg(5 downto 3);    -- selalua & selalub & aluopr   Path for ALU
                                
                            path_s.dbus_output  <= ALUBUS_OUT;          --{eabus(0)&} domux setting 
                            path_s.ea_output    <= NB_DS_EA;            -- dispmux & eamux & segop  (unless Segment OP flag is set)

                            if (second_pass='0') then                   -- first pass read operand
                                second_pass_s <= '1';                   -- need another pass
                                next_state  <= Sreadmem;                -- start read cycle 
                            else
                                second_pass_s <= '0';                   -- clear                                
                                wrpath_s.wrcc <= '1';                   -- Update Status Register
                                wrpath_s.wrip <= '1';                   -- Update IP+nbreq register 

                                if ((instr.ireg(5 downto 3)/="111") and (instr.ireg(7)='0')) then-- Check if not CMP or TEST Instruction
                                    next_state <= Swritemem;            -- start write cycle
                                else
                                    next_state <= Sexecute;
                                end if;
                            end if;             
                                                    
                        else                                            -- 'd'=1  SRC=rm, DEST=Reg, Read Cycle  (reg<- reg, mem, AND)
                            second_pass_s <= '0';
                            -- Select Data for result path
                            path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.reg;       -- dimux & w & seldreg
                            -- Select Path for ALU                          
                            path_s.alu_operation<= '0'&instr.reg & REG_MDBUS & ALU_ADD(6 downto 4)&instr.ireg(7)&instr.ireg(5 downto 3);-- selalua & selalub & aluopr
                
                            path_s.ea_output    <= NB_DS_EA;            -- dispmux & eamux & segop  (unless Segment OP flag is set)

                            if ((instr.ireg(5 downto 3)/="111") and (instr.ireg(7)='0')) then-- Check if not CMP or TEST Instruction
                                wrpath_s.wrd    <= '1';                 -- Write Data Register to Data Register
                            end if; 
                            wrpath_s.wrcc       <= '1';                 -- Update Status Register                           
                            wrpath_s.wrip       <= '1';                 -- Update IP+nbreq register
                    
                            next_state  <= Sreadmem;                    -- start read cycle             
                        end if;                                                                     

                    end if;


                ---------------------------------------------------------------------------------
                -- OPCODE 80,81,82,83, ADD/ADC/SUB/SBB/CMP/AND/OR/XOR Immediate to Reg/Mem  
                -- ALU operation is defined in reg field (3 bits) and not in bit 5-3 of opcode
                -- Data is routed from drmux->dibus->dbusdp_out
                -- If instr(1)=1 then signextend the data byte (SW=11)
                ---------------------------------------------------------------------------------
                when O80I2RM | O81I2RM | O83I2RM  =>

                    if instr.xmod="11" then                             -- Immediate to Register  r/m=reg field
                        second_pass_s <= '0';
                        
                        path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm;    -- dimux & w & seldreg  Note RM=Destination!!
                        
                        -- instr.reg contains the required operation  (Reg AND Constant)
                        -- If s-bit=0 then 000+REG else 110+REG, s-bit is bit 1 of instr.reg
                        path_s.alu_operation<= '0'&instr.rm & REG_DATAIN &instr.ireg(1)&instr.ireg(1)&"00"&instr.reg; -- selalua & selalub & aluopr
                        path_s.ea_output    <= NB_CS_IP;                -- IPREG+NB ADDR=CS:IP
                        
                        if (instr.reg/="111") then                      -- Check if not CMP Instruction
                            wrpath_s.wrd    <= '1';                     -- Write Data Register to Data Register
                        end if; 
                        wrpath_s.wrcc       <= '1';                     -- Update Status Register                                                               
                        wrpath_s.wrip       <= '1';                     -- Update IP+nbreq register
                        
                        next_state <= Sexecute;

                    else                                                -- Destination and source is memory (no wrpath_s.wrd)
                                                                        -- This is nearly the same as AND with d=0, see above
                        -- only need W bit
                        path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg (only dimux, the rest is don't care) 
                        -- Memory AND Constant, need to read memory first
                        path_s.alu_operation<= REG_MDBUS & REG_DATAIN&instr.ireg(1)&instr.ireg(1)&"00"&instr.reg; -- selalua & selalub & aluopr
                                                                                    
                        path_s.dbus_output  <= ALUBUS_OUT;              --{eabus(0)&} domux setting 
                        path_s.ea_output    <= NB_DS_EA;                -- dispmux & eamux & segop  (unless Segment OP flag is set)

                        if (second_pass='0') then                       -- first pass read operand
                            second_pass_s <= '1';                       -- need another pass
                            next_state  <= Sreadmem;                    -- start read cycle 
                        else
                            second_pass_s <= '0';                       -- clear                                
                            wrpath_s.wrip <= '1';                       -- Update IP+nbreq register 
                            wrpath_s.wrcc <= '1';                       -- Update Status Register 
                            if (instr.reg/="111") then                  -- Check if not CMP Instruction
                                next_state <= Swritemem;                -- start write cycle
                            else
                                next_state <= Sexecute;                 -- CMP, do not write results
                            end if;                            
                        end if;             

                    end if;

                -----------------------------------------------------------------------------
                -- NOT/TEST F6/F7 Shared Instructions 
                -- TEST regfield=000  
                -- NOT  regfield=010
                -- NEG  regfield=011    
                -- MUL  regfield=100
                -- IMUL regfield=101
                -- DIV  regfield=110
                -- IDIV regfield=111
                -- ALU operation is defined in bits 5-3 of modrm.reg
                -- Same sequence as OPC80..83 instruction?
                -- Note for NOT instruction DATAIN must be zero!!
                -----------------------------------------------------------------------------
                when F6INSTR | F7INSTR  =>
                    
                   --   case instr.reg(2 downto 0) is   
                    case instr.reg is   
                                                
                        when "000"  =>                                  -- TEST instruction, Combine with NEG/NOT Instruction ?????????????
                            if instr.xmod="11" then                     -- Immediate to Register  r/m=reg field
                                second_pass_s <= '0';
                                
                                path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm;    -- dimux & w & seldreg  
                                -- instr.reg contains the required operation  
                                -- Note ALU_TEST2 is generic for all sub types
                                path_s.alu_operation<= '0'&instr.rm & REG_DATAIN & ALU_TEST2(6 downto 3)&instr.reg; -- selalua & selalub & aluopr

                                path_s.ea_output    <= NB_CS_IP;        -- IPREG+NB ADDR=CS:IP
                                
                                wrpath_s.wrcc       <= '1';             -- Update Status Register                                                               
                                wrpath_s.wrip       <= '1';             -- Update IP+nbreq register
                                
                                next_state <= Sexecute;

                            else                                        -- Destination and source is memory (no wrpath_s.wrd)
                                                                        -- This is nearly the same as AND with d=0, see above
                                -- only need W bit
                                path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg (only dimux, the rest is don't care) 
                                -- Memory AND Constant, need to read memory first
                                path_s.alu_operation<= REG_MDBUS & REG_DATAIN & ALU_TEST2(6 downto 3)&instr.reg; -- selalua & selalub & aluopr
                                                                                            
                                path_s.dbus_output  <= ALUBUS_OUT;      --{eabus(0)&} domux setting 
                                path_s.ea_output    <= NB_DS_EA;        -- dispmux & eamux & segop  (unless Segment OP flag is set)

                                if (second_pass='0') then               -- first pass read operand
                                    second_pass_s <= '1';               -- need another pass
                                    next_state  <= Sreadmem;            -- start read cycle 
                                else
                                    second_pass_s <= '0';               -- clear                                
                                    wrpath_s.wrip <= '1';               -- Update IP+nbreq register 
                                    wrpath_s.wrcc <= '1';               -- Update Status Register 
                                    next_state <= Sexecute;             -- TEST, do not write results
                                end if;             

                            end if;

                        when "010" | "011"  =>                          -- Invert NOT and 2s complement NEG
                                                                        -- Check with others to see if can be combined!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                            if instr.xmod="11" then                     -- Negate Register  r/m=reg field
                                second_pass_s <= '0';
                                
                                path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm;    -- dimux & w & seldreg  
                                -- Note ALU_TEST2 is generic for all sub types
                                if (instr.reg(0)='1') then              -- NEG instruction
                                    path_s.alu_operation<= '0'&instr.rm & REG_CONST1 & ALU_TEST2(6 downto 3)&instr.reg; -- selalua & se

⌨️ 快捷键说明

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