📄 fp_mult.vhd
字号:
PACKAGE fpmult_pkg is constant MNT_LENGTH : INTEGER := 24; -- including hidden "1" bit constant PRODUCT_LENGTH : INTEGER := 48; -- twice of mantissa length constant MAX_EXP : INTEGER := 2#11111111#; subtype mnt is bit_vector(MNT_LENGTH - 1 downto 0); subtype product is bit_vector(PRODUCT_LENGTH - 1 downto 0); subtype mantissa is bit_vector((MNT_LENGTH - 1) -1 downto 0); subtype exp is integer range 0 to MAX_EXP; constant dMNT_LENGTH : INTEGER := 53; -- including hidden "1" bit constant dPRODUCT_LENGTH : INTEGER := 106; -- twice of mantissa length constant dMAX_EXP : INTEGER := 2#11111111111#; subtype dmnt is bit_vector(dMNT_LENGTH - 1 downto 0); subtype dproduct is bit_vector(dPRODUCT_LENGTH - 1 downto 0); subtype dmantissa is bit_vector((dMNT_LENGTH - 1) -1 downto 0); subtype dexp is integer range 0 to dMAX_EXP; END fpmult_pkg;----------------------------------------------------------------USE work.fpmult_pkg.all;use work.dp32_types.all;ENTITY fmu is PORT ( phi1,phi2 : in bit; Op1,Op1b,Op2,Op2b: in bit_32; R1,R2 : out bit_32; operation : in bit_2; fsr_in : in bit_32; fsr_out : out bit_32);-- 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---- The representation for input operands and the result is IEEE standard as-- shown below, with a 1-bit sign, an 8-bit exponent biased 127, and a 23-bit-- mantissa with a "hidden 1". ---- ______________________________-- | sign | exponent | mantissa |-- |______|__________|__________|-- 1 bit 8 bits 23 bits END fmu;-- ***************************************************************************ARCHITECTURE fmu_behavior of fmu is constant idel: bit_2 :="00"; constant multf: bit_2 :="01"; constant multd: bit_2 :="11"; 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";------------------------------------------------------------------------------FUNCTION shift_left1(bv : bit_vector) RETURN bit_vector ISVARIABLE temp: bit_vector(bv'RANGE); BEGIN temp:= bv; FOR i IN temp'high DOWNTO temp'low+1 LOOP temp(i):=temp(i-1); END LOOP; temp(temp'LOW):='0'; RETURN (temp);END shift_left1;------------------------------------------------------------------------------PROCEDURE bit_add( -- add operation does bv1+bv2 --> bv2 bv1 : in bit_vector; bv2 : in bit_vector; result: out bit_vector; Cout: out bit) IS VARIABLE Ci,Co : bit; VARIABLE i: integer:=0;BEGIN Co :='0'; FOR i IN bv1'REVERSE_RANGE LOOP Ci:=Co; IF Ci='1' THEN IF bv1(i)=bv2(i) THEN result(i):= '1'; ELSE result(i):= '0'; END IF; Co := bv1(i) OR bv2(i); ELSE IF bv1(i)=bv2(i) THEN result(i):='0'; ELSE result(i):='1'; END IF; Co:=bv1(i) AND bv2(i); END IF; END LOOP; Cout :=Co;END bit_add;------------------------------------------------------------------------------PROCEDURE shift_right1( Cout: in bit; bv : inout bit_vector) ISVARIABLE temp: bit_vector(bv'RANGE); BEGIN temp:= bv; FOR i IN temp'LOW TO temp'HIGH-1 LOOP temp(i):=temp(i+1); END LOOP; temp(temp'high):=Cout; bv:= temp;END shift_right1;-------------------------------------------------------------------------------- IEEE 754 standard, default rounding mode, round to NEAREST/EVENPROCEDURE round_result ( sign : in bit; round : in bit; sticky : in bit; prelim_result : inout bit_vector; exp_result : inout integer; round_mode : in bit_2) ISvariable carry: boolean := true;BEGIN case round_mode is when rn=> IF (round='1') then if((sticky='1') or (prelim_result(MNT_LENGTH)='1')) then if prelim_result((PRODUCT_LENGTH) - 1 downto MNT_LENGTH) = "111111111111111111111111" then --overflow prelim_result((PRODUCT_LENGTH) -1 downto MNT_LENGTH) := "000000000000000000000000"; exp_result := exp_result + 1; else carry:=true; FOR i IN MNT_LENGTH to ((PRODUCT_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((PRODUCT_LENGTH ) - 1 downto MNT_LENGTH) = "111111111111111111111111" then --overflow prelim_result((PRODUCT_LENGTH ) -1 downto MNT_LENGTH) := "000000000000000000000000"; exp_result := exp_result + 1; else carry:=true; FOR i IN MNT_LENGTH to ((PRODUCT_LENGTH)-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((PRODUCT_LENGTH ) - 1 downto MNT_LENGTH) = "111111111111111111111111" then --overflow prelim_result((PRODUCT_LENGTH ) -1 downto MNT_LENGTH) := "000000000000000000000000"; exp_result := exp_result + 1; else carry:=true; FOR i IN MNT_LENGTH to ((PRODUCT_LENGTH)-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;END round_result;-------------------------------------------------------------------------------- IEEE 754 standard, default rounding mode, round to NEAREST/EVENPROCEDURE dround_result ( round : in bit; sticky : in bit; prelim_result : inout bit_vector; exp_result : inout integer) ISvariable carry: boolean := true;BEGIN -- condition for not rounding -- if the round bit r=0 then do not round result -- In the case of tie, ie r=1 and s=0 then round to -- nearest even number. -- Therefore, if LSB is even do not round the result, -- else, add 1 to LSB, for the other case. IF round = '0' THEN RETURN; ELSIF (sticky = '0' and prelim_result(0)='0') THEN RETURN; END IF; -- round result, add one to the prelimanary result overflow IF prelim_result = B"11111111_11111111_11111111_11111111_11111111_11111111_11111" THEN --overflow prelim_result := B"10000000_00000000_00000000_00000000_00000000_00000000_00000"; exp_result := exp_result + 1; RETURN; END IF; -- round result FOR i IN dMNT_LENGTH TO (prelim_result'HIGH - 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; RETURN;END dround_result;------------------------------------------------------------------------------BEGIN multply: PROCESS(phi1, operation) VARIABLE dexp1, dexp2 : dexp; VARIABLE dexp_product : integer; VARIABLE dmant1, dmant2 : dmnt; VARIABLE dp_addend, dp_result: dmnt; VARIABLE dtemp_product : dproduct; VARIABLE dmant_result : dmantissa; VARIABLE dsign1, dsign2 : bit; VARIABLE dsign_product : bit; VARIABLE exp1, exp2 : exp; VARIABLE exp_product : integer; VARIABLE mant1, mant2 : mnt; VARIABLE p_addend, p_result : mnt; VARIABLE temp_product : product; VARIABLE mant_result : mantissa; VARIABLE sign1, sign2 : bit; VARIABLE sign_product : bit; VARIABLE underflow, overflow: boolean; VARIABLE zero_flag1 : boolean; VARIABLE zero_flag2 : boolean; VARIABLE inf_flag1 : boolean; VARIABLE inf_flag2 : boolean; VARIABLE Nan_flag1 : boolean; VARIABLE Nan_flag2 : boolean; VARIABLE non_special1 : boolean; VARIABLE non_special2 : boolean; VARIABLE over_under_flow : boolean; VARIABLE Cout : bit:='0'; VARIABLE sticky_bit : bit:='0'; VARIABLE round_bit : bit:='0'; variable dtemp_exp : bit_vector (10 downto 0); variable temp_exp : bit_vector (7 downto 0); ALIAS zero : bit is fsr_out(4); alias round_mode: bit_2 is fsr_in(31 downto 30); alias fsr_overflow: bit is fsr_out(3); alias fsr_underflow: bit is fsr_out(2); alias fsr_aoverflow: bit is fsr_out(7); alias fsr_aunderflow: bit is fsr_out(6); 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; variable dop1_sign : bit; variable dop1_exp : dexp; variable dop1_mant : dmantissa; variable dop2_sign : bit; variable dop2_exp : dexp; variable dop2_mant : dmantissa; variable dres_sign : bit; variable dres_exp : dexp; variable dres_mant : dmantissa; variable R,dop1,dop2 : bit_64; BEGIN case operation is when multf => fsr_out<=fsr_in; fsr_overflow<='0'; fsr_underflow<='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)); -- 1. Initialize the flags, check for special operands and load operands -- zero_flag1:=false; zero_flag2:=false; underflow:=false; overflow :=false; inf_flag1:=false; inf_flag2:=false; Nan_flag1:=false; Nan_flag2:=false; non_special1:=false; -- operand 1 is not special input if true non_special2:=false; -- operand 2 is not special input if true over_under_flow:=false; --flags<="0000"; sticky_bit:='0'; -- initialize sticky bit -- Load oprand1 and set internal flags IF op1_exp=0 and op1_mant=B"0000000_00000000_00000000" THEN zero_flag1:=true; ELSIF op1_exp=MAX_EXP THEN IF op1_mant/=B"0000000_00000000_00000000" THEN Nan_flag1:= true; ELSE inf_flag1:=true; END IF; ELSE non_special1:= true; sign1 := op1_sign; exp1 := op1_exp; mant1 := '1'&op1_mant; END IF; -- Load oprand2 and set internal flags IF op2_exp=0 and op2_mant=B"0000000_00000000_00000000" THEN zero_flag2:=true; ELSIF op2_exp=MAX_EXP THEN IF op2_mant/=B"0000000_00000000_00000000" THEN Nan_flag2:= true; ELSE inf_flag2:=true; END IF; ELSE non_special2:=true; sign2 := op2_sign; exp2 := op2_exp; mant2 := '1'&op2_mant; END IF; -- 2. Check Special operands -- If there are no special input (0, Nan, +/- Infinity) do step 3 through -- step 5; otherwise, skip to step 7 IF non_special1 and non_special2 THEN -- 3. Operate on the exponent and set product sign bit -- Check the product exponent overflow after result normalized in step 5 -- Add two exponent and subtract bias exp_product:=exp1+exp2-127; -- Set result sign bit IF sign1=sign2 THEN sign_product:='0'; ELSE sign_product:='1'; END IF;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -