📄 alu_rtl.vhd
字号:
end if;
if ((alu_inbusa(7 downto 0) > X"9F") or (psrreg_s(0)='1')) then
setdaa_s(1) <= '1'; -- set CF
else
setdaa_s(1) <= '0'; -- clr CF
end if;
case setdaa_s is
when "00" => daabus_s <= alu_inbusa(7 downto 0);
when "01" => daabus_s <= alu_inbusa(7 downto 0) + X"06";
when "10" => daabus_s <= alu_inbusa(7 downto 0) + X"60";
when others => daabus_s <= alu_inbusa(7 downto 0) + X"66";
end case;
end process;
----------------------------------------------------------------------------
-- DAS Instruction 2F
----------------------------------------------------------------------------
-- 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,setdas_s)
begin
if ((alu_inbusa(3 downto 0) > X"9") or (psrreg_s(4)='1')) then
setdas_s(0) <= '1'; -- set AF
else
setdas_s(0) <= '0'; -- clr AF
end if;
if ((alu_inbusa(7 downto 0) > X"9F") or (psrreg_s(0)='1')) then
setdas_s(1) <= '1'; -- set CF
else
setdas_s(1) <= '0'; -- clr CF
end if;
case setdas_s is
when "00" => dasbus_s <= alu_inbusa(7 downto 0);
when "01" => dasbus_s <= alu_inbusa(7 downto 0) - X"06";
when "10" => dasbus_s <= alu_inbusa(7 downto 0) - X"60";
when others => dasbus_s <= alu_inbusa(7 downto 0) - X"66";
end case;
end process;
----------------------------------------------------------------------------
-- AAD Instruction 5D 0A
----------------------------------------------------------------------------
-- AL = (AH * 10) + AL;
-- AH = 0;
-- SF=1 if result is 0 or positive
-- SF=0 if result is negative
-- ZF=1 if result equal to 0
-- ZF=0 if result not equal to 0
-- PF=1 if low byte of result has even number of set bits
-- PF=0 otherwise
-- AF=?
----------------------------------------------------------------------------
process (alu_inbusa,aad1bus_s,aad2bus_s)
begin
aad1bus_s <= ("00" & alu_inbusa(15 downto 8) & '0') + (alu_inbusa(15 downto 8) & "000"); -- AH*2 + AH*8
aad2bus_s <= aad1bus_s + ("000" & alu_inbusa(7 downto 0)); -- + AL
aadbus_s<= "00000000" & aad2bus_s(7 downto 0);
end process;
----------------------------------------------------------------------------
-- ALU Operation
----------------------------------------------------------------------------
process (aluopr,abus_s,bbus_s,outbus_s,psrreg_s,alureg_s,aasbus_s,aaabus_s,daabus_s,sign16a_s,
sign16b_s,sign32a_s,dasbus_s,product_s,divresult_s,alu_temp_s,aadbus_s,quotient_s,remainder_s)
begin
case aluopr is
when ALU_ADD | ALU_ADD_SE | ALU_INC | ALU_POP | ALU_SUB | ALU_SUB_SE | ALU_DEC | ALU_PUSH | ALU_CMP | ALU_CMP_SE |
ALU_CMPS | ALU_ADC | ALU_ADC_SE | ALU_SBB | ALU_SBB_SE | ALU_SCAS | ALU_NEG | ALU_NOT
=> alubus_s <= outbus_s;
when ALU_OR | ALU_OR_SE
=> alubus_s <= abus_s OR bbus_s;
when ALU_AND | ALU_AND_SE | ALU_TEST0 | ALU_TEST1 | ALU_TEST2
=> alubus_s <= abus_s AND bbus_s;
when ALU_XOR | ALU_XOR_SE
=> alubus_s <= abus_s XOR bbus_s;
when ALU_LAHF => alubus_s <= psrreg_s(15 downto 2)&'1'&psrreg_s(0);-- flags onto ALUBUS, note reserved bit1=1
when ALU_MUL | ALU_IMUL
=> alubus_s <= product_s(15 downto 0); -- AX of Multiplier
when ALU_MUL2| ALU_IMUL2
=> alubus_s <= product_s(31 downto 16); -- DX of Multiplier
when ALU_DIV | ALU_IDIV
=> alubus_s <= divresult_s(15 downto 0);-- AX of Divider (quotient)
when ALU_DIV2| ALU_IDIV2
=> alubus_s <= divresult_s(31 downto 16);-- DX of Divider (remainder)
when ALU_SEXT => alubus_s <= sign16a_s; -- Used for CBW Instruction
when ALU_SEXTW => alubus_s <= sign32a_s; -- Used for CWD Instruction
when ALU_AAS => alubus_s <= aasbus_s; -- Used for AAS Instruction
when ALU_AAA => alubus_s <= aaabus_s; -- Used for AAA Instruction
when ALU_DAA => alubus_s <= abus_s(15 downto 8) & daabus_s;-- Used for DAA Instruction
when ALU_DAS => alubus_s <= abus_s(15 downto 8) & dasbus_s;-- Used for DAS Instruction
when ALU_AAD => alubus_s <= aadbus_s; -- Used for AAD Instruction
when ALU_AAM => alubus_s <= quotient_s(7 downto 0) & remainder_s(7 downto 0); -- Used for AAM Instruction
when ALU_ROL | ALU_ROL1 | ALU_ROR | ALU_ROR1 | ALU_RCL | ALU_RCL1 | ALU_RCR | ALU_RCR1 |
ALU_SHL | ALU_SHL1 | ALU_SHR | ALU_SHR1 | ALU_SAR | ALU_SAR1 | ALU_REGL
=> alubus_s <= alureg_s(15 downto 0); -- alu_inbusb to output
when ALU_REGH => alubus_s <= alureg_s(31 downto 16); -- alu_inbusa to output
when ALU_PASSA => alubus_s <= abus_s;
--when ALU_PASSB => alubus_s <= bbus_s;
when ALU_TEMP => alubus_s <= alu_temp_s;
when others => alubus_s <= DONTCARE(15 downto 0);
end case;
end process;
alubus <= alubus_s; -- Connect to entity
----------------------------------------------------------------------------
-- Processor Status Register (Flags)
-- bit Flag
-- 15 Reserved
-- 14 Reserved
-- 13 Reserved Set to 1?
-- 12 Reserved Set to 1?
-- 11 Overflow Flag OF
-- 10 Direction Flag DF
-- 9 Interrupt Flag IF
-- 8 Trace Flag TF
-- 7 Sign Flag SF
-- 6 Zero Flag ZF
-- 5 Reserved
-- 4 Auxiliary Carry AF
-- 3 Reserved
-- 2 Parity Flag PF
-- 1 Reserved Set to 1 ????
-- 0 Carry Flag
----------------------------------------------------------------------------
process (clk, reset)
begin
if reset='1' then
psrreg_s <= "0011000000000010";--(others => '0'); -- Change?
elsif rising_edge(clk) then
if (wrcc='1') then
case aluopr is
when ALU_ADD | ALU_ADD_SE | ALU_ADC | ALU_ADC_SE | ALU_INC =>
OFLAG <= overflow_s;
SFLAG <= signflag_s;
ZFLAG <= zeroflag_s;
AFLAG <= bit4_s;
PFLAG <= parityflag_s;
CFLAG <= cout_s;
when ALU_DEC => -- Same as for ALU_SUB exclusing the CFLAG :-(
OFLAG <= overflow_s;
SFLAG <= signflag_s;
ZFLAG <= zeroflag_s;
AFLAG <= not bit4_s;
PFLAG <= parityflag_s;
when ALU_SUB | ALU_SUB_SE | ALU_SBB | ALU_SBB_SE | ALU_CMP |
ALU_CMP_SE | ALU_CMPS | ALU_SCAS | ALU_NEG =>
OFLAG <= overflow_s;
SFLAG <= signflag_s;
ZFLAG <= zeroflag_s;
AFLAG <= not bit4_s;
PFLAG <= parityflag_s;
CFLAG <= not cout_s;
when ALU_OR | ALU_OR_SE | ALU_AND | ALU_AND_SE | ALU_XOR | ALU_XOR_SE | ALU_TEST0 | ALU_TEST1 | ALU_TEST2 =>
OFLAG <= '0';
SFLAG <= signflag_s;
ZFLAG <= zeroflag_s;
AFLAG <= '0'; -- None defined, set to 0 to be compatible with debug
PFLAG <= parityflag_s;
CFLAG <= '0';
when ALU_SHL | ALU_SHR | ALU_SAR |
ALU_SHR1 | ALU_SAR1 | ALU_SHL1 =>
OFLAG <= overflow_s;
PFLAG <= parityflag_s;
SFLAG <= signflag_s;
ZFLAG <= zeroflag_s;
CFLAG <= alucout_s;
when ALU_CLC =>
CFLAG <= '0';
when ALU_CMC =>
CFLAG <= not CFLAG;
when ALU_STC =>
CFLAG <= '1';
when ALU_CLD =>
DFLAG <= '0';
when ALU_STD =>
DFLAG <= '1';
when ALU_CLI =>
IFLAG <= '0';
when ALU_STI =>
IFLAG <= '1';
when ALU_POP => -- Note only POPF executes a WRCC command, thus save for other pops
psrreg_s <= alu_inbusa; --or ABUS???-- Write memory operand (MDBUS) to CC register
when ALU_SAHF => -- Write all AH bits (not compatible!)
-- psrreg_s(7 downto 0) <= alu_inbusa(7 downto 0);--alu_inbusa(15 downto 8); -- SAHF only writes bits 7,6,4,2,0
psrreg_s(7 downto 0) <= alu_inbusa(7 downto 6) & '0' & alu_inbusa(4) & '0' &
alu_inbusa(2) & '0' & alu_inbusa(0);-- SAHF only writes bits 7,6,4,2,0
when ALU_AAS =>
AFLAG <= setaas_s; -- set or clear CF/AF flag
CFLAG <= setaas_s;
SFLAG <= '0'; -- **** Undefined, cleared to match debug output!!!!!! *****
when ALU_AAA =>
AFLAG <= setaaa_s; -- set or clear CF/AF flag
CFLAG <= setaaa_s;
when ALU_DAA =>
AFLAG <= setdaa_s(0); -- set or clear CF/AF flag
CFLAG <= setdaa_s(1);
PFLAG <= parityflag_s;
SFLAG <= signflag_s;
ZFLAG <= zeroflag_s;
when ALU_AAD =>
SFLAG <= alubus_s(7); --signflag_s;
PFLAG <= parityflag_s;
ZFLAG <= zeroflag_s;
when ALU_AAM =>
SFLAG <= signflag_s;
PFLAG <= parityflag_s;
ZFLAG <= not(zflaglow_s); -- signflag on AL only
when ALU_DAS =>
AFLAG <= setdas_s(0); -- set or clear CF/AF flag
CFLAG <= setdas_s(1);
PFLAG <= parityflag_s;
SFLAG <= signflag_s;
ZFLAG <= zeroflag_s;
-- Shift Rotate Instructions
when ALU_ROL | ALU_ROR | ALU_RCL | ALU_RCR |
ALU_ROL1 | ALU_RCL1 | ALU_ROR1 | ALU_RCR1 =>
CFLAG <= alucout_s;
OFLAG <= overflow_s;
when ALU_MUL | ALU_MUL2 | ALU_IMUL | ALU_IMUL2 => -- Multiply affects CF&OF only
CFLAG <= overflow_s;
OFLAG <= overflow_s;
when ALU_CLRTIF => -- Clear TF and IF flag
IFLAG <= '0';
TFLAG <= '0';
when others =>
psrreg_s <= psrreg_s;
end case;
end if;
end if;
end process;
ccbus <= psrreg_s; -- Connect to entity
-- Latch Divide by 0 error flag & latched divresult.
-- Requires a MCP from all registers to these endpoint registers!
process (clk, reset)
begin
if reset='1' then
div_err <= '0';
divresult_s <= (others => '0');
elsif rising_edge(clk) then
if done_s='1' then -- Latched pulse generated by serial divider
div_err <= div_err_s; -- Divide Overflow
-- pragma synthesis_off
assert div_err_s='0' report "**** Divide Overflow ***" severity failure;
-- pragma synthesis_on
if wl_s='1' then -- Latched version required?????
divresult_s <= remainder_s & quotient_s;
else
divresult_s <= remainder_s & remainder_s(7 downto 0) & quotient_s(7 downto 0);
end if;
else
div_err <= '0';
end if;
end if;
end process;
end rtl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -