📄 fp_adder.vhd
字号:
library IEEE;use STD.textio.all;use IEEE.std_logic_1164.all;use work.dp32_types.all;PACKAGE fpadd_pkg is constant MNT_LENGTH : INTEGER := 24; -- including hidden "1" bit constant ADDEND_LENGTH : INTEGER := MNT_LENGTH + 4; -- 3 bits for precision, 1 for overflow constant MAX_EXP : INTEGER := 2#11111111#; subtype mnt is bit_vector(MNT_LENGTH - 1 downto 0); subtype addend is bit_vector(ADDEND_LENGTH - 1 downto 0); subtype mantissa is bit_vector((MNT_LENGTH - 1) -1 downto 0); subtype exp is integer; constant dMNT_LENGTH : INTEGER := 53; -- including hidden "1" bit constant dADDEND_LENGTH : INTEGER := dMNT_LENGTH + 4; -- 3 bits for precision, 1 for overflow constant dMAX_EXP : INTEGER := 2#11111111111#; subtype dmnt is bit_vector(dMNT_LENGTH - 1 downto 0); subtype daddend is bit_vector(dADDEND_LENGTH - 1 downto 0); subtype dmantissa is bit_vector((dMNT_LENGTH - 1) -1 downto 0); subtype dexp is integer;END fpadd_pkg;----------------------------------------------------------------USE work.fpadd_pkg.all;use work.dp32_types.all;--LIBRARY std_developerskit;--USE std_developerskit.std_regpak.all;ENTITY fau is port ( phi1, phi2 : in bit; Op1,Op1b,Op2,Op2b : in bit_vector(31 downto 0); R,Rb : out bit_vector (31 downto 0); fsr_in : in bit_32; fsr_out : out bit_32; operation : in bit_4); -- Note: The flags vector is used to indicate special result cases; when the-- case is met, the bit is set to 1, otherwise 0-- Bit 3 --> Zero result-- Bit 2 --> Positive Infinity result-- Bit 1 --> Negative Infinity result-- Bit 0 --> NaN result---- ______________________________-- | sign | exponent | mantissa |-- |______|__________|__________| single-- 1 bit 8 bits 23 bits -- ______________________________-- | sign | exponent | mantissa |-- |______|__________|__________| double-- 1 bit 11 bits 52 bits END fau;----------------------------------------------------------------ARCHITECTURE fau_behavior of fau is constant add : bit_4 :="0000"; constant subtract: bit_4 :="0001"; constant add_d : bit_4 :="0010"; constant subtract_d: bit_4 :="0011"; constant ltf: bit_4 :="0100"; constant ltd: bit_4 :="0101"; constant gtf: bit_4 :="0110"; constant gtd: bit_4 :="0111"; constant lef: bit_4 :="1000"; constant led: bit_4 :="1001"; constant gef: bit_4 :="1010"; constant ged: bit_4 :="1011"; constant eqf: bit_4 :="1100"; constant eqd: bit_4 :="1101"; constant nef: bit_4 :="1110"; constant ned: bit_4 :="1111"; constant rn : bit_vector(1 downto 0) := "00"; constant rz : bit_vector(1 downto 0) := "01"; constant rm : bit_vector(1 downto 0) := "10"; constant rp : bit_vector(1 downto 0) := "11"; -- Bit vector concatenation function.FUNCTION "&" (bv1, bv2 : bit_vector) RETURN bit_vector IS variable result_length : integer := bv1'length + bv2'length; variable bv_out : bit_vector(result_length - 1 downto 0); BEGIN bv_out((bv2'length-1) downto 0) := bv2; bv_out(result_length-1 downto bv2'length) := bv1; RETURN(bv_out); END;FUNCTION bit_complement (b_in : bit) RETURN bit IS variable result : bit; BEGIN IF b_in = '0' THEN result := '1'; ELSE result := '0'; END IF; RETURN(result); END bit_complement;FUNCTION flip_bits (bv_in : bit_vector) RETURN bit_vector IS variable bv_out : bit_vector(bv_in'length - 1 downto 0); BEGIN bv_out := bv_in; FOR i in bv_out'range LOOP bv_out(i) := bit_complement(bv_in(i)); END LOOP; RETURN(bv_out); END flip_bits; PROCEDURE left_shift ( reg_val : inout bit_vector; shift_amt : in natural) is BEGIN FOR i in reg_val'range LOOP IF i >= shift_amt THEN reg_val(i) := reg_val(i - shift_amt); ELSE reg_val(i) := '0'; END IF; END LOOP; END left_shift;PROCEDURE right_shift (reg_val: inout bit_vector; shift_amt: in natural) IS variable i : integer; BEGIN FOR i in reg_val'reverse_range LOOP IF i < (reg_val'length - shift_amt) THEN reg_val(i) := reg_val(i + shift_amt); ELSE reg_val(i) := '0'; END IF; END LOOP; END right_shift; -- Extends the precision by three extra bits. These are the -- guard, round, and sticky bits.PROCEDURE form_extended_operand ( reg_val : in bit_vector; extended_reg : out bit_vector; shift_amt : in natural) is variable sticky : bit; variable i : integer; variable tmp_reg : bit_vector(extended_reg'range); BEGIN sticky := '0'; FOR i in 0 to shift_amt - 3 LOOP IF reg_val(i) = '1' THEN sticky := '1'; END IF; END LOOP; tmp_reg := "0" & reg_val & "000"; right_shift(tmp_reg, shift_amt); extended_reg := tmp_reg; extended_reg(0) := sticky; END form_extended_operand;PROCEDURE swap_bvs ( in1 : inout bit_vector; in2 : inout bit_vector) is variable tmp : bit_vector(in1'range); BEGIN tmp := in1; in1 := in2; in2 := tmp; END swap_bvs; PROCEDURE swap_bits ( in1 : inout bit; in2 : inout bit) is variable tmp : bit; BEGIN tmp := in1; in1 := in2; in2 := tmp; END swap_bits;PROCEDURE swap_ints ( in1 : inout integer; in2 : inout integer) is variable tmp: integer; BEGIN tmp := in1; in1 := in2; in2 := tmp; END swap_ints; -- Operates on unsigned numbers. -- Shifts the number so that the left-most '1' becomes the most significant -- bit.PROCEDURE normalize ( prelim_result : inout bit_vector; exponent : inout exp ) is -- Shift prelim_result to left until normalized. Normalized when the value -- to the left of the decimal point is 1. -- Adjust the exponent value accordingly. variable i, count_from_left : integer; variable shift_out : bit; variable found_one : boolean := false; BEGIN count_from_left := 0; FOR i in prelim_result'left downto prelim_result'right LOOP IF (not found_one) and (prelim_result(i) = '0') THEN count_from_left := count_from_left + 1; ELSE found_one := true; END IF; END LOOP; -- $BSYNTH(definite_unroll); IF (count_from_left > 0) THEN left_shift(prelim_result, count_from_left); IF (exponent - count_from_left >= 0) THEN exponent := exponent - count_from_left; END IF; END IF; END normalize; -- Note: This assumes that the two input bitvectors are the same lengthPROCEDURE bv_add ( result : out bit_vector; in1 : in bit_vector; in2 : in bit_vector; overflow : out boolean) is variable i : integer; variable carry_in : bit := '0'; variable carry_out : bit; BEGIN FOR i in in1'reverse_range LOOP IF carry_in = '0' THEN IF in1(i) = in2(i) THEN result(i) := '0'; ELSE result(i) := '1'; END IF; carry_out := in1(i) AND in2(i); ELSE IF in1(i) = in2(i) THEN result(i) := '1'; ELSE result(i) := '0'; END IF; carry_out := in1(i) OR in2(i); END IF; -- Note, the overflow check below should be performed only for the -- highest order bit. However, the behavior was easier to write -- this way, and the outcome is the same. If we were synthesizing -- the adder itself, we would have to watch out for this type of -- description. IF carry_out = carry_in THEN overflow := false; ELSE overflow := true; END IF; carry_in := carry_out; END LOOP; END bv_add;FUNCTION twos_complement(bv_in: in bit_vector) RETURN bit_vector IS variable bv_out : bit_vector(bv_in'length-1 downto 0); variable i : integer; variable carry : boolean := true; BEGIN bv_out := NOT(bv_in); FOR i IN bv_in'reverse_range LOOP IF carry THEN IF bv_out(i) = '0' THEN bv_out(i) := '1'; carry := false; ELSE bv_out(i) := '0'; END IF; END IF; END LOOP; RETURN(bv_out); END twos_complement; -- IEEE 754 standard, default rounding mode, round to nearest/even PROCEDURE round_result ( sign: in bit; prelim_result : inout bit_vector; exp_result : inout exp; round_mode : in bit_2) is variable r : bit; -- round bit variable s : bit; -- sticky bit variable i : integer; variable carry: boolean := true; BEGIN-- ASSERT false REPORT vector_to_string(round_mode) SEVERITY warning; case round_mode is when rn=> IF (prelim_result(1)='1') then if((prelim_result(0)='1') or (prelim_result(2)='1')) then if prelim_result((ADDEND_LENGTH - 2) - 1 downto 3) = "11111111111111111111111" then --overflow prelim_result((ADDEND_LENGTH -2) -1 downto 3) := "00000000000000000000000"; exp_result := exp_result + 1; else carry:=true; FOR i IN 3 to ((ADDEND_LENGTH-2)-1) LOOP IF carry THEN IF prelim_result(i) = '0' THEN prelim_result(i) := '1'; carry := false; ELSE prelim_result(i) := '0'; END IF; END IF; END LOOP; end if; end if; end if; when rz=> when rm=> if(sign='1' and (prelim_result(1)='1' or prelim_result(0)='1')) then --subtract one, but actually add it since mant is negative if prelim_result((ADDEND_LENGTH - 2) - 1 downto 3) = "11111111111111111111111" then --overflow prelim_result((ADDEND_LENGTH -2) -1 downto 3) := "00000000000000000000000"; exp_result := exp_result + 1; else carry:=true; FOR i IN 3 to ((ADDEND_LENGTH-2)-1) LOOP IF carry THEN IF prelim_result(i) = '0' THEN prelim_result(i) := '1'; carry := false; ELSE prelim_result(i) := '0'; END IF; END IF; END LOOP; end if; else --nothing to do, truncation end if; when rp=> ASSERT false REPORT vector_to_string(prelim_result) SEVERITY warning; if(sign='0' and( prelim_result(1)='1' or prelim_result(0)='1')) then -- add one if prelim_result((ADDEND_LENGTH - 2) - 1 downto 3) = "11111111111111111111111" then --overflow prelim_result((ADDEND_LENGTH -2) -1 downto 3) := "00000000000000000000000"; exp_result := exp_result + 1; else carry:=true; FOR i IN 3 to ((ADDEND_LENGTH-2)-1) LOOP IF carry THEN IF prelim_result(i) = '0' THEN prelim_result(i) := '1'; carry := false; ELSE prelim_result(i) := '0'; END IF; END IF; END LOOP; end if; else --nothing to do, truncation end if;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -