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

📄 proc_rtl.vhd

📁 Intel微处理器8088的VHDL实现
💻 VHD
📖 第 1 页 / 共 5 页
字号:
        when Sopcode =>   

            second_pass_s<='0';
            opc_req <= '1'; 

            if (latcho = '0')   then 
                next_state <= Sopcode;                  -- Wait
            else
                next_state <= Sdecode;                  -- Decode instruction               
            end if;

        ----------------------------------------------------------------------------
        -- Opcode received, decode instruction
        -- Set Path (next state)
        -- Set wrpath_s, lacthed as this stage, enabled only at Sexecute
        ----------------------------------------------------------------------------
        when Sdecode =>    
                    
             if second_pass='1' then
                wrpath <= wrpathl_s;                                    -- Assert write strobe(s) during first & second pass                                                        
             else 
                decode_state <= '1';                                    -- Asserted during first decode stage
             end if;

             case instr.ireg is

                ---------------------------------------------------------------------------------
                -- IN Port Instruction           0xE4..E5, 0xEC..ED
                -- Use fake xmod and rm setting for fixed port number
                ---------------------------------------------------------------------------------
                when INFIXED0 | INFIXED1 | INDX0 | INDX1 =>
                    second_pass_s <= '0';
                    iomem_s       <= '1';                               -- Select IO cycle

                    path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & "000";    -- dimux & w & seldreg  AX/AL=000
                
                    if instr.ireg(3)='0' then                           -- 0=Fixed, 1=DX
                        path_s.ea_output    <= PORT_00_EA & DONTCARE(2 downto 0);-- dispmux & eamux(4) & segop  11=00:EA
                    else                                                -- 1=DX
                        path_s.ea_output    <= PORT_00_DX & DONTCARE(2 downto 0);-- dispmux & eamux(4) & segop  10=00:DX
                    end if;

                    wrpath_s.wrd        <= '1';                         -- Write to Data Register
                    wrpath_s.wrip       <= '1';                         -- Update IP+nbreq register                 
                    
                    next_state  <= Sreadmem;                            -- start read cycle     

                ---------------------------------------------------------------------------------
                -- XLAT Instruction          
                -- AL<= SEG:[BX+AL]
                ---------------------------------------------------------------------------------
                when XLAT =>
                    second_pass_s <= '0';

                    path_s.datareg_input<= MDBUS_IN & '0' & REG_AX(2 downto 0); -- dimux & w & seldreg  AX/AL=000
                
                    path_s.ea_output<= "0001111011";                    -- EA=BX+AL, dispmux(2) & eamux(4) & [flag]&segop(2)

                    wrpath_s.wrd    <= '1';                             -- Write to Data Register
                    wrpath_s.wrip   <= '1';                             -- Update IP+nbreq register                 
                    
                    next_state      <= Sreadmem;                        -- start read cycle     


                ---------------------------------------------------------------------------------
                -- OUT Port Instruction          0xE6..E7, 0xEE..EF
                -- Use fake xmod and rm setting for fixed port number
                ---------------------------------------------------------------------------------
                when OUTFIXED0 | OUTFIXED1 | OUTDX0 | OUTDX1 =>
                    second_pass_s <= '0';
                    iomem_s       <= '1';                               -- Select IO cycle
                    
                    path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg  Only need to set W

                    path_s.alu_operation<= "0000" & DONTCARE(3 downto 0) & ALU_PASSA;  -- selalua & selalub & aluopr  selalua=AX/AL
                    path_s.dbus_output  <= ALUBUS_OUT;                  --{eabus(0)&} domux setting  
                    
                    if instr.ireg(3)='0' then                           -- 0=Fixed, 1=DX
                        path_s.ea_output    <= PORT_00_EA & DONTCARE(2 downto 0);-- dispmux & eamux(4) & segop  11=00:EA
                    else                                                -- 1=DX
                        path_s.ea_output    <= PORT_00_DX & DONTCARE(2 downto 0);-- dispmux & eamux(4) & segop  10=00:DX
                    end if;

                    wrpath_s.wrip       <= '1';                         -- Update IP+nbreq register                 
                    
                    next_state  <= Swritemem;                           -- start write cycle        


                ---------------------------------------------------------------------------------
                -- Increment/Decrement Register, word only!
                ---------------------------------------------------------------------------------
                when INCREG0 |INCREG1 |INCREG2 |INCREG3 | INCREG4 |INCREG5 |INCREG6 |INCREG7 |
                     DECREG0 |DECREG1 |DECREG2 |DECREG3 | DECREG4 |DECREG5 |DECREG6 |DECREG7 => 
                    second_pass_s <= '0';

                    path_s.datareg_input<= ALUBUS_IN & '1' & instr.reg; -- dimux & w & seldreg
                        
                    -- instr.ireg(5..3) contains the required operation,  ALU_INBUSB=X"0001"
                    -- Note ALU_INC is generic for INC/DEC
                    path_s.alu_operation<= '0'&instr.reg & REG_CONST1 & ALU_INC(6 downto 3)&instr.ireg(5 downto 3); -- selalua & selalub & aluopr

                    path_s.ea_output    <= NB_CS_IP;                    -- IPREG+NB ADDR=CS:IP

                    wrpath_s.wrd        <= '1';                         -- Update register 
                    wrpath_s.wrcc       <= '1';                         -- Update Flag register
                    wrpath_s.wrip       <= '1';                         -- Update IP+nbreq register
                    
                    next_state  <= Sexecute;

                -----------------------------------------------------------------------------
                -- Shift/Rotate Instructions   
                -- Operation define in MODRM REG bits
                -- Use MODRM reg bits   
                -- bit 0=b/w, bit1=0 then count=1 else count=cl
                -- if cl=00 then don't write to CC register
                -----------------------------------------------------------------------------
                when SHFTROT0 | SHFTROT1 | SHFTROT2 | SHFTROT3 =>   
                    
                    if instr.reg="110" then                             -- Not supported/defined
                        proc_error_s<='1';                              -- Assert Bus Error Signal
                        -- pragma synthesis_off
                        assert not (now > 0 ns) report "**** Illegal SHIFT/ROTATE instruction (proc)  ***" severity failure;
                        -- pragma synthesis_on
                    end if;

                    if instr.xmod="11" then                             -- Immediate to Register  r/m=reg field
                        
                        path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm; -- dimux & w & seldreg Note RM=Destination!!

                        path_s.ea_output    <= NB_CS_IP;                -- IPREG+NB ADDR=CS:IP
                        
                        if (second_pass='0') then                       -- first pass, load reg into alureg
                            
                            if (instr.ireg(1)='1' and status.cl5="00000") then
                                second_pass_s <= '0';                   -- No second pass if cl=0
                                wrpath_s.wrip <= '1';                   -- Update IP+nbreq register 
                                next_state    <= Sexecute;              -- terminate    
                            else
                                second_pass_s <= '1';                   -- need another pass
                                next_state    <= Sdecode;               -- round the loop again
                            end if;

                            -- Load instr.rm register into ALUREG                       
                            path_s.alu_operation<= DONTCARE(3 downto 0) & '0'&instr.rm & ALU_REGL; -- selalua(4) & selalub(4) & aluopr(7)
                            wrpath_s.wralu      <= '1'; 
                                
                            if (instr.ireg(1)='1') then                             
                                passcnt_s   <= status.cl5;              -- Load CL loop counter
                            end if;                                     -- else passcnt_s=1;
                                
                        
                        else                                            -- second pass, terminate or go around the loop again
                            
                            -- selalua & selalu are dontcare, instruction is V+001+instr.reg    
                            -- ALU_ROL(6 downto 4) is generic for all shift/rotate 
                            -- Instruction=Constant & V_Bit & modrm.reg(5 downto 3)                 
                            path_s.alu_operation<= DONTCARE(3 downto 0) & '0'&instr.rm & ALU_ROL(6 downto 4)& instr.ireg(1) & instr.reg; -- selalua(4) & selalub(4) & aluopr(7)

                            if (passcnt="00000") then                   -- Check if end of shift/rotate
                                second_pass_s   <= '0';                 -- clear
                                wrpath_s.wrcc   <= '1';                 -- Update Status Register after last shift/rot  
                                wrpath_s.wrd    <= '1';                 -- Write shift/rotate results to Data Register
                                wrpath_s.wrip   <= '1';                 -- Update IP+nbreq register 
                                next_state      <= Sexecute;            -- terminate                    
                            else
                                second_pass_s   <= '1';                 -- need another pass
                                wrpath_s.wralu  <= '1';
                                wrpath_s.wrcc   <= '1';
                                passcnt_s       <= passcnt - '1';
                                next_state      <= Sdecode;             -- round the loop again                             
                            end if; 
                                                           
                        end if; 

                    else                                                -- Destination and source is memory, use ALUREG 
                        
                        path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & DONTCARE(2 downto 0); --  ver 0.69, path& w! seldreg=don'tcare                                                            
                        
                        path_s.dbus_output  <= ALUBUS_OUT;              -- {eabus(0)&} domux setting    
                        path_s.ea_output    <= NB_DS_EA;                -- dispmux & eamux & segop  

                        if (second_pass='0') then                       -- first pass, load memory operand into alureg
                            
                            if (instr.ireg(1)='1' and status.cl5="00000") then
                                second_pass_s <= '0';                   -- No second pass if cl=0
                                wrpath_s.wrip <= '1';                   -- Update IP+nbreq register 
                                next_state    <= Sexecute;              -- terminate    
                            else
                                second_pass_s <= '1';                   -- need another pass
                                next_state    <= Sreadmem;              -- start read cycle

⌨️ 快捷键说明

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