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

📄 fp_adder.vhd

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