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