⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fp_mult.vhd

📁 DLX CPU VHDL CODE UNIVERSITY
💻 VHD
📖 第 1 页 / 共 2 页
字号:
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 + -