proc_rtl.vhd

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

VHD
950
字号
                        wrpath_s.wrs        <= '1';                     -- Write Data Register to Segment Register
                        wrpath_s.wrip       <= '1';                     -- Update IP+nbreq register
                    
                        next_state <= Sexecute;

                    else                                                -- Memory to Segment Register

                        path_s.segreg_input <= SMDBUS_IN & instr.reg(1 downto 0); -- simux & selsreg

                        path_s.ea_output    <= NB_DS_EA;                -- dispmux & eamux & segop  (unless Segment OP flag is set)

                        wrpath_s.wrs        <= '1';                     -- Write Memory to Segment Register
                        wrpath_s.wrip       <= '1';                     -- Update IP+nbreq register
                    
                        next_state  <= Sreadmem;                        -- start read cycle                       
                    end if; 

                ---------------------------------------------------------------------------------
                -- Load Effective Address in Data Register
                -- mod=11 result in proc_error
                ---------------------------------------------------------------------------------
                when LEA =>
                    second_pass_s <= '0';

                    if instr.xmod="11" then                             -- Register to Register  rm=reg field
                        proc_error_s<='1';                              -- Assert Bus Error Signal
                        -- pragma synthesis_off
                        assert not (now > 0 ns) report "**** Illegal LEA operand (mod=11) (proc)  ***" severity failure;
                        -- pragma synthesis_on
                    end if;                                             -- Transfer Effective addresss (EABUS) to data register
                    
                    path_s.datareg_input<= EABUS_IN & '1' & instr.reg;  -- dimux & w & seldreg                      
                    path_s.ea_output    <= NB_DS_EA;                    -- dispmux & eamux & segop  

                    wrpath_s.wrd        <= '1';                         -- Write EABUS to Data Register
                    wrpath_s.wrip       <= '1';                         -- Update IP+nbreq register                 
                    
                    next_state  <= Sexecute;        

                    ---------------------------------------------------------------------------------
                    -- Load Effective Address in ES/DS:DEST_REGISTER
                    -- mod=11 result in proc_error
                    -- TEMP <=  readmem(ea) ; PASS1   (required for cases like LES SI,[SI] )
                    -- REG  <=  TEMP        ; PASS2
                    -- ES/DS<=  readmem(ea+2)
                    ---------------------------------------------------------------------------------
                    when LES | LDS =>
    
                        if instr.xmod="11" then                             -- Register to Register  rm=reg field
                            proc_error_s<='1';                              -- Assert Bus Error Signal
                            -- pragma synthesis_off
                            assert not (now > 0 ns) report "**** Illegal LES/LDS operand (mod=11) (proc)  ***" severity warning;
                            -- pragma synthesis_on
                        end if;                                             
        
                        path_s.alu_operation<= DONTCARE(3 downto 0) & REG_MDBUS & ALU_TEMP;-- selalua(4) & selalub(4) & aluopr                        
    
                        if (second_pass='0') then                           -- first pass reg<=mem(ea)
                            second_pass_s <= '1';                           -- need another pass
                            
                            path_s.datareg_input<= MDBUS_IN & '1' & instr.reg;-- dimux & w & seldreg
    
                            path_s.ea_output<="0000001001";                 -- dispmux(3) & eamux(4)=EA & dis_opflag & segop[1:0]
                            wrpath_s.wrtemp  <= '1'; -- Write reg value to alu_temp first                
                            next_state  <= Sreadmem;                        -- start read to read temp<=EA  
                        else
                            second_pass_s <= '0';                           -- clear
                        
                            path_s.datareg_input<= ALUBUS_IN & '1' & instr.reg;-- dimux & w & seldreg
                            path_s.ea_output<="0000011001";                 -- dispmux(3) & eamux(4)=EA+2 & dis_opflag & segop[1:0]
                                                                            -- Second Pass ES/DS<=mem(ea+2)
                            if instr.ireg(0)='0' then                       -- C4=LES
                                path_s.segreg_input <= SMDBUS_IN & ES_IN(1 downto 0); -- simux & selsreg=ES
                            else                                            -- C5=LDS
                                path_s.segreg_input <= SMDBUS_IN & DS_IN(1 downto 0); -- simux & selsreg=DS
                            end if;
                            wrpath_s.wrip <= '1';                           -- Update IP+nbreq register
                            wrpath_s.wrd  <= '1';                           -- Update Reg<=temp
                            wrpath_s.wrs  <= '1';                           -- Update ES/DS Register                                                
                            next_state  <= Sreadmem;
                        end if;             

                ---------------------------------------------------------------------------------
                -- Convert AL to AX, AX -> DX:AX
                -- Flags are not affected
                ---------------------------------------------------------------------------------
                when CBW | CWD =>
                    second_pass_s <= '0';

                    -- Note ALU_SEXT(6 downto 4) is generic for CBW and CWD
                    path_s.alu_operation<= REG_AX & DONTCARE(3 downto 0) & ALU_SEXT(6 downto 4) & instr.ireg(3 downto 0) ;-- selalua & selalub & aluopr

                    if (instr.ireg(0)='0') then                         -- if 0 then CBW else CWD
                        path_s.datareg_input<= ALUBUS_IN & '1' & REG_AX(2 downto 0);-- dimux & w & seldreg  Note RM=Destination!!
                    else
                        path_s.datareg_input<= ALUBUS_IN & '1' & REG_DX(2 downto 0);-- dimux & w & seldreg  Note RM=Destination!!
                    end if;

                    path_s.ea_output    <= NB_CS_IP;                    -- IPREG+NB ADDR=CS:IP
                                                                                        
                    wrpath_s.wrd        <= '1';                         -- Write Data Register to Data Register
                    wrpath_s.wrip       <= '1';                         -- Update IP+nbreq register

                    next_state <= Sexecute;
                
                ---------------------------------------------------------------------------------
                -- Convert AL 
                -- Use bit 4 of instruction to drive W bit
                ---------------------------------------------------------------------------------
                when AAS | DAS | AAA | DAA | AAM | AAD =>
                    
                    passcnt_s <= passcnt - '1';

                    path_s.ea_output <= NB_CS_IP;                       -- IPREG+NB ADDR=CS:IP
                    path_s.datareg_input<= ALUBUS_IN & instr.ireg(4) & REG_AX(2 downto 0);-- dimux & w & seldreg    Note RM=Destination!!
                    path_s.alu_operation<= REG_AX & DONTCARE(3 downto 0) & ALU_DAA(6 downto 4)&instr.ireg(0)&instr.ireg(5 downto 3);-- selalua & selalub & aluopr

                    if (second_pass='0') then                           -- first pass
                                               
                        if (instr.ireg=AAM) then                        -- AAM instruction only
                            second_pass_s   <= '1';                     -- need another pass
                            wrpath_s.wralu  <= '1';                     -- Write Data to ALUREG, only used for AAM (uses divider)
                            passcnt_s       <= DIV_MCD_C;           -- Serial delay
                            next_state      <= Sdecode;                 -- round the loop again
                        else                    
                            second_pass_s   <= '0';                      
                            wrpath_s.wrcc   <= '1';                     -- Update Status Register                                                                       
                            wrpath_s.wrd    <= '1';                     -- Write Data Register to Data Register                        
                            wrpath_s.wrip   <= '1';                     -- Update IP+nbreq register 
                            next_state      <= Sexecute;                -- terminate    
                        end if;
                    
                    else
                        second_pass_s       <= '1';
                        if (passcnt="000000") then                      -- Divider Done?
                            second_pass_s   <= '0';                      
                            wrpath_s.wrcc   <= '1';                     -- Update Status Register                                                                       
                            wrpath_s.wrd    <= '1';                     -- Write Data Register to Data Register                                                 
                            wrpath_s.wrip   <= '1';                     -- Update IP+nbreq register 
                            next_state      <= Sexecute;                -- terminate    
                        end if;
                    end if;


                ---------------------------------------------------------------------------------
                -- Segment Override Prefix  
                ---------------------------------------------------------------------------------
                when SEGOPES | SEGOPCS | SEGOPSS | SEGOPDS => 

                    irq_blocked_s <= '1';                               -- Block IRQ if asserted during next instr.
                    second_pass_s <= '0';
                    path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg 
                                                                                               
                    path_s.ea_output    <= "000"&DONTCARE(3 downto 0) & '0' & instr.ireg(4 downto 3);  -- dispmux & eamux(4) & [flag]&segop[1:0] 
                                                                                            
                    wrpath_s.wrop       <= '1';                         -- Write to Override Prefix Register
                    wrpath_s.wrip       <= '1';                         -- Update IP+nbreq register
                    
                    next_state  <= Sexecute;

                ---------------------------------------------------------------------------------
                -- LOCK Prefix, Not implemented, result in NOP  
                ---------------------------------------------------------------------------------
                when LOCKBUS => 
--                  irq_blocked_s   <= '1';                             -- Block IRQ if asserted during next instr.
                    second_pass_s   <= '0'; 
                    path_s.ea_output<= NB_CS_IP;                     
                    wrpath_s.wrip   <= '1';                             -- Update IP+nbreq register
                    next_state      <= Sexecute;
            
                ---------------------------------------------------------------------------------
                -- Halt Instruction, wait for NMI, INTR, Reset  
                ---------------------------------------------------------------------------------
                when HLT => 

                    second_pass_s   <= '0';
                    path_s.ea_output<= NB_CS_IP;                     
                    wrpath_s.wrip   <= '1';                             -- Update IP+nbreq register                     
                    next_state      <= Sexecute;
                                                                                               

                ---------------------------------------------------------------------------------
                -- ADD/ADC/SUB/SBB/CMP/AND/OR/XOR Register/Memory <- Register/Memory
                -- TEST same as AND without returning any result (wrpath_s.wrd is not asserted) 
                ---------------------------------------------------------------------------------
                when ADDRM2R0 |  ADDRM2R1 | ADDRM2R2 |  ADDRM2R3 | ADCRM2R0 |  ADCRM2R1 | ADCRM2R2 |  ADCRM2R3 |    
                     SUBRM2R0 |  SUBRM2R1 | SUBRM2R2 |  SUBRM2R3 | SBBRM2R0 |  SBBRM2R1 | SBBRM2R2 |  SBBRM2R3 |    
                     CMPRM2R0 |  CMPRM2R1 | CMPRM2R2 |  CMPRM2R3 | ANDRM2R0 |  ANDRM2R1 | ANDRM2R2 |  ANDRM2R3 |    
                     ORRM2R0  |  ORRM2R1  | ORRM2R2  |  ORRM2R3  | XORRM2R0 |  XORRM2R1 | XORRM2R2 |  XORRM2R3 |
                     TESTRMR0 |  TESTRMR1  =>   

⌨️ 快捷键说明

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