📄 proc_rtl.vhd
字号:
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 + -