📄 fp_adder.vhd
字号:
end case; RETURN; END round_result;-- IEEE 754 standard, default rounding mode, round to nearest/even PROCEDURE dround_result ( sign : in bit; prelim_result : inout bit_vector; exp_result : inout dexp; round_mode : in bit_2) is variable r : bit; -- round bit variable s : bit; -- sticky bit variable i : integer; variable carry: boolean := true; BEGIN 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((dADDEND_LENGTH - 2) - 1 downto 3) = "1111111111111111111111111111111111111111111111111111" then --overflow prelim_result((dADDEND_LENGTH -2) -1 downto 3) := "0000000000000000000000000000000000000000000000000000"; exp_result := exp_result + 1; else carry:=true; FOR i IN 3 to ((dADDEND_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=> --dont round, just truncate 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((dADDEND_LENGTH - 2) - 1 downto 3) = "1111111111111111111111111111111111111111111111111111" then --overflow prelim_result((dADDEND_LENGTH -2) -1 downto 3) := "0000000000000000000000000000000000000000000000000000"; exp_result := exp_result + 1; else carry:=true; FOR i IN 3 to ((dADDEND_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=> if(sign='0' and (prelim_result(1)='1' or prelim_result(0)='1')) then -- add one if prelim_result((dADDEND_LENGTH - 2) - 1 downto 3) = "1111111111111111111111111111111111111111111111111111" then --overflow prelim_result((dADDEND_LENGTH -2) -1 downto 3) := "0000000000000000000000000000000000000000000000000000"; exp_result := exp_result + 1; else carry:=true; FOR i IN 3 to ((dADDEND_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; end case; RETURN; END dround_result; BEGINmain_proc : process variable dmnt1 : dmnt; variable dmnt2 : dmnt; variable dexp1 : dexp; variable dexp2 : dexp; variable dsign1 : bit; variable dsign2 : bit; variable dsign_result : bit; variable dexp_diff : integer; variable daddend1 : daddend; variable daddend2 : daddend; variable dprelim_result : daddend; variable doverflow : boolean; variable dexp_result : dexp; variable dtrue_subtract : boolean; variable dswapped : boolean; variable mnt1 : mnt; variable mnt2 : mnt; variable exp1 : exp; variable exp2 : exp; variable sign1 : bit; variable sign2 : bit; variable sign_result : bit; variable exp_diff : integer; variable addend1 : addend; variable addend2 : addend; variable prelim_result : addend; variable overflow : boolean; variable exp_result : exp; variable true_subtract : boolean; variable swapped : boolean; variable pos_inf_flag1 : boolean; variable neg_inf_flag1 : boolean; variable pos_inf_flag2 : boolean; variable neg_inf_flag2 : boolean; variable nan_flag : boolean; variable special_flag : boolean; variable temp_exp : bit_vector (7 downto 0); variable op1_sign : bit; variable op1_exp : exp; variable op1_mant : mantissa; variable op2_sign : bit; variable op2_exp : exp; variable op2_mant : mantissa; variable res_sign : bit; variable res_exp : exp; variable res_mant : mantissa; alias fsr_cond : bit is fsr_out(12); alias round_mode : bit_vector (31 downto 30) is fsr_in(31 downto 30); variable z,n: bit:='0'; variable double1, double2, double3 : bit_64; alias d1L:bit_32 is double1(31 downto 0); alias d1H:bit_32 is double1(63 downto 32); alias d2L:bit_32 is double2(31 downto 0); alias d2H:bit_32 is double2(63 downto 32); alias d3L:bit_32 is double3(31 downto 0); alias d3H:bit_32 is double3(63 downto 32); alias v: bit is fsr_out (3); alias u: bit is fsr_out (2); alias dz: bit is fsr_out (1); alias av: bit is fsr_out (7); alias au: bit is fsr_out (6); alias d1_mant:bit_52 is double1(51 downto 0); alias d1_sign:bit is double1(63); alias d1_exp:bit_11 is double1(62 downto 52); alias d2_mant:bit_52 is double2(51 downto 0); alias d2_sign:bit is double2(63); alias d2_exp:bit_11 is double2(62 downto 52); alias d3_mant:bit_52 is double3(51 downto 0); alias d3_sign:bit is double3(63); alias d3_exp:bit_11 is double3(62 downto 52); BEGIN case operation is when add_d | subtract_d | ltd | gtd | led | ged | eqd | ned=> fsr_out<=fsr_in; u<='0'; v<='0'; dz<='0'; d1L:=Op1; d1H:=Op1b; d2L:=Op2; d2H:=Op2b;-- wait until phi1= '0';-- IF (phi1 = '1' ) THEN -- Step 1: Load operands and set flags dexp1:=bits_to_uint(d1_exp); dexp2:=bits_to_uint( d2_exp); -- Add the 1 (hidden 1) assumed in the representation. -- Actually, should not do this for any input which is -- denormalized. ( Both input assumed to be nomalized. ) IF (dexp1 = 0) AND (bits_to_uint(d1_mant) = 0) THEN dmnt1 := "0" & d1_mant; dexp1 := dexp2; ELSE dmnt1 := "1" & d1_mant; END IF; IF (dexp2 = 0) AND (bits_to_uint(d2_mant) =0) THEN dmnt2 := "0" & d2_mant; dexp2 := dexp1; ELSE dmnt2 := "1" & d2_mant; END IF; dsign1 := d1_sign; dsign2 := d2_sign; pos_inf_flag1 := false; neg_inf_flag1 := false; pos_inf_flag2 := false; neg_inf_flag2 := false; nan_flag := false; special_flag := false;-- fsr_flags <= "0000000"; -- Step 2: Check for special inputs ( +/- Infinity, NaN) IF (bits_to_uint(d1_exp) = dMAX_EXP) THEN dexp_result := dexp1; special_flag := true; IF (bits_to_uint(d1_mant) = 0) THEN IF d1_sign = '0' THEN pos_inf_flag1 := true; ELSE neg_inf_flag1 := true; END IF; ELSE nan_flag := true; END IF; END IF; IF (bits_to_uint(d2_exp) = dMAX_EXP) then dexp_result := dexp2; special_flag := true; IF (bits_to_uint(d2_mant) = 0) THEN IF d2_sign = '0' THEN pos_inf_flag2 := true; ELSE neg_inf_flag2 := true; END IF; ELSE nan_flag := true; END IF; END IF; -- Step 3: Compare exponents. Swap the operands of exp1 < exp2 -- or of (dexp1 = dexp2 AND mnt1 < mnt2) dswapped := false; IF (dexp1 < dexp2 OR (dexp1 = dexp2 AND dmnt1 < dmnt2)) THEN swap_ints(dexp1, dexp2); swap_bvs(dmnt1, dmnt2); swap_bits(sign1, sign2); dswapped := true; END IF; dexp_diff := dexp1 - dexp2; dexp_result := dexp1; dsign_result := dsign1; IF (dexp_diff > (dADDEND_LENGTH - 2)) THEN ASSERT (dexp_diff <= (dADDEND_LENGTH -2)) REPORT "Precision lost in exponent difference" SEVERITY warning; dexp_diff := dADDEND_LENGTH -2; END IF; -- Step 4: Shift the mantissa corresponding to the smaller exponent, -- and extend precision by three bits to the right. IF (dexp_diff > 0) THEN daddend1 := "0" & dmnt1 & "000"; form_extended_operand(dmnt2, daddend2, dexp_diff); ELSE daddend1 := "0" & dmnt1 & "000"; daddend2 := "0" & dmnt2 & "000"; END IF; -- Step 5: Add or subtract the mantissas. IF (operation /= add_d) THEN IF dswapped THEN dsign_result := NOT(dsign_result); END IF; IF (dsign1 = dsign2) THEN true_subtract := true; ELSE true_subtract := false; END IF; ELSIF (dsign1 /= dsign2 and operation = add_d) THEN true_subtract := true; ELSE true_subtract := false; END IF; IF true_subtract THEN daddend2 := twos_complement(daddend2); END IF; IF (special_flag = false) THEN bv_add(dprelim_result, daddend1, daddend2, overflow); END IF; -- Step 6: Normalize the result. IF (special_flag = false) THEN IF (bits_to_uint(dprelim_result) = 0) AND (overflow = false) THEN dsign_result := '0'; dexp_result:= 0; -- zero_res <= '1'; ELSIF overflow THEN IF dexp_result >= (dMAX_EXP - 1) THEN if(dsign_result='0') then v<='1'; else u<='1'; end if; av<='1'; int_to_bits(0,dprelim_result); dexp_result := dMAX_EXP;-- pos_inf_res <= '1'; ELSE dexp_result := exp_result + 1; right_shift(reg_val => dprelim_result, shift_amt => 1); END IF; ELSE -- Shift left until normalized. Normalized when the value to the -- left of the decimal point is 1. normalize(dprelim_result((dADDEND_LENGTH-2) downto 0), dexp_result); END IF; END IF; -- ASSERT false REPORT vector_to_string(round_mode) SEVERITY warning; -- Step 7: Round the result. IF (special_flag = false) THEN dround_result(dsign_result,dprelim_result, dexp_result, round_mode); END IF; -- Step 8: Put sum onto output. IF (special_flag = false) THEN d3_sign := dsign_result; n:=dsign_result; int_to_bits(dexp_result,d3_exp); d3_mant := dprelim_result((dADDEND_LENGTH - 2) - 1 downto 3); -- leaves off "hidden 1" and most significant bit(reserved for -- overflow earlier) ELSIF (nan_flag = true) THEN d3_sign := '0'; n:='0'; int_to_bits( dexp1,d3_exp); d3_mant := dmnt1(51 downto 0);-- nan_res <= '1';-- The rest of the code is to set the flag for the boundry conditions.-- -- Following truth table is for the boundry condition for setting the Flags-- "ctrl" refer to the conditional control for the hightest levels of ELSIF-- -- pos_inf_f1 pos_inf_f2 neg_inf_f1 neg_inf_f2 add sub Zero +INF -INF-- ********** ********** ********** ********** *** *** **** **** ****-- ctrl=1 1 0 0 0 1 1 0 0-- ctrl=1 0 0 1 1 0 1 0 0-- ctrl=1 0 0 0 X X 0 1 0---- 0 ctrl=1 1 0 1 0 1 0 0-- 0 ctrl=1 0 0 0 1 0 0 1-- 0 ctrl=1 1 0 0 1 0 0 1---- 0 0 ctrl=1 1 0 1 1 0 0-- 0 0 ctrl=1 1 1 0 0 0 1-- 0 0 ctrl=1 0 0 1 0 0 1---- 0 0 0 ctrl=1 0 1 0 1 0-- 0 0 0 ctrl=1 1 0 0 0 1---- ELSIF (pos_inf_flag1 = true) THEN d3_sign := '0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -