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

📄 fpurt_lib.vhd

📁 ERC32 经典的sparc v7 cpu
💻 VHD
📖 第 1 页 / 共 5 页
字号:
	    end if;	elsif SIsInf(f1) then	    q1.v := Inf;        elsif SIsZero(f1) then	    q1.v := Zero;	end if;	return(q1);    end SToQuad;    function DToQuad(f1: std_logic_vector) return Quad is    variable q1 : Quad;    begin	q1.sign := f1(63);	q1.exp := unsigned(ext(f1(62 downto 52),15)) + 16383 - 1023;	q1.man := unsigned(ext(('1'& f1(51 downto 0) & "000"),113));	q1.v := Norm;	if  DIsNaN(f1) then	    if f1(51) = '1' then	        q1.v := QNaN;	    else	        q1.v := SNaN;	    end if;	elsif DIsInf(f1) then	    q1.v := Inf;        elsif DIsZero(f1) then	    q1.v := Zero;	end if;	return(q1);    end DToQuad;    procedure Normalize(q1 : inout quad) is    variable i : integer := 0;    begin	if q1.v = norm then	    while (i < 113) and (q1.man(112 - i) = '0') loop	        i := i + 1;	    end loop; 	    if (i < 57) then	        q1.man := shr(q1.man, conv_unsigned(57 - i,8));	    else	        q1.man := shl(q1.man, conv_unsigned(i - 57 ,8));	    end if;	    q1.exp := q1.exp + (57 - i);	end if;    end Normalize;    procedure FPround(q : quad; res : inout std_logic_vector; SP : boolean) is    variable i, intexp, iexp, isign, exprange, ig : integer;    variable utmp : unsigned (14 downto 0);    variable Pround : unsigned (112 downto 0) := (others => '0');    variable q1 : quad := q;    variable lexp, lman : integer;    variable RDL : std_logic_vector(1 downto 0);    begin	if q1.v = Inf then	    if SP then		res(31 downto 0) := q1.sign & SPInf;	    else		res(63 downto 0) := q1.sign & DPInf;	    end if;	elsif q1.v = Zero then	    if SP then		res(31 downto 0) := q1.sign & ext("0",31);	    else		res(63 downto 0) := q1.sign & ext("0",63);	    end if;	elsif q1.v <= SNan then	    if SP then		res(31 downto 0) := SPNan;	    else		res(63 downto 0) := DPNan;	    end if;	else	    if SP then	        lexp := 8;	        lman := 23;	    else	        lexp := 11;	        lman := 52;	    end if;	    ig := 54 -lman;	    Pround(ig) := '1';	    isign := lman + lexp;	    iexp := isign - 1;	    exprange := 2;	    for i in 2 to lexp loop	        exprange := exprange * 2;	    end loop;	    exprange := exprange;  	    i := 0;	-- First, we normalize to quad	    Normalize(q1);	-- Round according to RD            RDL := RD( 1 downto 0);	    if ((q1.man(ig downto 1)) /= unsigned(ext("0",ig-1))) or		cexc(0) = '1'	     then	        cexc(0) := '1';		-- Inexact ieee flag	        case RDL(1 downto 0) is		    when "00" =>		-- round to nearest		 	if ((q1.man(ig downto 0)) > 			     unsigned('1' & ext("0",ig))		 	   ) or			   (((q1.man(ig downto 0)) = 			      unsigned('1' & ext("0",ig))			     ) and 			     (q1.man(ig+1) = '1')			   ) then			    q1.man := q1.man + Pround;			    Normalize(q1);			end if;		    when "01" =>		-- round to zero (truncate)			null;		    when "10" =>		-- round to +Inf			if q1.sign = '0' then			    q1.man := q1.man + shl(Pround,"01");			end if;		    when "11" =>		-- round to -Inf			if q1.sign = '1' then			    q1.man := q1.man + shl(Pround,"01");			end if;		    when others =>			null;		end case;	    end if;	    res(isign) := q1.sign;	    utmp := q1.exp + (-16383 + (exprange / 2) -1);	    res(iexp downto lman) := std_logic_vector(utmp((lexp-1) downto 0));	    res(lman-1 downto 0) := std_logic_vector(q1.man(54 downto (54 -lman +1)));	-- Check ieee exceptions, improvements here are welcome	    intexp := conv_integer(q1.exp);	    if (intexp > ( 16383 + exprange/2 -1)) then	        cexc(3) := '1';				-- overflow		case RDL(1 downto 0) is		    when "00" =>	-- round to nearest, return 1	        	res(iexp downto lman) := '0' & sxt("1",lexp - 1);	        	res(lman-1 downto 0) := ext("0",lman);		    when "01" =>	-- round to zero, return largest norm	        	res(iexp downto lman) := sxt("1",lexp - 1) & '0';	        	res(lman-1 downto 0) := sxt("1",lman);		    when "10" =>	-- round to +Inf			if res(isign) = '1' then 	-- most negitive norm	        	    res(iexp downto lman) := sxt("1",lexp - 1) & '0';	        	    res(lman-1 downto 0) := sxt("1",lman);			else				-- +Inf	        	    res(iexp downto lman) := sxt("1",lexp);	        	    res(lman-1 downto 0) := sxt("0",lman);			end if;		    when "11" =>	-- round to -Inf			if res(isign) = '0' then 	-- most positive norm	        	    res(iexp downto lman) := sxt("1",lexp - 1) & '0';	        	    res(lman-1 downto 0) := sxt("1",lman);			else				-- -Inf	        	    res(iexp downto lman) := sxt("1",lexp);	        	    res(lman-1 downto 0) := sxt("0",lman);			end if;		    when others =>			null;		end case;	    elsif (intexp < (16383 - exprange/2 + 2)) then 	        cexc(2) := '1';		-- underflow, return denorm	        i := 16383 - intexp + (exprange / 2) - 1;		res(iexp downto lman) := ext("0",lexp);		res(lman-1 downto 0) := 		    std_logic_vector(shr(q1.man(55 downto 55 - lman +1),(conv_unsigned(i,8))));	    end if;	end if;	if (SP) then	    res (63 downto 32) := res(31 downto 0);	end if;    end FPround;			    procedure fmul(rs1, rs2: Quad; res: out Quad) is    variable q1: Quad;    begin	res.sign := rs1.sign xor rs2.sign;	if (rs1.v = Zero) or (rs2.v = Zero) then	    res.v := Zero;	elsif (rs1.v = Inf) or (rs2.v = Inf) then	    res.v := Inf;	else	  res.v := Norm;	  res.exp := (rs1.exp - 16383) + rs2.exp - 55;	  res.man := '0' & (rs1.man(55 downto 0) * rs2.man(55 downto 0));	end if;    end fmul;    procedure fdiv(rs1, rs2: Quad; res: out Quad) is    variable q1,q2: Quad;    variable i : integer := 55;    begin	res.sign := rs1.sign xor rs2.sign;	res.exp := (rs1.exp - rs2.exp) + 16383;	res.man := unsigned(ext("0",113));	if (rs1.v = Zero) then	    res.v := Zero;	elsif  (rs2.v = Inf) then	    res.v := Zero;	else	    res.v := Norm;	    q1.man := shl(rs1.man,"0111000");	    q2.man := shl(rs2.man,"0111000");	    while (i > 0) loop	        if q2.man <= q1.man then		    q1.man := q1.man - q2.man;		    res.man(i) := '1';	        end if;	        i := i - 1;	        q2.man := shr(q2.man, "01");	    end loop;	    if q1.man /= unsigned(ext("0",113)) then		cexc(0) := '1';		-- Inexact	    end if;	end if;    end fdiv;    procedure fcmp(q1, q2: quad; tfcc: out std_logic_vector) is    variable s1, s2 : signed(127 downto 0);    begin	if ((q1.v = Inf) and (q2.v = Inf) and (q1.sign = q2.sign)) then	    tfcc := "11";	else	    s1 := signed(q1.sign & q1.exp & q1.man(111 downto 0));	    s2 := signed(q2.sign & q2.exp & q2.man(111 downto 0));	    if (s1 < s2) then	        tfcc := "01";	    elsif (s1 > s2) then	        tfcc := "10";	    else	        tfcc := "00";	    end if;	end if;    end fcmp;    procedure faddsub(rs1, rs2: quad; res: out quad; doadd : boolean) is    variable s1, s2, exp1, exp2, man1, man2: quad;    begin	if (rs1.v = Inf) then	    res := rs1;	    if (rs2.v = Inf) then		if ((doadd and (rs1.sign /= rs2.sign)) or		    (not doadd and (rs1.sign = rs2.sign))) then		    cexc(4) := '1';		    res.v := QNan;		    res.sign := '0';		end if;	    end if;	elsif (rs2.v = Inf) then	    res.v := Inf;	    if doadd then	        res.sign := rs2.sign;	    else	        res.sign := not rs2.sign;	    end if;	elsif (rs1 = rs2) then	    res := rs1;	    if doadd then		res.exp := rs1.exp + 1;	    else	        res.v := Zero;	        if RD = "11" then		    res.sign := '1';	        else		    res.sign := '0';	        end if;	    end if;	elsif (rs1.v = Zero) then	    res := rs2;	    if (rs2.v = norm) and not doadd then		res.sign := not rs2.sign;	    end if;	elsif (rs2.v = Zero) then	    res := rs1;	else            if (rs1.exp < rs2.exp) then                s1 := rs2;                s2 := rs1;	        if not doadd then		    s1.sign := not s1.sign;		end if;            else                s1 := rs1;                s2 := rs2;	        if not doadd then		    s2.sign := not s2.sign;		end if;            end if;			    s2.man := shr(s2.man, s1.exp - s2.exp);            if (s1.sign = '1') then                s1.man := 0 - s1.man;            end if;            if (s2.sign = '1') then                s2.man := 0 - s2.man;            end if;            s1.man := s1.man + s2.man;	    s1.sign := s1.man(112);            if (s1.man(112) = '1') then                s1.man := 0 - s1.man;            end if;	    res := s1;	    if s1.man = unsigned(ext("0",113)) then		res.v := Zero;	    end if;	end if;    end;    procedure fsqrt(rs1 : quad; res: out quad; sp : boolean) is    variable s1, s2, s3, s4, s5 : quad;    variable accuracy : integer;    begin	-- Sqrt calculations according newton/rapson xn = (x2 +s1)/2x	if (rs1.v = Norm) then	    s1 := rs1;	    s2 := rs1;	    if SP then	        accuracy := 16838 - 130;	    else	        accuracy := 16838 - 1026;	    end if;	    s2.exp := s2.exp - 1;	-- s2 is seed, equal to s1/2	    loop		fmul(s2,s2,s3);	        Normalize(s3);	        faddsub(s3, s1, s4, false);	        Normalize(s4);		s4.exp := s4.exp -1;	        fdiv(s4,s2,s3);	        Normalize(s3);	        faddsub(s2, s3, s5, false);	        Normalize(s5);--		s4 := s1;--		s4.exp := s4.exp -1;--	        fdiv(s4,s2,s3);--	        Normalize(s3);--		s4 := s2;--		s4.exp := s4.exp -1;--	        faddsub(s3, s4, s5, true);--	        Normalize(s5);	        if (s5.v /= norm) or (s3.v /= norm) or (s2 = s5) then		    exit;		end if;		s2 := s5;	    end loop;--	    if s5.man(1 downto 0) = unsigned'("11") then--		s5.man := s5.man + 1;--	        Normalize(s5);--	    elsif s5.man(1 downto 0) = unsigned'("01") then--		s5.man(0) := '0';

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -