📄 fp_adder.vhd
字号:
n:='0'; d3_mant := dmnt1(51 downto 0); IF (pos_inf_flag2 = true) AND (operation /= add_d) THEN int_to_bits(0,d3_exp); z:='1'; -- zero_res <= '1'; ELSIF (neg_inf_flag2 = true) AND (operation = add_d) THEN int_to_bits(0,d3_exp); z:='1'; -- zero_res <= '1'; ELSE int_to_bits( MAX_EXP,d3_exp); -- pos_inf_res <= '1'; END IF; ELSIF (pos_inf_flag2 = true) THEN d3_mant := d2_mant; int_to_bits( dMAX_EXP,d3_exp); IF (neg_inf_flag1 = true) AND (operation = add_d) THEN int_to_bits(0,d3_exp); d3_sign := '0'; n:='0'; z:='1'; -- zero_res <= '1'; ELSIF (operation /= add_d) THEN d3_sign := '1'; -- neg_inf_res <= '1'; n:='1'; ELSE d3_sign := '0'; n:='0'; -- pos_inf_res <= '1'; END IF; ELSIF (neg_inf_flag1 = true) THEN d3_sign := '1'; d3_mant := d1_mant; IF (neg_inf_flag2 = true) AND (operation /=add_d) THEN int_to_bits(0,d3_exp); z:='1'; n:='0'; d3_sign := '0'; -- zero_res <= '1'; ELSE int_to_bits( dMAX_EXP,d3_exp); -- neg_inf_res <= '1'; END IF; ELSIF (neg_inf_flag2 = true) THEN d3_mant := d2_mant; int_to_bits( dMAX_EXP,d3_exp); IF (operation /= add_d) THEN d3_sign := '0'; n:='0'; -- pos_inf_res <= '1'; ELSE d3_sign := '1'; n:='1'; -- neg_inf_res <= '1'; END IF; END IF; when others => --**************************** fsr_out<=fsr_in; u<='0'; v<='0'; dz<='0'; op1_mant:=Op1(22 downto 0); op2_mant:=Op2(22 downto 0); op1_sign:=Op1(31); op2_sign:=Op2(31); op1_exp:=bits_to_uint(Op1(30 downto 23)); op2_exp:=bits_to_uint(Op2(30 downto 23));-- wait until phi1= '0';-- IF (phi1 = '1' ) THEN -- Step 1: Load operands and set flags exp1 := op1_exp; --bits_to_int(op1_exp); exp2 := op2_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 (exp1 = 0) AND (op1_mant = "00000000000000000000000") THEN mnt1 := "0" & op1_mant; exp1 := exp2; ELSE mnt1 := "1" & op1_mant; END IF; IF (exp2 = 0) AND (op2_mant = "00000000000000000000000") THEN mnt2 := "0" & op2_mant; exp2 := exp1; ELSE mnt2 := "1" & op2_mant; END IF; sign1 := op1_sign; sign2 := op2_sign; pos_inf_flag1 := false; neg_inf_flag1 := false; pos_inf_flag2 := false; neg_inf_flag2 := false; nan_flag := false; special_flag := false; fsr_out (4 downto 1) <= "0000"; -- Step 2: Check for special inputs ( +/- Infinity, NaN) IF (op1_exp = MAX_EXP) THEN exp_result := exp1; special_flag := true; IF op1_mant = "00000000000000000000000" THEN IF op1_sign = '0' THEN pos_inf_flag1 := true; ELSE neg_inf_flag1 := true; END IF; ELSE nan_flag := true; END IF; END IF; IF (op2_exp = MAX_EXP) then exp_result := exp2; special_flag := true; IF op2_mant = "00000000000000000000000" THEN IF op2_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 (exp1 = exp2 AND mnt1 < mnt2) swapped := false; IF (exp1 < exp2 OR (exp1 = exp2 AND mnt1 < mnt2)) THEN swap_ints(exp1, exp2); swap_bvs(mnt1, mnt2); swap_bits(sign1, sign2); swapped := true; END IF; exp_diff := exp1 - exp2; exp_result := exp1; sign_result := sign1; IF (exp_diff > (ADDEND_LENGTH - 2)) THEN ASSERT (exp_diff <= (ADDEND_LENGTH -2)) REPORT "Precision lost in exponent difference" SEVERITY warning; exp_diff := ADDEND_LENGTH -2; END IF; -- Step 4: Shift the mantissa corresponding to the smaller exponent, -- and extend precision by three bits to the right. IF (exp_diff > 0) THEN addend1 := "0" & mnt1 & "000"; form_extended_operand(mnt2, addend2, exp_diff); ELSE addend1 := "0" & mnt1 & "000"; addend2 := "0" & mnt2 & "000"; END IF; -- Step 5: Add or subtract the mantissas. IF (operation /= add) THEN IF swapped THEN sign_result := NOT(sign_result); END IF; IF (sign1 = sign2) THEN true_subtract := true; ELSE true_subtract := false; END IF; ELSIF (sign1 /= sign2 and operation = add) THEN true_subtract := true; ELSE true_subtract := false; END IF; IF true_subtract THEN addend2 := twos_complement(addend2); END IF; IF (special_flag = false) THEN bv_add(prelim_result, addend1, addend2, overflow); END IF; -- Step 6: Normalize the result. IF (special_flag = false) THEN IF (prelim_result = "0000000000000000000000000000") AND (overflow = false) THEN sign_result := '0'; exp_result:= 0;-- zero_res <= '1'; ELSIF overflow THEN IF exp_result >= (MAX_EXP - 1) THEN prelim_result := "0000000000000000000000000000"; if(dsign_result='0') then v<='1'; else u<='1'; end if; av<='1'; exp_result := MAX_EXP;-- pos_inf_res <= '1'; ELSE exp_result := exp_result + 1; right_shift(reg_val => prelim_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(prelim_result((ADDEND_LENGTH-2) downto 0), exp_result); END IF; END IF; -- Step 7: Round the result. IF (special_flag = false) THEN round_result(sign_result,prelim_result, exp_result, round_mode); END IF; -- Step 8: Put sum onto output. IF (special_flag = false) THEN res_sign := sign_result; n:=sign_result; res_exp := exp_result; res_mant := prelim_result((ADDEND_LENGTH - 2) - 1 downto 3); -- leaves off "hidden 1" and most significant bit(reserved for -- overflow earlier) ELSIF (nan_flag = true) THEN res_sign := '0'; res_exp := exp1; n:='0'; res_mant := mnt1(22 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 res_sign := '0'; res_mant := mnt1(22 downto 0); IF (pos_inf_flag2 = true) AND (operation /= add) THEN res_exp := 0; z:='1'; -- zero_res <= '1'; ELSIF (neg_inf_flag2 = true) AND (operation = add) THEN res_exp := 0; z:='1'; --- zero_res <= '1'; ELSE res_exp := MAX_EXP; -- pos_inf_res <= '1'; END IF; ELSIF (pos_inf_flag2 = true) THEN res_mant := op2_mant; res_exp := MAX_EXP; IF (neg_inf_flag1 = true) AND (operation = add) THEN res_exp := 0; z:='1'; res_sign := '0'; n:='0'; -- zero_res <= '1'; ELSIF (operation /= add) THEN res_sign := '1'; n:='1'; -- neg_inf_res <= '1'; ELSE n:='0'; res_sign := '0'; -- pos_inf_res <= '1'; END IF; ELSIF (neg_inf_flag1 = true) THEN res_sign := '1'; res_mant := op1_mant; IF (neg_inf_flag2 = true) AND (operation /= add) THEN z:='1'; res_exp := 0; res_sign := '0'; -- zero_res <= '1'; n:='0'; ELSE res_exp := MAX_EXP; -- neg_inf_res <= '1'; END IF; ELSIF (neg_inf_flag2 = true) THEN res_mant := op2_mant; res_exp := MAX_EXP; IF (operation /= add) THEN res_sign := '0'; n:='0'; -- pos_inf_res <= '1'; ELSE res_sign := '1'; n:='1'; -- neg_inf_res <= '1'; END IF; END IF; end case;case operation is when add | subtract => int_to_bits(res_exp,temp_exp); R<= res_sign&temp_exp&res_mant;-- neg_res<=res_sign; when add_d | subtract_d => -- neg_res<=d3H(31); R<=d3L; Rb<=d3H; when eqf|eqd => fsr_out<=fsr_in; -- ASSERT false REPORT "eqf or eqd" SEVERITY warning; if(z='1') then fsr_cond<='1'; -- ASSERT false REPORT "zero_res=1" SEVERITY warning; else fsr_cond<='0'; end if; when gtf|gtd=> fsr_out<=fsr_in; -- ASSERT false REPORT "gt" SEVERITY warning; if( n='0' and z='0') then fsr_cond<='1'; else fsr_cond<='0'; end if; when lef|led=> fsr_out<=fsr_in; -- ASSERT false REPORT "le" SEVERITY warning; if( n='1' or z='1') then fsr_cond<='1'; else fsr_cond<='0'; end if; when ltf|ltd=> fsr_out<=fsr_in; -- ASSERT false REPORT "lt" SEVERITY warning; if( n='1' and z='0') then fsr_cond<='1'; else fsr_cond<='0'; end if; when gef|ged=> fsr_out<=fsr_in; -- ASSERT false REPORT "ge" SEVERITY warning; if( n='0'or z='1') then fsr_cond<='1'; else fsr_cond<='0'; end if; when nef|ned=> fsr_out<=fsr_in; -- ASSERT false REPORT "ne" SEVERITY warning; if( z='0') then fsr_cond<='1'; else fsr_cond<='0'; end if; when others => fsr_out<=fsr_in;-- ASSERT false REPORT "others" SEVERITY warning; end case;wait until phi2='1';END PROCESS;END fau_behavior;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -