📄 alu.vhd
字号:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use WORK.UPAC.ALL;
entity ALU is
port( I_TR1PLS : in std_logic_vector(15 downto 0);
I_TR2DIV : in std_logic_vector(15 downto 0);
I_ALUCS : in std_logic_vector( 3 downto 0);
I_BW : in std_logic;
I_EA : in std_logic; --for b_w
I_MULHL : in std_logic;
I_USECARRY : in std_logic; --for use carry(<='1')
I_ADJUST : in std_logic_vector( 1 downto 0); --for ADJUST(AAA,DAA,AAS,DAS)
I_BORROW : in std_logic; --for div
I_CFR : in std_logic;
I_AFR : in std_logic;
I_DIVF : in std_logic; --for div
O_QUOF : out std_logic; --for div(quotient set)
O_STFR : out std_logic_vector( 5 downto 0); --status flag
O_ALUDATA_V : out std_logic_vector(15 downto 0); --for test
O_ALUDATA : out std_logic_vector(15 downto 0)
);
end ALU;
architecture RTL of ALU is
signal alu_out : std_logic_vector(15 downto 0);
signal mul_out : std_logic_vector(31 downto 0);
signal sub : std_logic_vector(16 downto 0);
signal b_w : std_logic;
signal out_tmp : std_logic_vector(15 downto 0); --for adjust
signal af_cs : std_logic; --set af for adjust
signal cf_cs : std_logic; --set cf for adjust
begin
O_ALUDATA_V <= alu_out; --for test
O_ALUDATA <= alu_out ;--when '1'
b_w <= I_BW or I_EA; --for ea
process (I_TR1PLS,I_TR2DIV,alu_out,mul_out,I_ALUCS,b_w,I_MULHL,I_AFR,I_CFR,sub,I_USECARRY,out_tmp,
I_ADJUST,I_TR1PLS,I_TR2DIV)
begin
case I_ALUCS is
--SUB--####################################################################################################
when GEN =>
case I_ADJUST is
when "01" => --AAS (ASCII ADJUST for SUBTRACTION)
case I_TR1PLS(3 downto 0) is
when "1010" | "1011" | "1100" | "1101" | "1110" | "1111" => --when AX>9
alu_out <= (I_TR1PLS - "0000000100000110") and "1111111100001111";
when others =>
if(I_AFR = '1')then --when AF=1
alu_out <= (I_TR1PLS - "0000000100000110") and "1111111100001111";
else
alu_out <= I_TR1PLS;
end if;
end case;
when "10" => --DAS (DECIMAL ADJUST for SUBTRACTION)
case out_tmp(7 downto 4) is
when "1010" | "1011" | "1100" | "1101" | "1110" | "1111" => --when AH>9
alu_out <= out_tmp - "0000000001100000"; --adjust(+60H)
when others =>
if(I_CFR = '1')then
alu_out <= out_tmp - "0000000001100000"; --adjust(+60H)
else
alu_out <= out_tmp;
end if;
end case;
when others =>
alu_out <= sub(15 downto 0);
end case;
--ADD--#######################################################################################
when KA =>
case I_ADJUST is
when "01" => --AAA (ASCII ADJUST for ADDITION)
case I_TR1PLS(3 downto 0) is
when "1010" | "1011" | "1100" | "1101" | "1110" | "1111" => --when AX>9
alu_out <= (I_TR1PLS + "0000000100000110") and "1111111100001111";
when others =>
if(I_AFR = '1')then
alu_out <= (I_TR1PLS + "0000000100000110") and "1111111100001111";
else
alu_out <= I_TR1PLS;
end if;
end case;
when "10" => --DAA (DECIMAL ADJUST for ADDITION)
case out_tmp(7 downto 4) is
when "1010" | "1011" | "1100" | "1101" | "1110" | "1111" => --when AH>9
alu_out <= out_tmp + "0000000001100000"; --adjust(+60H)
when others =>
if(I_CFR = '1')then
alu_out <= out_tmp + "0000000001100000"; --adjust(+60H)
else
alu_out <= out_tmp;
end if;
end case;
when others =>
alu_out <= I_TR1PLS+I_TR2DIV+("000000000000000"&(I_USECARRY and I_CFR)); --add
end case;
--MUL(small portion of adjust calculaation)--#############################################################
when JOU =>
if (I_MULHL = '0') then
alu_out <= mul_out(31 downto 16);
else
alu_out <= mul_out(15 downto 0);
end if;
--NOT--##################################################################################################
when NO => --NOT
alu_out <= not I_TR1PLS;
--AND--##################################################################################################
when KATU =>
alu_out <= I_TR1PLS and I_TR2DIV;
--OR--##################################################################################################
when MATA =>
alu_out <= I_TR1PLS or I_TR2DIV; --or
--XOR--################################################################################################
when HAI =>
alu_out <= I_TR1PLS xor I_TR2DIV; --xor
--SHIFT ARITHMETIC LEFT : SHIFT LOGICAL LEFT--####################################################
when HSIF =>
alu_out <= I_TR1PLS(14 downto 0) & '0';
--SHIFT LOGICAL RIGHT--############################################################################
when RMSIF =>
if (b_w = '1') then
alu_out <= '0'&I_TR1PLS(15 downto 1);
elsif (b_w = '0') then
alu_out <= "000000000"&I_TR1PLS(7 downto 1);
end if;
--SHIFT ARITHMETIC RIGHT--###############################################################
when SMSIF =>
if (b_w = '1') then
alu_out <= I_TR1PLS(15)&I_TR1PLS(15 downto 1);
elsif (b_w = '0') then
alu_out <= "00000000"&I_TR1PLS(7)&I_TR1PLS(7 downto 1);
end if;
--ROTATE LEFT--###############################################################################
when HRO =>
if (b_w = '1') then
alu_out <= I_TR1PLS(14 downto 0)&I_TR1PLS(15);
elsif (b_w = '0') then
alu_out <= "00000000"&I_TR1PLS(6 downto 0)&I_TR1PLS(7);
end if;
--ROTATE RIGHT--###################################################################################
when MRO =>
if (b_w = '1') then
alu_out <= I_TR1PLS(0)&I_TR1PLS(15 downto 1);
elsif (b_w = '0') then
alu_out <= "00000000"&I_TR1PLS(0)&I_TR1PLS(7 downto 1);
end if;
--ROTATE through CARRY LEFT--####################################################################
when CHRO =>
if (b_w = '1') then
alu_out <= I_TR1PLS(14 downto 0)&I_CFR;
elsif (b_w = '0') then
alu_out <= "00000000"&I_TR1PLS(6 downto 0)&I_CFR;
end if;
--ROTATE through CARRY RIGHT--##################################################################
when CMRO =>
if (b_w = '1') then
alu_out <= I_CFR&I_TR1PLS(15 downto 1);
elsif (b_w = '0') then
alu_out <= "00000000"&I_CFR&I_TR1PLS(7 downto 1);
end if;
--NEG--#############################################################################################
when ALUNEG =>
if (I_ADJUST = "11") then
if (I_MULHL = '1') then
alu_out <= mul_out(15 downto 0);
else
alu_out <= mul_out(31 downto 16);
end if;
else
if(b_w = '0')then
alu_out <= "00000000"&(not I_TR1PLS(7 downto 0)) + "0000000000000001";
else
alu_out <= (not I_TR1PLS) + "0000000000000001"; --twos complement conversion
end if;
end if;
when others =>
alu_out <= "0000000000000000";
end case;
end process;
STATE_FREG_0_CFR_carry_frag :
process (I_ALUCS,I_ADJUST,I_TR1PLS,sub,alu_out,I_TR1PLS,I_TR2DIV,mul_out,b_w,cf_cs)
begin
case I_ALUCS is
when GEN =>
case I_ADJUST is
when "01" => --ASCII ADJUST (AF,CF set)
case I_TR1PLS(3 downto 0) is
when "1010" | "1011" | "1100" | "1101" | "1110" | "1111" => --when AX>9
O_STFR(0) <= '1'; --CF
when others =>
O_STFR(0) <= '0'; --CF
end case;
when "10" =>
if(cf_cs = '1')then
O_STFR(0) <= '1'; --CF
else
O_STFR(0) <= '0';
end if;
when others =>
O_STFR(0) <= sub(16); --borrow
end case;
when KA =>
case I_ADJUST is
when "01" => --ASCII ADJUST (AF,CF set)
case I_TR1PLS(3 downto 0) is
when "1010" | "1011" | "1100" | "1101" | "1110" | "1111" => --when AX>9
O_STFR(0) <= '1'; --CF
when others =>
O_STFR(0) <= '0'; --CF
end case;
when "10" =>
if(cf_cs = '1')then
O_STFR(0) <= '1'; --CF
else
O_STFR(0) <= '0';
end if;
when others =>
if (b_w = '1') then
O_STFR(0) <= (I_TR1PLS(15) or I_TR2DIV(15)) and (not alu_out(15));
else
O_STFR(0) <= (I_TR1PLS(7) or I_TR2DIV(7)) and (not alu_out(7));
end if;
end case;
when JOU =>
if(b_w = '0') then ---------------FR setting--
case mul_out(15 downto 8) is --
when "00000000" =>
O_STFR(0) <= '0'; --cf --
when others =>
O_STFR(0) <= '1'; --cf --
end case; --
else --
case mul_out(31 downto 16) is --
when "0000000000000000" =>
O_STFR(0) <= '0'; --cf --
when others =>
O_STFR(0) <= '1'; --cf --
end case; --
end if;
when NO => --NOT
if (b_w = '1') then
O_STFR(0) <= (I_TR1PLS(15) or I_TR2DIV(15)) and (not alu_out(15));
else
O_STFR(0) <= (I_TR1PLS( 7) or I_TR2DIV( 7)) and (not alu_out( 7));
end if;
when KATU =>
if (b_w = '1') then
O_STFR(0) <= (I_TR1PLS(15) or I_TR2DIV(15)) and (not alu_out(15));
else
O_STFR(0) <= (I_TR1PLS( 7) or I_TR2DIV( 7)) and (not alu_out( 7));
end if;
when MATA =>
if (b_w = '1') then
O_STFR(0) <= (I_TR1PLS(15) or I_TR2DIV(15)) and (not alu_out(15));
else
O_STFR(0) <= (I_TR1PLS( 7) or I_TR2DIV( 7)) and (not alu_out( 7));
end if;
when HAI =>
if (b_w = '1') then
O_STFR(0) <= (I_TR1PLS(15) or I_TR2DIV(15)) and (not alu_out(15));
else
O_STFR(0) <= (I_TR1PLS( 7) or I_TR2DIV( 7)) and (not alu_out( 7));
end if;
when HSIF =>
if (b_w = '1') then
O_STFR(0) <= I_TR1PLS(15); --shl,sal
else
O_STFR(0) <= I_TR1PLS( 7);
end if;
when RMSIF =>
O_STFR(0) <= I_TR1PLS(0); --shr
when SMSIF =>
O_STFR(0) <= I_TR1PLS(0); --sar
when HRO =>
if (b_w = '1') then
O_STFR(0) <= I_TR1PLS(15); --rol
else
O_STFR(0) <= I_TR1PLS(7);
end if;
when MRO =>
O_STFR(0) <= I_TR1PLS(0); --ror
when CHRO =>
if (b_w = '1') then
O_STFR(0) <= I_TR1PLS(15); --rcl
else
O_STFR(0) <= I_TR1PLS(7);
end if;
when CMRO =>
O_STFR(0) <= I_TR1PLS(0);
when ALUNEG =>
if (I_ADJUST = "11") then
if (I_TR1PLS = "1111111111111111") then --cf check for IMUL
O_STFR(0) <= '0'; --zero
else
O_STFR(0) <= '1'; --nomal
end if;
else
if (I_TR1PLS = "0000000000000000") then --cf check for NEG
O_STFR(0) <= '0'; --zero
else
O_STFR(0) <= '1'; --nomal
end if;
end if;
when others =>
O_STFR(0) <= '0';
end case;
end process;
STATE_FREG_1_PFR_parity_frag :
process(b_w,alu_out)
begin
if (b_w = '0') then
O_STFR(1) <= not (alu_out(7) xor alu_out(6) xor alu_out(5) xor alu_out(4) xor alu_out(3) xor alu_out(2)
xor alu_out(1) xor alu_out(0));
else
O_STFR(1) <= not ((((alu_out(15) xor alu_out(14)) xor(alu_out(13) xor alu_out(12))) xor ((alu_out(11)
xor alu_out(10)) xor (alu_out(9) xor alu_out(8))))xor (((alu_out(7) xor alu_out(6))
xor (alu_out(5) xor alu_out(4))) xor ((alu_out(3) xor alu_out(2)) xor (alu_out(1)
xor alu_out(0)))));
end if;
end process;
STATE_FREG_2_AFR_auxility_carry_frag :
process(I_ADJUST,I_TR1PLS,af_cs,I_TR1PLS,I_TR2DIV,alu_out,I_ALUCS)
begin
if (I_ALUCS = ALUNEG)then
O_STFR(2) <= I_TR1PLS(3) and (not alu_out(3)); --af check
else
case I_ADJUST is
when "01" => --ASCII ADJUST (AF,CF set)
case I_TR1PLS(3 downto 0) is
when "1010" | "1011" | "1100" | "1101" | "1110" | "1111" => --when AX>9
O_STFR(2) <= '1'; --AF
when others =>
O_STFR(2) <= '0'; --AF
end case;
when "10" =>
if (af_cs = '1') then --decimal adjust (AF,CF set)
O_STFR(2) <= '1'; --AF
else
O_STFR(2) <= '0';
end if;
when others =>
O_STFR(2) <= (I_TR1PLS(3) or I_TR2DIV(3)) and (not alu_out(3)); --af check
end case;
end if;
end process;
STATE_FREG_3_ZFR_zero_frag :
process(b_w,alu_out)
begin
if (b_w ='0') then
if(alu_out(7 downto 0) = "00000000") then
O_STFR(3) <= '1';
else
O_STFR(3) <= '0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -