-- Updated 23 May 1997 by N.M.Duc -- Uncompletely tested. library IEEE; use IEEE.std_logic_1164.all; --use IEEE.std_logic_arith.all; -- This statement is needed when compile with Cadence tools. use IEEE.std_logic_unsigned.all; -- This statement is needed when compile with Peak tools. entity ADD is generic ( EXP_BIT : integer :=8; MAN_BIT : integer :=23 ); -- EXP_BIT and MAN_BIT is the number of bits of exponent -- and mantissa port( A,B : in std_logic_vector(EXP_BIT+MAN_BIT downto 0); C : out std_logic_vector(EXP_BIT+MAN_BIT downto 0) ); -- A and B are input floating numbers, C is their sum. end ADD; architecture BEHAVIOR of ADD is constant EXP_ZERO : std_logic_vector(EXP_BIT-1 downto 0) := "00000000"; constant EXP_MAX : std_logic_vector(EXP_BIT-1 downto 0) := "11111111"; constant MAN_ZERO : std_logic_vector(MAN_BIT-1 downto 0) := "00000000000000000000000"; begin AdderBody : process(A,B) variable index : integer range 0 to MAN_BIT+2; variable S_a,S_b,S_c : std_logic; variable E_a,E_b,E_c : std_logic_vector(EXP_BIT-1 downto 0); variable E_buf : std_logic_vector(EXP_BIT+1 downto 0); -- use 2 extra bits for checking overflow and underflow of exponent variable E_dif : std_logic_vector(EXP_BIT-1 downto 0); variable M_a,M_b,M_c : std_logic_vector(MAN_BIT-1 downto 0); variable M_big,M_small : std_logic_vector(MAN_BIT-1 downto 0); variable M1,M2,M3 : std_logic_vector(MAN_BIT+1 downto 0); --use 1 extra bit for checking overflow of mantissa. Underflow will not occur with --the algorithm used here. begin -- first, get exponents,sign bits an mantissas. S_a := A(EXP_BIT+MAN_BIT); S_b := B(EXP_BIT+MAN_BIT); E_a := A(EXP_BIT+MAN_BIT-1 downto MAN_BIT); E_b := B(EXP_BIT+MAN_BIT-1 downto MAN_BIT); M_a := A(MAN_BIT-1 downto 0); M_b := B(MAN_BIT-1 downto 0); -- Put the bigger mantissa in M_big, the smaller one in M_small. The result C will have -- the sign of the input number which have the bigger mattissa. if(E_a = E_b) then E_dif := EXP_ZERO; E_buf := "00" & E_a; if(M_a > M_b) then M_big := M_a; M_small := M_b; S_c := S_a; else M_big := M_b; M_small := M_a; S_c := S_b; end if; elsif(E_a > E_b) then M_big := M_a; M_small := M_b; E_dif := E_a - E_b; E_buf := "00" & E_a; S_c := S_a; else M_big := M_b; M_small := M_a; E_dif := E_b - E_a; E_buf := "00" & E_b; S_c := S_b; end if; M1 := "01" & M_big; -- right-shift M_2( the smaller mantissa) E_dif bits. case E_dif is when "00000000" => M2 := "01" & M_small; when "00000001" => M2 := "001" & M_small(MAN_BIT-1 downto 1); when "00000010" => M2 := "0001" & M_small(MAN_BIT-1 downto 2); when "00000011" => M2 := "00001" & M_small(MAN_BIT-1 downto 3); when "00000100" => M2 := "000001" & M_small(MAN_BIT-1 downto 4); when "00000101" => M2 := "0000001" & M_small(MAN_BIT-1 downto 5); when "00000110" => M2 := "00000001" & M_small(MAN_BIT-1 downto 6); when "00000111" => M2 := "000000001" & M_small(MAN_BIT-1 downto 7); when "00001000" => M2 := "0000000001" & M_small(MAN_BIT-1 downto 8); when "00001001" => M2 := "00000000001" & M_small(MAN_BIT-1 downto 9); when "00001010" => M2 := "000000000001" & M_small(MAN_BIT-1 downto 10); when "00001011" => M2 := "0000000000001" & M_small(MAN_BIT-1 downto 11); when "00001100" => M2 := "00000000000001" & M_small(MAN_BIT-1 downto 12); when "00001101" => M2 := "000000000000001" & M_small(MAN_BIT-1 downto 13); when "00001110" => M2 := "0000000000000001" & M_small(MAN_BIT-1 downto 14); when "00001111" => M2 := "00000000000000001" & M_small(MAN_BIT-1 downto 15); when "00010000" => M2 := "000000000000000001" & M_small(MAN_BIT-1 downto 16); when "00010001" => M2 := "0000000000000000001" & M_small(MAN_BIT-1 downto 17); when "00010010" => M2 := "00000000000000000001" & M_small(MAN_BIT-1 downto 18); when "00010011" => M2 := "000000000000000000001" & M_small(MAN_BIT-1 downto 19); when "00010100" => M2 := "0000000000000000000001" & M_small(MAN_BIT-1 downto 20); when "00010101" => M2 := "00000000000000000000001" & M_small(MAN_BIT-1 downto 21); when "00010110" => M2 := "000000000000000000000001" & M_small(MAN_BIT-1); when "00010111" => M2 := MAN_ZERO & "01"; --"0000000000000000000000001"; when others => M2 := MAN_ZERO & "00"; end case; if(S_a=S_b) then M3 := M1 + M2; -- add matissas when A and B have the same sign else M3 := M1 - M2; -- substract mantissas when A and B have different signs end if; -- normalize M3 index := 0; M_c := MAN_ZERO; while (M3(MAN_BIT+1-index)='0') loop index := index+1; exit when (index = MAN_BIT+2); end loop; -- index is the number of zeros stand continuously -- on the left of M3 if( index=0 ) then -- overflow E_buf := E_buf+1; M_c := M3(MAN_BIT downto 1); else -- normal case. L-shift mantissa index-1 bits E_buf := E_buf-index+1; if index <= MAN_BIT then M_c(MAN_BIT-1 downto index-1) := M3(MAN_BIT-index downto 0); end if; if index = MAN_BIT+2 then E_buf := "00" & EXP_ZERO; -- set special value end if; end if; -- check for exponent E_buf's overflow and underflow if(E_buf(EXP_BIT+1)='1') then --underflow E_c := EXP_ZERO; M_c := MAN_ZERO; --set special value ( zero ) elsif E_buf(EXP_BIT)='1' then --overflow E_c := EXP_MAX; --set special value (infinity) else --in range E_c := E_buf(EXP_BIT-1 downto 0); end if; --compose result C from S_c,E_c,M_c; C <= S_c & E_c & M_c; end process; end BEHAVIOR;