123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- 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;
|