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

📄 alu.vhd

📁 X8086的VHDL源码
💻 VHD
📖 第 1 页 / 共 2 页
字号:
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 + -