----------------------------------------------------------------- -- BEHAVIORAL REFERENCE MODEL FOR FPA ----------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use WORK.fpa_support.all; entity fpa is PORT (A,B : IN std_logic_vector (31 downto 0); latch, drive: IN std_ulogic; C : OUT std_logic_vector (31 downto 0)); end fpa; ---------------------------------------------------------------- architecture behavioral of fpa is signal Aint,Bint,Cint : std_logic_vector (31 downto 0); signal srexp : std_logic_vector (7 downto 0); signal saman,sbman,srman : std_logic_vector (23 downto 0); signal s_mul_res : std_logic_vector (47 downto 0); signal s_res_exp_int : integer; BEGIN latch_in : PROCESS BEGIN wait until rising_edge(latch); Aint <= A; Bint <= B; END PROCESS latch_in; floating_pt_add : PROCESS (Aint,Bint) variable asign,bsign,rsign : std_logic; variable aexp,bexp,rexp : std_logic_vector (7 downto 0); variable aman,bman,rman : std_logic_vector (23 downto 0); variable a_arg,b_arg : std_logic_vector (24 downto 0); variable res_build : std_logic_vector (31 downto 0); variable add_res : std_logic_vector (47 downto 0); variable res_exp_int : integer; variable aexp_int, bexp_int,shift_dist : integer; BEGIN asign := Aint(31); bsign := Bint(31); rsign := asign; aexp := Aint(30 downto 23); bexp := Bint(30 downto 23); -- handle NaNs by putting them into a format like normalized num -- or put into normalized format IF ((aexp = exp_zero) and (Aint(22 downto 0) /= man_zero(22 downto 0))) THEN aman := Aint(22 downto 0) & '0'; ELSIF (aexp /= exp_zero AND aexp /= exp_ones) THEN aman := '1' & Aint(22 downto 0); ELSE aman := '0' & Aint(22 downto 0); END IF; IF ((bexp = exp_zero) and (Bint(22 downto 0) /= man_zero(22 downto 0))) THEN bman := Bint(22 downto 0) & '0'; ELSIF (bexp /= exp_zero AND bexp /= exp_ones) THEN bman := '1' & Bint(22 downto 0); ELSE bman := '0'&Bint(22 downto 0); END IF; -- handle special case of result a NaN IF((aexp = exp_ones) and (not (aman = man_zero))) or -- A a NaN ((bexp = exp_ones) and (not (bman = man_zero))) or -- B a NaN ((aexp = exp_ones) and (aman = man_zero) and -- +inif + -inif (bexp = exp_ones) and (bman = man_zero) and (asign /= bsign)) THEN Cint <= NAN; -- handle special case of A input Inifinity ELSIF((aexp = exp_ones) and (aman = man_zero)) THEN Cint <= Aint; -- handle special case of B input Inifinity ELSIF((bexp = exp_ones) and (bman = man_zero)) THEN Cint <= Bint; -- handle special case of A equal +/- 0 ELSIF((aexp = exp_zero) and (aman = man_zero)) THEN Cint <= Bint; -- handle special case of B equal +/- 0 ELSIF((bexp = exp_zero) and (bman = man_zero)) THEN Cint <= Aint; ELSE -- add the numbers -- make a the large of the two numbers IF ((bexp > aexp) OR ((bexp = aexp) AND (bman > aman))) THEN -- b is the larger number so exchange them rsign := bsign; bsign := asign; asign := rsign; rexp := bexp; bexp := aexp; aexp := rexp; rman := bman; bman := aman; aman := rman; END IF; -- a now holds the larger of the two numbers -- determine the exponent difference by converting the -- exponents to integer aexp_int := std8_2_int(aexp); bexp_int := std8_2_int(bexp); shift_dist := aexp_int - bexp_int; -- shift the b mantissa by shift distance IF (shift_dist>0) THEN FOR I in 1 to shift_dist LOOP bman := '0' & bman(23 downto 1); END LOOP; END IF; -- add the mantissas if the signs are the same or subtract if diff. a_arg := '0' & aman; b_arg := '0' & bman; IF (asign = bsign) THEN -- add std_logic_add(b_arg,a_arg); -- result will be in a_arg ELSE b_arg := not b_arg; -- ones complement of B std_logic_add(const_one,b_arg); std_logic_add(b_arg,a_arg); -- result in a_arg END IF; -- now normalize the result of the add normalize (aexp_int,a_arg,rexp,rman); IF (rman = man_zero) THEN -- zero result Cint <= rsign & exp_zero & man_zero(22 downto 0); ELSIF (rexp = exp_zero) THEN -- denorm result Cint <= rsign & rexp & rman(23 downto 1); ELSE CINT <= rsign & rexp & rman(22 downto 0); END IF; END IF; END PROCESS floating_pt_add; drive_out : PROCESS (drive) BEGIN IF drive = '0' THEN C <= Cint; ELSE C <= HighZ; END IF; END PROCESS drive_out; END behavioral;