Initial commit
This commit is contained in:
commit
f0ce9c44cc
43 files changed
+1815
No files matched your search
@@ -0,0 +1,133 @@
|
||||
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;
|
||||
Reference in new issue
Block a user