library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity float_add is port(A : in std_logic_vector(31 downto 0); B : in std_logic_vector(31 downto 0); clk : in std_logic; reset : in std_logic; start : in std_logic; done : out std_logic; sum : out std_logic_vector(31 downto 0) ); end float_add; architecture mixed of float_add is type ST is (WAIT_STATE, ALIGN_STATE, ADDITION_STATE, NORMALIZE_STATE, OUTPUT_STATE); signal state : ST := WAIT_STATE; ---Internal Signals latched from the inputs signal A_mantissa, B_mantissa : std_logic_vector (24 downto 0); signal A_exp, B_exp : std_logic_vector (8 downto 0); signal A_sgn, B_sgn : std_logic; --Internal signals for Output signal sum_exp: std_logic_vector (8 downto 0); signal sum_mantissa : std_logic_vector (24 downto 0); signal sum_sgn : std_logic; begin Control_Unit : process (clk, reset) is variable diff : signed(8 downto 0); begin if(reset = '1') then state <= WAIT_STATE; --start in wait state done <= '0'; elsif rising_edge(clk) then case state is when WAIT_STATE => if (start = '1') then --wait till start request startes high A_sgn <= A(31); A_exp <= '0' & A(30 downto 23); --One bit is added for signed subtraction A_mantissa <= "01" & A(22 downto 0); --Two bits are added extra, one for leading 1 and other one for storing carry B_sgn <= B(31); B_exp <= '0' & B(30 downto 23); B_mantissa <= "01" & B(22 downto 0); state <= ALIGN_STATE; else state <= WAIT_STATE; end if; when ALIGN_STATE => --Compare exponent and align it --If any num is greater by 2**24, we skip the addition. if unsigned(A_exp) > unsigned(B_exp) then --B needs downshifting diff := signed(A_exp) - signed(B_exp); --Small Alu if diff > 23 then sum_mantissa <= A_mantissa; --B insignificant relative to A sum_exp <= A_exp; sum_sgn <= A_sgn; state <= OUTPUT_STATE; --start latch A as output else --downshift B to equilabrate B_exp to A_exp sum_exp <= A_exp; B_mantissa(24-to_integer(diff) downto 0) <= B_mantissa(24 downto to_integer(diff)); B_mantissa(24 downto 25-to_integer(diff)) <= (others => '0'); state <= ADDITION_STATE; end if; elsif unsigned(A_exp) < unsigned(B_exp) then --A_exp < B_exp. A needs downshifting diff := signed(B_exp) - signed(A_exp); -- Small Alu if diff > 23 then sum_mantissa <= B_mantissa; --A insignificant relative to B sum_sgn <= B_sgn; sum_exp <= B_exp; state <= OUTPUT_STATE; --start latch B as output else --downshift A to equilabrate A_exp to B_exp sum_exp <= B_exp; A_mantissa(24-to_integer(diff) downto 0) <= A_mantissa(24 downto to_integer(diff)); A_mantissa(24 downto 25-to_integer(diff)) <= (others => '0'); state <= ADDITION_STATE; end if; else -- Both exponent is equal. No need to mantissa shift sum_exp <= A_exp; state <= ADDITION_STATE; end if; when ADDITION_STATE => --Mantissa addition state <= NORMALIZE_STATE; if (A_sgn xor B_sgn) = '0' then --signs are the same. Just add them sum_mantissa <= std_logic_vector((unsigned(A_mantissa) + unsigned(B_mantissa))); --Big Alu sum_sgn <= A_sgn; --both nums have same sign --Else subtract smaller from larger and use sign of larger elsif unsigned(A_mantissa) >= unsigned(B_mantissa) then sum_mantissa <= std_logic_vector((unsigned(A_mantissa) - unsigned(B_mantissa))); --Big Alu sum_sgn <= A_sgn; else sum_mantissa <= std_logic_vector((unsigned(B_mantissa) - unsigned(A_mantissa))); --Big Alu sum_sgn <= B_sgn; end if; when NORMALIZE_STATE => --Normalization. if unsigned(sum_mantissa) = TO_UNSIGNED(0, 25) then --The sum is 0 sum_mantissa <= (others => '0'); sum_exp <= (others => '0'); state <= OUTPUT_STATE; elsif(sum_mantissa(24) = '1') then --If sum overflowed we downshift and are done. sum_mantissa <= '0' & sum_mantissa(24 downto 1); --shift the 1 down sum_exp <= std_logic_vector((unsigned(sum_exp)+ 1)); state <= OUTPUT_STATE; elsif(sum_mantissa(23) = '0') then --in this case we need to upshift --This iterates the normalization shifts, thus can take many clocks. sum_mantissa <= sum_mantissa(23 downto 0) & '0'; sum_exp <= std_logic_vector((unsigned(sum_exp)-1)); state<= NORMALIZE_STATE; --keep shifting till leading 1 appears else state <= OUTPUT_STATE; --leading 1 already there. Latch output end if; when OUTPUT_STATE => sum(22 downto 0) <= sum_mantissa(22 downto 0); sum(30 downto 23) <= sum_exp(7 downto 0); sum(31) <= sum_sgn; done <= '1'; -- signal done if (start = '0') then -- stay in the state till request ends i.e start is low done <= '0'; state <= WAIT_STATE; end if; when others => state <= WAIT_STATE; --Just in case. end case; end if; end process; end mixed;