📄 float_pkg_c.vhdl
字号:
variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range begin if (arg'length >= 1) then BUS_int := to_ux01 (arg); if (BUS_int'length = 1) then Result := BUS_int (BUS_int'left); elsif (BUS_int'length = 2) then Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); else Half := (BUS_int'length + 1) / 2 + BUS_int'right; Upper := xor_reduce (BUS_int (BUS_int'left downto Half)); Lower := xor_reduce (BUS_int (Half - 1 downto BUS_int'right)); Result := Upper xor Lower; end if; end if; return Result; end function xor_reduce; function nand_reduce(arg : std_ulogic_vector) return STD_ULOGIC is begin return not and_reduce (arg); end function nand_reduce; function nor_reduce(arg : std_ulogic_vector) return STD_ULOGIC is begin return not or_reduce (arg); end function nor_reduce; function xnor_reduce(arg : std_ulogic_vector) return STD_ULOGIC is begin return not xor_reduce (arg); end function xnor_reduce; function find_leftmost (ARG : UNSIGNED; Y : STD_ULOGIC) return INTEGER is begin for INDEX in ARG'range loop if ARG(INDEX) = Y then return INDEX; end if; end loop; return -1; end function find_leftmost; -- Match table, copied form new std_logic_1164 type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; constant match_logic_table : stdlogic_table := ( ----------------------------------------------------- -- U X 0 1 Z W L H - | | ----------------------------------------------------- ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1'), -- | U | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | X | ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | 0 | ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | 1 | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | Z | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | W | ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | L | ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | H | ('1', '1', '1', '1', '1', '1', '1', '1', '1') -- | - | ); constant no_match_logic_table : stdlogic_table := ( ----------------------------------------------------- -- U X 0 1 Z W L H - | | ----------------------------------------------------- ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '0'), -- | U | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | X | ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | 0 | ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | 1 | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | Z | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | W | ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | L | ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | H | ('0', '0', '0', '0', '0', '0', '0', '0', '0') -- | - | ); ------------------------------------------------------------------- -- ?= functions, Similar to "std_match", but returns "std_ulogic". ------------------------------------------------------------------- -- %%% FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic IS function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is begin return match_logic_table (l, r); end function \?=\; -- %%% END FUNCTION "?="; -- %%% FUNCTION "?/=" ( l, r : std_ulogic ) RETURN std_ulogic is function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is begin return no_match_logic_table (l, r); end function \?/=\; -- %%% END FUNCTION "?/="; function \?=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is begin return \?=\ (ufixed(l), ufixed(r)); end function \?=\; function Is_X ( s : UNSIGNED ) return BOOLEAN is begin return Is_X (STD_LOGIC_VECTOR (s)); end function Is_X; function Is_X ( s : SIGNED ) return BOOLEAN is begin return Is_X (STD_LOGIC_VECTOR (s)); end function Is_X;-- %%% END replicated functions -- Special version of "minimum" to do some boundary checking function mine (L, R : INTEGER) return INTEGER is begin -- function minimum if (L = INTEGER'low or R = INTEGER'low) then report float_pkg'instance_name & " Unbounded number passed, was a literal used?" severity error; return 0; end if; return minimum (L, R); end function mine; -- Generates the base number for the exponent normalization offset. function gen_expon_base ( constant exponent_width : NATURAL) return SIGNED is variable result : SIGNED (exponent_width-1 downto 0); begin result := (others => '1'); result (exponent_width-1) := '0'; return result; end function gen_expon_base; -- Integer version of the "log2" command (contributed by Peter Ashenden) function log2 (A : NATURAL) return NATURAL is variable quotient : NATURAL; variable result : NATURAL := 0; begin quotient := A / 2; while quotient > 0 loop quotient := quotient / 2; result := result + 1; end loop; return result; end function log2; -- Function similar to the ILOGB function in MATH_REAL function log2 (A : REAL) return INTEGER is variable Y : REAL; variable N : INTEGER := 0; begin if (A = 1.0 or A = 0.0) then return 0; end if; Y := A; if(A > 1.0) then while Y >= 2.0 loop Y := Y / 2.0; N := N + 1; end loop; return N; end if; -- O < Y < 1 while Y < 1.0 loop Y := Y * 2.0; N := N - 1; end loop; return N; end function log2; -- purpose: Test the boundary conditions of a Real number procedure test_boundary ( arg : in REAL; -- Input, converted to real constant fraction_width : in NATURAL; -- length of FP output fraction constant exponent_width : in NATURAL; -- length of FP exponent constant denormalize : in BOOLEAN := true; -- Use IEEE extended FP variable btype : out boundary_type; variable log2i : out INTEGER ) is constant expon_base : SIGNED (exponent_width-1 downto 0) := gen_expon_base(exponent_width); -- exponent offset constant exp_min : SIGNED (12 downto 0) := -(resize(expon_base, 13)) + 1; -- Minimum normal exponent constant exp_ext_min : SIGNED (12 downto 0) := exp_min - fraction_width; -- Minimum for denormal exponent variable log2arg : INTEGER; -- log2 of argument begin -- function test_boundary -- Check to see if the exponent is big enough -- Note that the argument is always an absolute value at this point. log2arg := log2(arg); if arg = 0.0 then btype := zero; elsif exponent_width > 11 then -- Exponent for Real is 11 (64 bit) btype := normal; else if log2arg < to_integer(exp_min) then if denormalize then if log2arg < to_integer(exp_ext_min) then btype := zero; else btype := denormal; end if; else if log2arg < to_integer(exp_min)-1 then btype := zero; else btype := normal; -- Can still represent this number end if; end if; elsif exponent_width < 11 then if log2arg > to_integer(expon_base)+1 then btype := infinity; else btype := normal; end if; else btype := normal; end if; end if; log2i := log2arg; end procedure test_boundary; -- purpose: Rounds depending on the state of the "round_style" -- Logic taken from -- "What Every Computer Scientist Should Know About Floating Point Arithmetic" -- by David Goldberg (1991) function check_round ( fract_in : STD_ULOGIC; -- input fraction sign : STD_ULOGIC; -- sign bit remainder : UNSIGNED; -- remainder to round from sticky : STD_ULOGIC := '0'; -- Sticky bit constant round_style : round_type) -- rounding type return BOOLEAN is variable result : BOOLEAN; variable or_reduced : STD_ULOGIC; begin -- function check_round result := false; if (remainder'length > 0) then -- if remainder in a null array or_reduced := or_reduce (remainder & sticky); rounding_case : case round_style is when round_nearest => -- Round Nearest, default mode if remainder(remainder'high) = '1' then -- round if (remainder'length > 1) then if ((or_reduce (remainder(remainder'high-1 downto remainder'low)) = '1' or sticky = '1') or fract_in = '1') then -- Make the bottom bit zero if possible if we are at 1/2 result := true; end if; else result := (fract_in = '1' or sticky = '1'); end if; end if; when round_inf => -- round up if positive, else truncate. if or_reduced = '1' and sign = '0' then result := true; end if; when round_neginf => -- round down if negative, else truncate. if or_reduced = '1' and sign = '1' then result := true; end if; when round_zero => -- round toward 0 Truncate null; end case rounding_case; end if; return result; end function check_round; -- purpose: Rounds depending on the state of the "round_style" -- unsigned version procedure fp_round ( fract_in : in UNSIGNED; -- input fraction expon_in : in SIGNED; -- input exponent fract_out : out UNSIGNED; -- output fraction expon_out : out SIGNED) is -- output exponent begin -- procedure fp_round if and_reduce (fract_in) = '1' then -- Fraction is all "1" expon_out := expon_in + 1; fract_out := to_unsigned(0, fract_out'h
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -