-- -------------------------------------------------------------------- -- "fixed_pkg_c.vhdl" package contains functions for fixed point math. -- Please see the documentation for the fixed point package. -- This package should be compiled into "ieee_proposed" and used as follows: -- use ieee.std_logic_1164.all; -- use ieee.numeric_std.all; -- use ieee_proposed.math_utility_pkg.all; -- use ieee_proposed.fixed_pkg.all; -- -- This verison is designed to work with the VHDL-93 compilers -- synthesis tools. Please note the "%%%" comments. These are where we -- diverge from the VHDL-200X LRM. -- -------------------------------------------------------------------- -- Version : $Revision: 1.17 $ -- Date : $Date: 2007-05-31 14:52:33-04 $ -- -------------------------------------------------------------------- use STD.TEXTIO.all; library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD.all; library IEEE_PROPOSED; use IEEE_PROPOSED.math_utility_pkg.all; package fixed_pkg is -- generic ( -- Rounding routine to use in fixed point, fixed_round or fixed_truncate constant fixed_round_style : fixed_round_style_type := fixed_round; -- Overflow routine to use in fixed point, fixed_saturate or fixed_wrap constant fixed_overflow_style : fixed_overflow_style_type := fixed_saturate; -- Extra bits used in divide routines constant fixed_guard_bits : NATURAL := 3; -- If TRUE, then turn off warnings on "X" propagation constant no_warning : BOOLEAN := (false ); -- Author David Bishop (dbishop@vhdl.org) -- base Unsigned fixed point type, downto direction assumed type UNRESOLVED_ufixed is array (INTEGER range <>) of STD_ULOGIC; -- base Signed fixed point type, downto direction assumed type UNRESOLVED_sfixed is array (INTEGER range <>) of STD_ULOGIC; subtype U_ufixed is UNRESOLVED_ufixed; subtype U_sfixed is UNRESOLVED_sfixed; subtype ufixed is UNRESOLVED_ufixed; subtype sfixed is UNRESOLVED_sfixed; --=========================================================================== -- Arithmetic Operators: --=========================================================================== -- Absolute value, 2's complement -- abs sfixed(a downto b) = sfixed(a+1 downto b) function "abs" (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- Negation, 2's complement -- - sfixed(a downto b) = sfixed(a+1 downto b) function "-" (arg : UNRESOLVED_sfixed)return UNRESOLVED_sfixed; -- Addition -- ufixed(a downto b) + ufixed(c downto d) -- = ufixed(maximum(a,c)+1 downto minimum(b,d)) function "+" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- sfixed(a downto b) + sfixed(c downto d) -- = sfixed(maximum(a,c)+1 downto minimum(b,d)) function "+" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- Subtraction -- ufixed(a downto b) - ufixed(c downto d) -- = ufixed(maximum(a,c)+1 downto minimum(b,d)) function "-" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- sfixed(a downto b) - sfixed(c downto d) -- = sfixed(maximum(a,c)+1 downto minimum(b,d)) function "-" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- Multiplication -- ufixed(a downto b) * ufixed(c downto d) = ufixed(a+c+1 downto b+d) function "*" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- sfixed(a downto b) * sfixed(c downto d) = sfixed(a+c+1 downto b+d) function "*" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- Division -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) function "/" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) function "/" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- Remainder -- ufixed (a downto b) rem ufixed (c downto d) -- = ufixed (minimum(a,c) downto minimum(b,d)) function "rem" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- sfixed (a downto b) rem sfixed (c downto d) -- = sfixed (minimum(a,c) downto minimum(b,d)) function "rem" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- Modulo -- ufixed (a downto b) mod ufixed (c downto d) -- = ufixed (minimum(a,c) downto minimum(b, d)) function "mod" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- sfixed (a downto b) mod sfixed (c downto d) -- = sfixed (c downto minimum(b, d)) function "mod" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; ---------------------------------------------------------------------------- -- In these routines the "real" or "natural" (integer) -- are converted into a fixed point number and then the operation is -- performed. It is assumed that the array will be large enough. -- If the input is "real" then the real number is converted into a fixed of -- the same size as the fixed point input. If the number is an "integer" -- then it is converted into fixed with the range (l'high downto 0). ---------------------------------------------------------------------------- -- ufixed(a downto b) + ufixed(a downto b) = ufixed(a+1 downto b) function "+" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; -- ufixed(c downto d) + ufixed(c downto d) = ufixed(c+1 downto d) function "+" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- ufixed(a downto b) + ufixed(a downto 0) = ufixed(a+1 downto minimum(0,b)) function "+" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto minimum(0,d)) function "+" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- ufixed(a downto b) - ufixed(a downto b) = ufixed(a+1 downto b) function "-" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; -- ufixed(c downto d) - ufixed(c downto d) = ufixed(c+1 downto d) function "-" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- ufixed(a downto b) - ufixed(a downto 0) = ufixed(a+1 downto minimum(0,b)) function "-" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto minimum(0,d)) function "-" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- ufixed(a downto b) * ufixed(a downto b) = ufixed(2a+1 downto 2b) function "*" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; -- ufixed(c downto d) * ufixed(c downto d) = ufixed(2c+1 downto 2d) function "*" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) function "*" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) function "*" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) function "/" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) function "/" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- ufixed(a downto b) / ufixed(a downto 0) = ufixed(a downto b-a-1) function "/" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; -- ufixed(c downto 0) / ufixed(c downto d) = ufixed(c-d downto -c-1) function "/" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- ufixed (a downto b) rem ufixed (a downto b) = ufixed (a downto b) function "rem" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; -- ufixed (c downto d) rem ufixed (c downto d) = ufixed (c downto d) function "rem" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- ufixed (a downto b) rem ufixed (a downto 0) = ufixed (a downto minimum(b,0)) function "rem" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; -- ufixed (c downto 0) rem ufixed (c downto d) = ufixed (c downto minimum(d,0)) function "rem" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- ufixed (a downto b) mod ufixed (a downto b) = ufixed (a downto b) function "mod" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; -- ufixed (c downto d) mod ufixed (c downto d) = ufixed (c downto d) function "mod" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- ufixed (a downto b) mod ufixed (a downto 0) = ufixed (a downto minimum(b,0)) function "mod" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; -- ufixed (c downto 0) mod ufixed (c downto d) = ufixed (c downto minimum(d,0)) function "mod" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; -- sfixed(a downto b) + sfixed(a downto b) = sfixed(a+1 downto b) function "+" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; -- sfixed(c downto d) + sfixed(c downto d) = sfixed(c+1 downto d) function "+" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- sfixed(a downto b) + sfixed(a downto 0) = sfixed(a+1 downto minimum(0,b)) function "+" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; -- sfixed(c downto 0) + sfixed(c downto d) = sfixed(c+1 downto minimum(0,d)) function "+" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- sfixed(a downto b) - sfixed(a downto b) = sfixed(a+1 downto b) function "-" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; -- sfixed(c downto d) - sfixed(c downto d) = sfixed(c+1 downto d) function "-" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- sfixed(a downto b) - sfixed(a downto 0) = sfixed(a+1 downto minimum(0,b)) function "-" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; -- sfixed(c downto 0) - sfixed(c downto d) = sfixed(c+1 downto minimum(0,d)) function "-" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- sfixed(a downto b) * sfixed(a downto b) = sfixed(2a+1 downto 2b) function "*" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; -- sfixed(c downto d) * sfixed(c downto d) = sfixed(2c+1 downto 2d) function "*" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- sfixed(a downto b) * sfixed(a downto 0) = sfixed(2a+1 downto b) function "*" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; -- sfixed(c downto 0) * sfixed(c downto d) = sfixed(2c+1 downto d) function "*" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- sfixed(a downto b) / sfixed(a downto b) = sfixed(a-b+1 downto b-a) function "/" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; -- sfixed(c downto d) / sfixed(c downto d) = sfixed(c-d+1 downto d-c) function "/" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- sfixed(a downto b) / sfixed(a downto 0) = sfixed(a+1 downto b-a) function "/" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; -- sfixed(c downto 0) / sfixed(c downto d) = sfixed(c-d+1 downto -c) function "/" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- sfixed (a downto b) rem sfixed (a downto b) = sfixed (a downto b) function "rem" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; -- sfixed (c downto d) rem sfixed (c downto d) = sfixed (c downto d) function "rem" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- sfixed (a downto b) rem sfixed (a downto 0) = sfixed (a downto minimum(b,0)) function "rem" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; -- sfixed (c downto 0) rem sfixed (c downto d) = sfixed (c downto minimum(d,0)) function "rem" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- sfixed (a downto b) mod sfixed (a downto b) = sfixed (a downto b) function "mod" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; -- sfixed (c downto d) mod sfixed (c downto d) = sfixed (c downto d) function "mod" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- sfixed (a downto b) mod sfixed (a downto 0) = sfixed (a downto minimum(b,0)) function "mod" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; -- sfixed (c downto 0) mod sfixed (c downto d) = sfixed (c downto minimum(d,0)) function "mod" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- This version of divide gives the user more control -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) function divide ( l, r : UNRESOLVED_ufixed; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed; -- This version of divide gives the user more control -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) function divide ( l, r : UNRESOLVED_sfixed; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed; -- These functions return 1/X -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) function reciprocal ( arg : UNRESOLVED_ufixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed; -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) function reciprocal ( arg : UNRESOLVED_sfixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed; -- REM function -- ufixed (a downto b) rem ufixed (c downto d) -- = ufixed (minimum(a,c) downto minimum(b,d)) function remainder ( l, r : UNRESOLVED_ufixed; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed; -- sfixed (a downto b) rem sfixed (c downto d) -- = sfixed (minimum(a,c) downto minimum(b,d)) function remainder ( l, r : UNRESOLVED_sfixed; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed; -- mod function -- ufixed (a downto b) mod ufixed (c downto d) -- = ufixed (minimum(a,c) downto minimum(b, d)) function modulo ( l, r : UNRESOLVED_ufixed; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed; -- sfixed (a downto b) mod sfixed (c downto d) -- = sfixed (c downto minimum(b, d)) function modulo ( l, r : UNRESOLVED_sfixed; constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed; -- Procedure for those who need an "accumulator" function. -- add_carry (ufixed(a downto b), ufixed (c downto d)) -- = ufixed (maximum(a,c) downto minimum(b,d)) procedure add_carry ( L, R : in UNRESOLVED_ufixed; c_in : in STD_ULOGIC; result : out UNRESOLVED_ufixed; c_out : out STD_ULOGIC); -- add_carry (sfixed(a downto b), sfixed (c downto d)) -- = sfixed (maximum(a,c) downto minimum(b,d)) procedure add_carry ( L, R : in UNRESOLVED_sfixed; c_in : in STD_ULOGIC; result : out UNRESOLVED_sfixed; c_out : out STD_ULOGIC); -- Scales the result by a power of 2. Width of input = width of output with -- the binary point moved. function scalb (y : UNRESOLVED_ufixed; N : INTEGER) return UNRESOLVED_ufixed; function scalb (y : UNRESOLVED_ufixed; N : SIGNED) return UNRESOLVED_ufixed; function scalb (y : UNRESOLVED_sfixed; N : INTEGER) return UNRESOLVED_sfixed; function scalb (y : UNRESOLVED_sfixed; N : SIGNED) return UNRESOLVED_sfixed; function Is_Negative (arg : UNRESOLVED_sfixed) return BOOLEAN; --=========================================================================== -- Comparison Operators --=========================================================================== function ">" (l, r : UNRESOLVED_ufixed) return BOOLEAN; function ">" (l, r : UNRESOLVED_sfixed) return BOOLEAN; function "<" (l, r : UNRESOLVED_ufixed) return BOOLEAN; function "<" (l, r : UNRESOLVED_sfixed) return BOOLEAN; function "<=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; function "<=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; function ">=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; function ">=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; function "=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; function "=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; function "/=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; function "/=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; function \?=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?/=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?>\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?>=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?<\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?<=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?/=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?>\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?>=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?<\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?<=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; function std_match (l, r : UNRESOLVED_ufixed) return BOOLEAN; function std_match (l, r : UNRESOLVED_sfixed) return BOOLEAN; -- Overloads the default "maximum" and "minimum" function function maximum (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function minimum (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function maximum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function minimum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; ---------------------------------------------------------------------------- -- In these compare functions a natural is converted into a -- fixed point number of the bounds "maximum(l'high,0) downto 0" ---------------------------------------------------------------------------- function "=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; function "/=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; function ">=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; function "<=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; function ">" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; function "<" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; function "=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; function "/=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; function ">=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; function "<=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; function ">" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; function "<" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; function \?=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; function \?/=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; function \?>=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; function \?<=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; function \?>\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; function \?<\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; function \?=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?/=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?>=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?<=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?>\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?<\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function maximum (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; function minimum (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; function maximum (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function minimum (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; ---------------------------------------------------------------------------- -- In these compare functions a real is converted into a -- fixed point number of the bounds "l'high+1 downto l'low" ---------------------------------------------------------------------------- function "=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; function "/=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; function ">=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; function "<=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; function ">" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; function "<" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; function "=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; function "/=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; function ">=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; function "<=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; function ">" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; function "<" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; function \?=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; function \?/=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; function \?>=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; function \?<=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; function \?>\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; function \?<\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; function \?=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?/=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?>=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?<=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?>\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function \?<\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; function maximum (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; function maximum (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function minimum (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; function minimum (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; ---------------------------------------------------------------------------- -- In these compare functions an integer is converted into a -- fixed point number of the bounds "maximum(l'high,1) downto 0" ---------------------------------------------------------------------------- function "=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; function "/=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; function ">=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; function "<=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; function ">" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; function "<" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; function "=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; function "/=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; function ">=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; function "<=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; function ">" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; function "<" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; function \?=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; function \?/=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; function \?>=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; function \?<=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; function \?>\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; function \?<\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; function \?=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?/=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?>=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?<=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?>\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?<\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; function maximum (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; function maximum (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function minimum (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; function minimum (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; ---------------------------------------------------------------------------- -- In these compare functions a real is converted into a -- fixed point number of the bounds "l'high+1 downto l'low" ---------------------------------------------------------------------------- function "=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; function "/=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; function ">=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; function "<=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; function ">" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; function "<" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; function "=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; function "/=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; function ">=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; function "<=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; function ">" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; function "<" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; function \?=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; function \?/=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; function \?>=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; function \?<=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; function \?>\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; function \?<\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; function \?=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?/=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?>=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?<=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?>\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; function \?<\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; function maximum (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; function maximum (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function minimum (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; function minimum (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; --=========================================================================== -- Shift and Rotate Functions. -- Note that sra and sla are not the same as the BIT_VECTOR version --=========================================================================== function "sll" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed; function "srl" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed; function "rol" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed; function "ror" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed; function "sla" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed; function "sra" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed; function "sll" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed; function "srl" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed; function "rol" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed; function "ror" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed; function "sla" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed; function "sra" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed; function SHIFT_LEFT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) return UNRESOLVED_ufixed; function SHIFT_RIGHT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) return UNRESOLVED_ufixed; function SHIFT_LEFT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) return UNRESOLVED_sfixed; function SHIFT_RIGHT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) return UNRESOLVED_sfixed; ---------------------------------------------------------------------------- -- logical functions ---------------------------------------------------------------------------- function "not" (l : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "and" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "or" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "nand" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "nor" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "xor" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "xnor" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "not" (l : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "and" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "or" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "nand" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "nor" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "xor" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "xnor" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- Vector and std_ulogic functions, same as functions in numeric_std function "and" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "and" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) return UNRESOLVED_ufixed; function "or" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "or" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) return UNRESOLVED_ufixed; function "nand" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "nand" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) return UNRESOLVED_ufixed; function "nor" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "nor" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) return UNRESOLVED_ufixed; function "xor" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "xor" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) return UNRESOLVED_ufixed; function "xnor" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function "xnor" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) return UNRESOLVED_ufixed; function "and" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "and" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) return UNRESOLVED_sfixed; function "or" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "or" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) return UNRESOLVED_sfixed; function "nand" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "nand" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) return UNRESOLVED_sfixed; function "nor" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "nor" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) return UNRESOLVED_sfixed; function "xor" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "xor" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) return UNRESOLVED_sfixed; function "xnor" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function "xnor" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) return UNRESOLVED_sfixed; -- Reduction operators, same as numeric_std functions function and_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; function nand_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; function or_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; function nor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; function xor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; function xnor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; function and_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; function nand_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; function or_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; function nor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; function xor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; function xnor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; -- returns arg'low-1 if not found function find_leftmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) return INTEGER; function find_leftmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) return INTEGER; -- returns arg'high+1 if not found function find_rightmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) return INTEGER; function find_rightmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) return INTEGER; --=========================================================================== -- RESIZE Functions --=========================================================================== -- resizes the number (larger or smaller) -- The returned result will be ufixed (left_index downto right_index) -- If "round_style" is fixed_round, then the result will be rounded. -- If the MSB of the remainder is a "1" AND the LSB of the unrounded result -- is a '1' or the lower bits of the remainder include a '1' then the result -- will be increased by the smallest representable number for that type. -- "overflow_style" can be fixed_saturate or fixed_wrap. -- In saturate mode, if the number overflows then the largest possible -- representable number is returned. If wrap mode, then the upper bits -- of the number are truncated. function resize ( arg : UNRESOLVED_ufixed; -- input constant left_index : INTEGER; -- integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed; -- "size_res" functions create the size of the output from the length -- of the "size_res" input. The actual value of "size_res" is not used. function resize ( arg : UNRESOLVED_ufixed; -- input size_res : UNRESOLVED_ufixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed; -- Note that in "wrap" mode the sign bit is not replicated. Thus the -- resize of a negative number can have a positive result in wrap mode. function resize ( arg : UNRESOLVED_sfixed; -- input constant left_index : INTEGER; -- integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed; function resize ( arg : UNRESOLVED_sfixed; -- input size_res : UNRESOLVED_sfixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed; --=========================================================================== -- Conversion Functions --=========================================================================== -- integer (natural) to unsigned fixed point. -- arguments are the upper and lower bounds of the number, thus -- ufixed (7 downto -3) <= to_ufixed (int, 7, -3); function to_ufixed ( arg : NATURAL; -- integer constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER := 0; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed; function to_ufixed ( arg : NATURAL; -- integer size_res : UNRESOLVED_ufixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed; -- real to unsigned fixed point function to_ufixed ( arg : REAL; -- real constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed; function to_ufixed ( arg : REAL; -- real size_res : UNRESOLVED_ufixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed; -- unsigned to unsigned fixed point function to_ufixed ( arg : UNSIGNED; -- unsigned constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER := 0; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed; function to_ufixed ( arg : UNSIGNED; -- unsigned size_res : UNRESOLVED_ufixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed; -- Performs a conversion. ufixed (arg'range) is returned function to_ufixed ( arg : UNSIGNED) -- unsigned return UNRESOLVED_ufixed; -- Conversion from sfixed to ufixed (performs an "abs" function) function to_ufixed ( arg : UNRESOLVED_sfixed) return UNRESOLVED_ufixed; -- unsigned fixed point to unsigned function to_unsigned ( arg : UNRESOLVED_ufixed; -- fixed point input constant size : NATURAL; -- length of output constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNSIGNED; -- unsigned fixed point to unsigned function to_unsigned ( arg : UNRESOLVED_ufixed; -- fixed point input size_res : UNSIGNED; -- used for length of output constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNSIGNED; -- unsigned fixed point to real function to_real ( arg : UNRESOLVED_ufixed) -- fixed point input return REAL; -- unsigned fixed point to integer function to_integer ( arg : UNRESOLVED_ufixed; -- fixed point input constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return NATURAL; -- Integer to UNRESOLVED_sfixed function to_sfixed ( arg : INTEGER; -- integer constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER := 0; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed; function to_sfixed ( arg : INTEGER; -- integer size_res : UNRESOLVED_sfixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed; -- Real to sfixed function to_sfixed ( arg : REAL; -- real constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed; function to_sfixed ( arg : REAL; -- real size_res : UNRESOLVED_sfixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed; -- signed to sfixed function to_sfixed ( arg : SIGNED; -- signed constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER := 0; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed; function to_sfixed ( arg : SIGNED; -- signed size_res : UNRESOLVED_sfixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed; -- signed to sfixed (output assumed to be size of signed input) function to_sfixed ( arg : SIGNED) -- signed return UNRESOLVED_sfixed; -- Conversion from ufixed to sfixed function to_sfixed ( arg : UNRESOLVED_ufixed) return UNRESOLVED_sfixed; -- signed fixed point to signed function to_signed ( arg : UNRESOLVED_sfixed; -- fixed point input constant size : NATURAL; -- length of output constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return SIGNED; -- signed fixed point to signed function to_signed ( arg : UNRESOLVED_sfixed; -- fixed point input size_res : SIGNED; -- used for length of output constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return SIGNED; -- signed fixed point to real function to_real ( arg : UNRESOLVED_sfixed) -- fixed point input return REAL; -- signed fixed point to integer function to_integer ( arg : UNRESOLVED_sfixed; -- fixed point input constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return INTEGER; -- Because of the fairly complicated sizing rules in the fixed point -- packages these functions are provided to compute the result ranges -- Example: -- signal uf1 : ufixed (3 downto -3); -- signal uf2 : ufixed (4 downto -2); -- signal uf1multuf2 : ufixed (ufixed_high (3, -3, '*', 4, -2) downto -- ufixed_low (3, -3, '*', 4, -2)); -- uf1multuf2 <= uf1 * uf2; -- Valid characters: '+', '-', '*', '/', 'r' or 'R' (rem), 'm' or 'M' (mod), -- '1' (reciprocal), 'a' or 'A' (abs), 'n' or 'N' (unary -) function ufixed_high (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER; function ufixed_low (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER; function sfixed_high (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER; function sfixed_low (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER; -- Same as above, but using the "size_res" input only for their ranges: -- signal uf1multuf2 : ufixed (ufixed_high (uf1, '*', uf2) downto -- ufixed_low (uf1, '*', uf2)); -- uf1multuf2 <= uf1 * uf2; -- function ufixed_high (size_res : UNRESOLVED_ufixed; operation : CHARACTER := 'X'; size_res2 : UNRESOLVED_ufixed) return INTEGER; function ufixed_low (size_res : UNRESOLVED_ufixed; operation : CHARACTER := 'X'; size_res2 : UNRESOLVED_ufixed) return INTEGER; function sfixed_high (size_res : UNRESOLVED_sfixed; operation : CHARACTER := 'X'; size_res2 : UNRESOLVED_sfixed) return INTEGER; function sfixed_low (size_res : UNRESOLVED_sfixed; operation : CHARACTER := 'X'; size_res2 : UNRESOLVED_sfixed) return INTEGER; -- purpose: returns a saturated number function saturate ( constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_ufixed; -- purpose: returns a saturated number function saturate ( constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_sfixed; function saturate ( size_res : UNRESOLVED_ufixed) -- only the size of this is used return UNRESOLVED_ufixed; function saturate ( size_res : UNRESOLVED_sfixed) -- only the size of this is used return UNRESOLVED_sfixed; --=========================================================================== -- Translation Functions --=========================================================================== -- maps meta-logical values function to_01 ( s : UNRESOLVED_ufixed; -- fixed point input constant XMAP : STD_ULOGIC := '0') -- Map x to return UNRESOLVED_ufixed; -- maps meta-logical values function to_01 ( s : UNRESOLVED_sfixed; -- fixed point input constant XMAP : STD_ULOGIC := '0') -- Map x to return UNRESOLVED_sfixed; function Is_X (arg : UNRESOLVED_ufixed) return BOOLEAN; function Is_X (arg : UNRESOLVED_sfixed) return BOOLEAN; function to_X01 (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function to_X01 (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function to_X01Z (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function to_X01Z (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; function to_UX01 (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; function to_UX01 (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; -- straight vector conversion routines, needed for synthesis. -- These functions are here so that a std_logic_vector can be -- converted to and from sfixed and ufixed. Note that you can -- not convert these vectors because of their negative index. function to_slv ( arg : UNRESOLVED_ufixed) -- fixed point vector return STD_LOGIC_VECTOR; alias to_StdLogicVector is to_slv [UNRESOLVED_ufixed return STD_LOGIC_VECTOR]; alias to_Std_Logic_Vector is to_slv [UNRESOLVED_ufixed return STD_LOGIC_VECTOR]; function to_slv ( arg : UNRESOLVED_sfixed) -- fixed point vector return STD_LOGIC_VECTOR; alias to_StdLogicVector is to_slv [UNRESOLVED_sfixed return STD_LOGIC_VECTOR]; alias to_Std_Logic_Vector is to_slv [UNRESOLVED_sfixed return STD_LOGIC_VECTOR]; function to_suv ( arg : UNRESOLVED_ufixed) -- fixed point vector return STD_ULOGIC_VECTOR; alias to_StdULogicVector is to_suv [UNRESOLVED_ufixed return STD_ULOGIC_VECTOR]; alias to_Std_ULogic_Vector is to_suv [UNRESOLVED_ufixed return STD_ULOGIC_VECTOR]; function to_suv ( arg : UNRESOLVED_sfixed) -- fixed point vector return STD_ULOGIC_VECTOR; alias to_StdULogicVector is to_suv [UNRESOLVED_sfixed return STD_ULOGIC_VECTOR]; alias to_Std_ULogic_Vector is to_suv [UNRESOLVED_sfixed return STD_ULOGIC_VECTOR]; function to_ufixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_ufixed; function to_ufixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector size_res : UNRESOLVED_ufixed) -- for size only return UNRESOLVED_ufixed; function to_sfixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_sfixed; function to_sfixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector size_res : UNRESOLVED_sfixed) -- for size only return UNRESOLVED_sfixed; -- As a concession to those who use a graphical DSP environment, -- these functions take parameters in those tools format and create -- fixed point numbers. These functions are designed to convert from -- a std_logic_vector to the VHDL fixed point format using the conventions -- of these packages. In a pure VHDL environment you should use the -- "to_ufixed" and "to_sfixed" routines. -- unsigned fixed point function to_UFix ( arg : STD_ULOGIC_VECTOR; width : NATURAL; -- width of vector fraction : NATURAL) -- width of fraction return UNRESOLVED_ufixed; -- signed fixed point function to_SFix ( arg : STD_ULOGIC_VECTOR; width : NATURAL; -- width of vector fraction : NATURAL) -- width of fraction return UNRESOLVED_sfixed; -- finding the bounds of a number. These functions can be used like this: -- signal xxx : ufixed (7 downto -3); -- -- Which is the same as "ufixed (UFix_high (11,3) downto UFix_low(11,3))" -- signal yyy : ufixed (UFix_high (11, 3, "+", 11, 3) -- downto UFix_low(11, 3, "+", 11, 3)); -- Where "11" is the width of xxx (xxx'length), -- and 3 is the lower bound (abs (xxx'low)) -- In a pure VHDL environment use "ufixed_high" and "ufixed_low" function UFix_high (width, fraction : NATURAL; operation : CHARACTER := 'X'; width2, fraction2 : NATURAL := 0) return INTEGER; function UFix_low (width, fraction : NATURAL; operation : CHARACTER := 'X'; width2, fraction2 : NATURAL := 0) return INTEGER; -- Same as above but for signed fixed point. Note that the width -- of a signed fixed point number ignores the sign bit, thus -- width = sxxx'length-1 function SFix_high (width, fraction : NATURAL; operation : CHARACTER := 'X'; width2, fraction2 : NATURAL := 0) return INTEGER; function SFix_low (width, fraction : NATURAL; operation : CHARACTER := 'X'; width2, fraction2 : NATURAL := 0) return INTEGER; -- rtl_synthesis off -- pragma synthesis_off --=========================================================================== -- string and textio Functions --=========================================================================== -- purpose: writes fixed point into a line procedure WRITE ( L : inout LINE; -- input line VALUE : in UNRESOLVED_ufixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); -- purpose: writes fixed point into a line procedure WRITE ( L : inout LINE; -- input line VALUE : in UNRESOLVED_sfixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); procedure READ(L : inout LINE; VALUE : out UNRESOLVED_ufixed); procedure READ(L : inout LINE; VALUE : out UNRESOLVED_ufixed; GOOD : out BOOLEAN); procedure READ(L : inout LINE; VALUE : out UNRESOLVED_sfixed); procedure READ(L : inout LINE; VALUE : out UNRESOLVED_sfixed; GOOD : out BOOLEAN); alias bwrite is WRITE [LINE, UNRESOLVED_ufixed, SIDE, width]; alias bwrite is WRITE [LINE, UNRESOLVED_sfixed, SIDE, width]; alias bread is READ [LINE, UNRESOLVED_ufixed]; alias bread is READ [LINE, UNRESOLVED_ufixed, BOOLEAN]; alias bread is READ [LINE, UNRESOLVED_sfixed]; alias bread is READ [LINE, UNRESOLVED_sfixed, BOOLEAN]; alias BINARY_WRITE is WRITE [LINE, UNRESOLVED_ufixed, SIDE, width]; alias BINARY_WRITE is WRITE [LINE, UNRESOLVED_sfixed, SIDE, width]; alias BINARY_READ is READ [LINE, UNRESOLVED_ufixed, BOOLEAN]; alias BINARY_READ is READ [LINE, UNRESOLVED_ufixed]; alias BINARY_READ is READ [LINE, UNRESOLVED_sfixed, BOOLEAN]; alias BINARY_READ is READ [LINE, UNRESOLVED_sfixed]; -- octal read and write procedure OWRITE ( L : inout LINE; -- input line VALUE : in UNRESOLVED_ufixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); procedure OWRITE ( L : inout LINE; -- input line VALUE : in UNRESOLVED_sfixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); procedure OREAD(L : inout LINE; VALUE : out UNRESOLVED_ufixed); procedure OREAD(L : inout LINE; VALUE : out UNRESOLVED_ufixed; GOOD : out BOOLEAN); procedure OREAD(L : inout LINE; VALUE : out UNRESOLVED_sfixed); procedure OREAD(L : inout LINE; VALUE : out UNRESOLVED_sfixed; GOOD : out BOOLEAN); alias OCTAL_READ is OREAD [LINE, UNRESOLVED_ufixed, BOOLEAN]; alias OCTAL_READ is OREAD [LINE, UNRESOLVED_ufixed]; alias OCTAL_READ is OREAD [LINE, UNRESOLVED_sfixed, BOOLEAN]; alias OCTAL_READ is OREAD [LINE, UNRESOLVED_sfixed]; alias OCTAL_WRITE is OWRITE [LINE, UNRESOLVED_ufixed, SIDE, WIDTH]; alias OCTAL_WRITE is OWRITE [LINE, UNRESOLVED_sfixed, SIDE, WIDTH]; -- hex read and write procedure HWRITE ( L : inout LINE; -- input line VALUE : in UNRESOLVED_ufixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); -- purpose: writes fixed point into a line procedure HWRITE ( L : inout LINE; -- input line VALUE : in UNRESOLVED_sfixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); procedure HREAD(L : inout LINE; VALUE : out UNRESOLVED_ufixed); procedure HREAD(L : inout LINE; VALUE : out UNRESOLVED_ufixed; GOOD : out BOOLEAN); procedure HREAD(L : inout LINE; VALUE : out UNRESOLVED_sfixed); procedure HREAD(L : inout LINE; VALUE : out UNRESOLVED_sfixed; GOOD : out BOOLEAN); alias HEX_READ is HREAD [LINE, UNRESOLVED_ufixed, BOOLEAN]; alias HEX_READ is HREAD [LINE, UNRESOLVED_sfixed, BOOLEAN]; alias HEX_READ is HREAD [LINE, UNRESOLVED_ufixed]; alias HEX_READ is HREAD [LINE, UNRESOLVED_sfixed]; alias HEX_WRITE is HWRITE [LINE, UNRESOLVED_ufixed, SIDE, WIDTH]; alias HEX_WRITE is HWRITE [LINE, UNRESOLVED_sfixed, SIDE, WIDTH]; -- returns a string, useful for: -- assert (x = y) report "error found " & to_string(x) severity error; function to_string (value : UNRESOLVED_ufixed) return STRING; alias to_bstring is to_string [UNRESOLVED_ufixed return STRING]; alias TO_BINARY_STRING is TO_STRING [UNRESOLVED_ufixed return STRING]; function to_ostring (value : UNRESOLVED_ufixed) return STRING; alias TO_OCTAL_STRING is TO_OSTRING [UNRESOLVED_ufixed return STRING]; function to_hstring (value : UNRESOLVED_ufixed) return STRING; alias TO_HEX_STRING is TO_HSTRING [UNRESOLVED_ufixed return STRING]; function to_string (value : UNRESOLVED_sfixed) return STRING; alias to_bstring is to_string [UNRESOLVED_sfixed return STRING]; alias TO_BINARY_STRING is TO_STRING [UNRESOLVED_sfixed return STRING]; function to_ostring (value : UNRESOLVED_sfixed) return STRING; alias TO_OCTAL_STRING is TO_OSTRING [UNRESOLVED_sfixed return STRING]; function to_hstring (value : UNRESOLVED_sfixed) return STRING; alias TO_HEX_STRING is TO_HSTRING [UNRESOLVED_sfixed return STRING]; -- From string functions allow you to convert a string into a fixed -- point number. Example: -- signal uf1 : ufixed (3 downto -3); -- uf1 <= from_string ("0110.100", uf1'high, uf1'low); -- 6.5 -- The "." is optional in this syntax, however it exist and is -- in the wrong location an error is produced. Overflow will -- result in saturation. function from_string ( bstring : STRING; -- binary string constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_ufixed; alias from_bstring is from_string [STRING, INTEGER, INTEGER return UNRESOLVED_ufixed]; alias from_binary_string is from_string [STRING, INTEGER, INTEGER return UNRESOLVED_ufixed]; -- Octal and hex conversions work as follows: -- uf1 <= from_hstring ("6.8", 3, -3); -- 6.5 (bottom zeros dropped) -- uf1 <= from_ostring ("06.4", 3, -3); -- 6.5 (top zeros dropped) function from_ostring ( ostring : STRING; -- Octal string constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_ufixed; alias from_octal_string is from_ostring [STRING, INTEGER, INTEGER return UNRESOLVED_ufixed]; function from_hstring ( hstring : STRING; -- hex string constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_ufixed; alias from_hex_string is from_hstring [STRING, INTEGER, INTEGER return UNRESOLVED_ufixed]; function from_string ( bstring : STRING; -- binary string constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_sfixed; alias from_bstring is from_string [STRING, INTEGER, INTEGER return UNRESOLVED_sfixed]; alias from_binary_string is from_string [STRING, INTEGER, INTEGER return UNRESOLVED_sfixed]; function from_ostring ( ostring : STRING; -- Octal string constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_sfixed; alias from_octal_string is from_ostring [STRING, INTEGER, INTEGER return UNRESOLVED_sfixed]; function from_hstring ( hstring : STRING; -- hex string constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_sfixed; alias from_hex_string is from_hstring [STRING, INTEGER, INTEGER return UNRESOLVED_sfixed]; -- Same as above, "size_res" is used for it's range only. function from_string ( bstring : STRING; -- binary string size_res : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; alias from_bstring is from_string [STRING, UNRESOLVED_ufixed return UNRESOLVED_ufixed]; alias from_binary_string is from_string [STRING, UNRESOLVED_ufixed return UNRESOLVED_ufixed]; function from_ostring ( ostring : STRING; -- Octal string size_res : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; alias from_octal_string is from_ostring [STRING, UNRESOLVED_ufixed return UNRESOLVED_ufixed]; function from_hstring ( hstring : STRING; -- hex string size_res : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; alias from_hex_string is from_hstring [STRING, UNRESOLVED_ufixed return UNRESOLVED_ufixed]; function from_string ( bstring : STRING; -- binary string size_res : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; alias from_bstring is from_string [STRING, UNRESOLVED_sfixed return UNRESOLVED_sfixed]; alias from_binary_string is from_string [STRING, UNRESOLVED_sfixed return UNRESOLVED_sfixed]; function from_ostring ( ostring : STRING; -- Octal string size_res : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; alias from_octal_string is from_ostring [STRING, UNRESOLVED_sfixed return UNRESOLVED_sfixed]; function from_hstring ( hstring : STRING; -- hex string size_res : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; alias from_hex_string is from_hstring [STRING, UNRESOLVED_sfixed return UNRESOLVED_sfixed]; -- Direct conversion functions. Example: -- signal uf1 : ufixed (3 downto -3); -- uf1 <= from_string ("0110.100"); -- 6.5 -- In this case the "." is not optional, and the size of -- the output must match exactly. function from_string ( bstring : STRING) -- binary string return UNRESOLVED_ufixed; alias from_bstring is from_string [STRING return UNRESOLVED_ufixed]; alias from_binary_string is from_string [STRING return UNRESOLVED_ufixed]; -- Direct octal and hex conversion functions. In this case -- the string lengths must match. Example: -- signal sf1 := sfixed (5 downto -3); -- sf1 <= from_ostring ("71.4") -- -6.5 function from_ostring ( ostring : STRING) -- Octal string return UNRESOLVED_ufixed; alias from_octal_string is from_ostring [STRING return UNRESOLVED_ufixed]; function from_hstring ( hstring : STRING) -- hex string return UNRESOLVED_ufixed; alias from_hex_string is from_hstring [STRING return UNRESOLVED_ufixed]; function from_string ( bstring : STRING) -- binary string return UNRESOLVED_sfixed; alias from_bstring is from_string [STRING return UNRESOLVED_sfixed]; alias from_binary_string is from_string [STRING return UNRESOLVED_sfixed]; function from_ostring ( ostring : STRING) -- Octal string return UNRESOLVED_sfixed; alias from_octal_string is from_ostring [STRING return UNRESOLVED_sfixed]; function from_hstring ( hstring : STRING) -- hex string return UNRESOLVED_sfixed; alias from_hex_string is from_hstring [STRING return UNRESOLVED_sfixed]; -- rtl_synthesis on -- pragma synthesis_on -- IN VHDL-2006 std_logic_vector is a subtype of std_ulogic_vector, so these -- extra functions are needed for compatability. function to_ufixed ( arg : STD_LOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_ufixed; function to_ufixed ( arg : STD_LOGIC_VECTOR; -- shifted vector size_res : UNRESOLVED_ufixed) -- for size only return UNRESOLVED_ufixed; function to_sfixed ( arg : STD_LOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_sfixed; function to_sfixed ( arg : STD_LOGIC_VECTOR; -- shifted vector size_res : UNRESOLVED_sfixed) -- for size only return UNRESOLVED_sfixed; -- unsigned fixed point function to_UFix ( arg : STD_LOGIC_VECTOR; width : NATURAL; -- width of vector fraction : NATURAL) -- width of fraction return UNRESOLVED_ufixed; -- signed fixed point function to_SFix ( arg : STD_LOGIC_VECTOR; width : NATURAL; -- width of vector fraction : NATURAL) -- width of fraction return UNRESOLVED_sfixed; end package fixed_pkg; ------------------------------------------------------------------------------- -- Proposed package body for the VHDL-200x-FT fixed_pkg package -- (Fixed point math package) -- This package body supplies a recommended implementation of these functions -- Version : $Revision: 1.17 $ -- Date : $Date: 2007-05-31 14:52:33-04 $ -- -- Created for VHDL-200X-ft, David Bishop (dbishop@vhdl.org) ------------------------------------------------------------------------------- library IEEE; use IEEE.MATH_REAL.all; package body fixed_pkg is -- Author David Bishop (dbishop@vhdl.org) -- Other contributers: Jim Lewis, Yannick Grugni, Ryan W. Hilton -- null array constants constant NAUF : UNRESOLVED_ufixed (0 downto 1) := (others => '0'); constant NASF : UNRESOLVED_sfixed (0 downto 1) := (others => '0'); constant NSLV : STD_ULOGIC_VECTOR (0 downto 1) := (others => '0'); -- This differed constant will tell you if the package body is synthesizable -- or implemented as real numbers, set to "true" if synthesizable. constant fixedsynth_or_real : BOOLEAN := true; -- %%% Replicated functions function maximum ( l, r : integer) -- inputs return integer is begin -- function max if l > r then return l; else return r; end if; end function maximum; function minimum ( l, r : integer) -- inputs return integer is begin -- function min if l > r then return r; else return l; end if; end function minimum; function "sra" (arg : SIGNED; count : INTEGER) return SIGNED is begin if (COUNT >= 0) then return SHIFT_RIGHT(arg, count); else return SHIFT_LEFT(arg, -count); end if; end function "sra"; function or_reduce (arg : STD_ULOGIC_VECTOR) return STD_LOGIC is variable Upper, Lower : STD_ULOGIC; variable Half : INTEGER; variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); variable Result : STD_ULOGIC; begin if (arg'length < 1) then -- In the case of a NULL range Result := '0'; else 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) or BUS_int (BUS_int'left); else Half := (BUS_int'length + 1) / 2 + BUS_int'right; Upper := or_reduce (BUS_int (BUS_int'left downto Half)); Lower := or_reduce (BUS_int (Half - 1 downto BUS_int'right)); Result := Upper or Lower; end if; end if; return Result; end function or_reduce; -- purpose: AND all of the bits in a vector together -- This is a copy of the proposed "and_reduce" from 1076.3 function and_reduce (arg : STD_ULOGIC_VECTOR) return STD_LOGIC is variable Upper, Lower : STD_ULOGIC; variable Half : INTEGER; variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); variable Result : STD_ULOGIC; begin if (arg'length < 1) then -- In the case of a NULL range Result := '1'; else 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) and BUS_int (BUS_int'left); else Half := (BUS_int'length + 1) / 2 + BUS_int'right; Upper := and_reduce (BUS_int (BUS_int'left downto Half)); Lower := and_reduce (BUS_int (Half - 1 downto BUS_int'right)); Result := Upper and Lower; end if; end if; return Result; end function and_reduce; function xor_reduce (arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is variable Upper, Lower : STD_ULOGIC; variable Half : INTEGER; variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); 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; -- 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 begin return match_logic_table (l, r); end function \?=\; function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is begin return no_match_logic_table (l, r); end function \?/=\; -- "?=" operator is similar to "std_match", but returns a std_ulogic.. -- Id: M.2B function \?=\ (L, R: UNSIGNED) return STD_ULOGIC is constant L_LEFT : INTEGER := L'LENGTH-1; constant R_LEFT : INTEGER := R'LENGTH-1; alias XL : UNSIGNED(L_LEFT downto 0) is L; alias XR : UNSIGNED(R_LEFT downto 0) is R; constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); variable LX : UNSIGNED(SIZE-1 downto 0); variable RX : UNSIGNED(SIZE-1 downto 0); variable result, result1 : STD_ULOGIC; -- result begin -- Logically identical to an "=" operator. if ((L'LENGTH < 1) or (R'LENGTH < 1)) then assert NO_WARNING report "NUMERIC_STD.""?="": null detected, returning X" severity warning; return 'X'; else LX := RESIZE(XL, SIZE); RX := RESIZE(XR, SIZE); result := '1'; for i in LX'low to LX'high loop result1 := \?=\(LX(i), RX(i)); if result1 = 'U' then return 'U'; elsif result1 = 'X' or result = 'X' then result := 'X'; else result := result and result1; end if; end loop; return result; end if; end function \?=\; -- Id: M.3B function \?=\ (L, R: SIGNED) return std_ulogic is constant L_LEFT : INTEGER := L'LENGTH-1; constant R_LEFT : INTEGER := R'LENGTH-1; alias XL : SIGNED(L_LEFT downto 0) is L; alias XR : SIGNED(R_LEFT downto 0) is R; constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); variable LX : SIGNED(SIZE-1 downto 0); variable RX : SIGNED(SIZE-1 downto 0); variable result, result1 : STD_ULOGIC; -- result begin -- ?= if ((L'LENGTH < 1) or (R'LENGTH < 1)) then assert NO_WARNING report "NUMERIC_STD.""?="": null detected, returning X" severity warning; return 'X'; else LX := RESIZE(XL, SIZE); RX := RESIZE(XR, SIZE); result := '1'; for i in LX'low to LX'high loop result1 := \?=\ (LX(i), RX(i)); if result1 = 'U' then return 'U'; elsif result1 = 'X' or result = 'X' then result := 'X'; else result := result and result1; end if; end loop; return result; end if; end function \?=\; function \?/=\ (L, R : UNSIGNED) return std_ulogic is constant L_LEFT : INTEGER := L'LENGTH-1; constant R_LEFT : INTEGER := R'LENGTH-1; alias XL : UNSIGNED(L_LEFT downto 0) is L; alias XR : UNSIGNED(R_LEFT downto 0) is R; constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); variable LX : UNSIGNED(SIZE-1 downto 0); variable RX : UNSIGNED(SIZE-1 downto 0); variable result, result1 : STD_ULOGIC; -- result begin -- ?= if ((L'LENGTH < 1) or (R'LENGTH < 1)) then assert NO_WARNING report "NUMERIC_STD.""?/="": null detected, returning X" severity warning; return 'X'; else LX := RESIZE(XL, SIZE); RX := RESIZE(XR, SIZE); result := '0'; for i in LX'low to LX'high loop result1 := \?/=\ (LX(i), RX(i)); if result1 = 'U' then return 'U'; elsif result1 = 'X' or result = 'X' then result := 'X'; else result := result or result1; end if; end loop; return result; end if; end function \?/=\; function \?/=\ (L, R : SIGNED) return std_ulogic is constant L_LEFT : INTEGER := L'LENGTH-1; constant R_LEFT : INTEGER := R'LENGTH-1; alias XL : SIGNED(L_LEFT downto 0) is L; alias XR : SIGNED(R_LEFT downto 0) is R; constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); variable LX : SIGNED(SIZE-1 downto 0); variable RX : SIGNED(SIZE-1 downto 0); variable result, result1 : STD_ULOGIC; -- result begin -- ?= if ((L'LENGTH < 1) or (R'LENGTH < 1)) then assert NO_WARNING report "NUMERIC_STD.""?/="": null detected, returning X" severity warning; return 'X'; else LX := RESIZE(XL, SIZE); RX := RESIZE(XR, SIZE); result := '0'; for i in LX'low to LX'high loop result1 := \?/=\ (LX(i), RX(i)); if result1 = 'U' then return 'U'; elsif result1 = 'X' or result = 'X' then result := 'X'; else result := result or result1; end if; end loop; return result; end if; 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; function \?>\ (L, R : UNSIGNED) return STD_ULOGIC is begin if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "NUMERIC_STD.""?>"": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then report "NUMERIC_STD.""?>"": '-' found in compare string" severity error; return 'X'; end if; end loop; for i in R'range loop if R(i) = '-' then report "NUMERIC_STD.""?>"": '-' found in compare string" severity error; return 'X'; end if; end loop; if is_x(l) or is_x(r) then return 'X'; elsif l > r then return '1'; else return '0'; end if; end if; end function \?>\; -- %%% function "?>" (L, R : UNSIGNED) return std_ulogic is -- %%% end function "?>"\; function \?>\ (L, R : SIGNED) return STD_ULOGIC is begin if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "NUMERIC_STD.""?>"": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then report "NUMERIC_STD.""?>"": '-' found in compare string" severity error; return 'X'; end if; end loop; for i in R'range loop if R(i) = '-' then report "NUMERIC_STD.""?>"": '-' found in compare string" severity error; return 'X'; end if; end loop; if is_x(l) or is_x(r) then return 'X'; elsif l > r then return '1'; else return '0'; end if; end if; end function \?>\; function \?>=\ (L, R : UNSIGNED) return STD_ULOGIC is begin if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "NUMERIC_STD.""?>="": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then report "NUMERIC_STD.""?>="": '-' found in compare string" severity error; return 'X'; end if; end loop; for i in R'range loop if R(i) = '-' then report "NUMERIC_STD.""?>="": '-' found in compare string" severity error; return 'X'; end if; end loop; if is_x(l) or is_x(r) then return 'X'; elsif l >= r then return '1'; else return '0'; end if; end if; end function \?>=\; -- %%% function "?>=" (L, R : UNSIGNED) return std_ulogic is -- %%% end function "?>="; function \?>=\ (L, R : SIGNED) return STD_ULOGIC is begin if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "NUMERIC_STD.""?>="": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then report "NUMERIC_STD.""?>="": '-' found in compare string" severity error; return 'X'; end if; end loop; for i in R'range loop if R(i) = '-' then report "NUMERIC_STD.""?>="": '-' found in compare string" severity error; return 'X'; end if; end loop; if is_x(l) or is_x(r) then return 'X'; elsif l >= r then return '1'; else return '0'; end if; end if; end function \?>=\; function \?<\ (L, R : UNSIGNED) return STD_ULOGIC is begin if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "NUMERIC_STD.""?<"": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then report "NUMERIC_STD.""?<"": '-' found in compare string" severity error; return 'X'; end if; end loop; for i in R'range loop if R(i) = '-' then report "NUMERIC_STD.""?<"": '-' found in compare string" severity error; return 'X'; end if; end loop; if is_x(l) or is_x(r) then return 'X'; elsif l < r then return '1'; else return '0'; end if; end if; end function \?<\; -- %%% function "?<" (L, R : UNSIGNED) return std_ulogic is -- %%% end function "?<"; function \?<\ (L, R : SIGNED) return STD_ULOGIC is begin if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "NUMERIC_STD.""?<"": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then report "NUMERIC_STD.""?<"": '-' found in compare string" severity error; return 'X'; end if; end loop; for i in R'range loop if R(i) = '-' then report "NUMERIC_STD.""?<"": '-' found in compare string" severity error; return 'X'; end if; end loop; if is_x(l) or is_x(r) then return 'X'; elsif l < r then return '1'; else return '0'; end if; end if; end function \?<\; function \?<=\ (L, R : UNSIGNED) return STD_ULOGIC is begin if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "NUMERIC_STD.""?<="": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then report "NUMERIC_STD.""?<="": '-' found in compare string" severity error; return 'X'; end if; end loop; for i in R'range loop if R(i) = '-' then report "NUMERIC_STD.""?<="": '-' found in compare string" severity error; return 'X'; end if; end loop; if is_x(l) or is_x(r) then return 'X'; elsif l <= r then return '1'; else return '0'; end if; end if; end function \?<=\; -- %%% function "?<=" (L, R : UNSIGNED) return std_ulogic is -- %%% end function "?<="; function \?<=\ (L, R : SIGNED) return STD_ULOGIC is begin if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "NUMERIC_STD.""?<="": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then report "NUMERIC_STD.""?<="": '-' found in compare string" severity error; return 'X'; end if; end loop; for i in R'range loop if R(i) = '-' then report "NUMERIC_STD.""?<="": '-' found in compare string" severity error; return 'X'; end if; end loop; if is_x(l) or is_x(r) then return 'X'; elsif l <= r then return '1'; else return '0'; end if; end if; end function \?<=\; -- %%% END replicated functions -- Special version of "minimum" to do some boundary checking without errors function mins (l, r : INTEGER) return INTEGER is begin -- function mins if (L = INTEGER'low or R = INTEGER'low) then return 0; -- error condition, silent end if; return minimum (L, R); end function mins; -- Special version of "minimum" to do some boundary checking with errors function mine (l, r : INTEGER) return INTEGER is begin -- function mine if (L = INTEGER'low or R = INTEGER'low) then report fixed_pkg'instance_name & " Unbounded number passed, was a literal used?" severity error; return 0; end if; return minimum (L, R); end function mine; -- The following functions are used only internally. Every function -- calls "cleanvec" either directly or indirectly. -- purpose: Fixes "downto" problem and resolves meta states function cleanvec ( arg : UNRESOLVED_sfixed) -- input return UNRESOLVED_sfixed is constant left_index : INTEGER := maximum(arg'left, arg'right); constant right_index : INTEGER := mins(arg'left, arg'right); variable result : UNRESOLVED_sfixed (arg'range); begin -- function cleanvec assert not (arg'ascending and (arg'low /= INTEGER'low)) report fixed_pkg'instance_name & " Vector passed using a ""to"" range, expected is ""downto""" severity error; return arg; end function cleanvec; -- purpose: Fixes "downto" problem and resolves meta states function cleanvec ( arg : UNRESOLVED_ufixed) -- input return UNRESOLVED_ufixed is constant left_index : INTEGER := maximum(arg'left, arg'right); constant right_index : INTEGER := mins(arg'left, arg'right); variable result : UNRESOLVED_ufixed (arg'range); begin -- function cleanvec assert not (arg'ascending and (arg'low /= INTEGER'low)) report fixed_pkg'instance_name & " Vector passed using a ""to"" range, expected is ""downto""" severity error; return arg; end function cleanvec; -- Type convert a "unsigned" into a "ufixed", used internally function to_fixed ( arg : UNSIGNED; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (left_index downto right_index); begin -- function to_fixed result := UNRESOLVED_ufixed(arg); return result; end function to_fixed; -- Type convert a "signed" into an "sfixed", used internally function to_fixed ( arg : SIGNED; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (left_index downto right_index); begin -- function to_fixed result := UNRESOLVED_sfixed(arg); return result; end function to_fixed; -- Type convert a "ufixed" into an "unsigned", used internally function to_uns ( arg : UNRESOLVED_ufixed) -- fp vector return UNSIGNED is subtype t is UNSIGNED(arg'high - arg'low downto 0); variable slv : t; begin -- function to_uns slv := t(arg); return slv; end function to_uns; -- Type convert an "sfixed" into a "signed", used internally function to_s ( arg : UNRESOLVED_sfixed) -- fp vector return SIGNED is subtype t is SIGNED(arg'high - arg'low downto 0); variable slv : t; begin -- function to_s slv := t(arg); return slv; end function to_s; -- adds 1 to the LSB of the number procedure round_up (arg : in UNRESOLVED_ufixed; result : out UNRESOLVED_ufixed; overflowx : out BOOLEAN) is variable arguns, resuns : UNSIGNED (arg'high-arg'low+1 downto 0) := (others => '0'); begin -- round_up arguns (arguns'high-1 downto 0) := to_uns (arg); resuns := arguns + 1; result := to_fixed(resuns(arg'high-arg'low downto 0), arg'high, arg'low); overflowx := (resuns(resuns'high) = '1'); end procedure round_up; -- adds 1 to the LSB of the number procedure round_up (arg : in UNRESOLVED_sfixed; result : out UNRESOLVED_sfixed; overflowx : out BOOLEAN) is variable args, ress : SIGNED (arg'high-arg'low+1 downto 0); begin -- round_up args (args'high-1 downto 0) := to_s (arg); args(args'high) := arg(arg'high); -- sign extend ress := args + 1; result := to_fixed(ress (ress'high-1 downto 0), arg'high, arg'low); overflowx := ((arg(arg'high) /= ress(ress'high-1)) and (or_reduce (STD_ULOGIC_VECTOR(ress)) /= '0')); end procedure round_up; -- Rounding - Performs a "round_nearest" (IEEE 754) which rounds up -- when the remainder is > 0.5. If the remainder IS 0.5 then if the -- bottom bit is a "1" it is rounded, otherwise it remains the same. function round_fixed (arg : UNRESOLVED_ufixed; remainder : UNRESOLVED_ufixed; overflow_style : fixed_overflow_style_type := fixed_overflow_style) return UNRESOLVED_ufixed is variable rounds : BOOLEAN; variable round_overflow : BOOLEAN; variable result : UNRESOLVED_ufixed (arg'range); begin rounds := false; if (remainder'length > 1) then if (remainder (remainder'high) = '1') then rounds := (arg(arg'low) = '1') or (or_reduce (to_suv(remainder(remainder'high-1 downto remainder'low))) = '1'); end if; else rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); end if; if rounds then round_up(arg => arg, result => result, overflowx => round_overflow); else result := arg; end if; if (overflow_style = fixed_saturate) and round_overflow then result := saturate (result'high, result'low); end if; return result; end function round_fixed; -- Rounding case statement function round_fixed (arg : UNRESOLVED_sfixed; remainder : UNRESOLVED_sfixed; overflow_style : fixed_overflow_style_type := fixed_overflow_style) return UNRESOLVED_sfixed is variable rounds : BOOLEAN; variable round_overflow : BOOLEAN; variable result : UNRESOLVED_sfixed (arg'range); begin rounds := false; if (remainder'length > 1) then if (remainder (remainder'high) = '1') then rounds := (arg(arg'low) = '1') or (or_reduce (to_suv(remainder(remainder'high-1 downto remainder'low))) = '1'); end if; else rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); end if; if rounds then round_up(arg => arg, result => result, overflowx => round_overflow); else result := arg; end if; if round_overflow then if (overflow_style = fixed_saturate) then if arg(arg'high) = '0' then result := saturate (result'high, result'low); else result := not saturate (result'high, result'low); end if; -- Sign bit not fixed when wrapping end if; end if; return result; end function round_fixed; ----------------------------------------------------------------------------- -- Visible functions ----------------------------------------------------------------------------- -- Conversion functions. These are needed for synthesis where typically -- the only input and output type is a std_logic_vector. function to_suv ( arg : UNRESOLVED_ufixed) -- fixed point vector return STD_ULOGIC_VECTOR is variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0); begin if arg'length < 1 then return NSLV; end if; result := STD_ULOGIC_VECTOR (arg); return result; end function to_suv; function to_suv ( arg : UNRESOLVED_sfixed) -- fixed point vector return STD_ULOGIC_VECTOR is variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0); begin if arg'length < 1 then return NSLV; end if; result := STD_ULOGIC_VECTOR (arg); return result; end function to_suv; function to_slv ( arg : UNRESOLVED_ufixed) -- fixed point vector return STD_LOGIC_VECTOR is begin return to_stdlogicvector(to_suv(arg)); end function to_slv; function to_slv ( arg : UNRESOLVED_sfixed) -- fixed point vector return STD_LOGIC_VECTOR is begin return to_stdlogicvector(to_suv(arg)); end function to_slv; function to_ufixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return unresolved_ufixed is variable result : UNRESOLVED_ufixed (left_index downto right_index); begin if (arg'length < 1 or right_index > left_index) then return NAUF; end if; if (arg'length /= result'length) then report fixed_pkg'instance_name & "TO_UFIXED(SLV) " & "Vector lengths do not match. Input length is " & INTEGER'image(arg'length) & " and output will be " & INTEGER'image(result'length) & " wide." severity error; return NAUF; else result := to_fixed (arg => UNSIGNED(arg), left_index => left_index, right_index => right_index); return result; end if; end function to_ufixed; function to_sfixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return unresolved_sfixed is variable result : UNRESOLVED_sfixed (left_index downto right_index); begin if (arg'length < 1 or right_index > left_index) then return NASF; end if; if (arg'length /= result'length) then report fixed_pkg'instance_name & "TO_SFIXED(SLV) " & "Vector lengths do not match. Input length is " & INTEGER'image(arg'length) & " and output will be " & INTEGER'image(result'length) & " wide." severity error; return NASF; else result := to_fixed (arg => SIGNED(arg), left_index => left_index, right_index => right_index); return result; end if; end function to_sfixed; -- Two's complement number, Grows the vector by 1 bit. -- because "abs (1000.000) = 01000.000" or abs(-16) = 16. function "abs" ( arg : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is constant left_index : INTEGER := arg'high; constant right_index : INTEGER := mine(arg'low, arg'low); variable ressns : SIGNED (arg'length downto 0); variable result : UNRESOLVED_sfixed (left_index+1 downto right_index); begin if (arg'length < 1 or result'length < 1) then return NASF; end if; ressns (arg'length-1 downto 0) := to_s (cleanvec (arg)); ressns (arg'length) := ressns (arg'length-1); -- expand sign bit result := to_fixed (abs(ressns), left_index+1, right_index); return result; end function "abs"; -- also grows the vector by 1 bit. function "-" ( arg : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is constant left_index : INTEGER := arg'high+1; constant right_index : INTEGER := mine(arg'low, arg'low); variable ressns : SIGNED (arg'length downto 0); variable result : UNRESOLVED_sfixed (left_index downto right_index); begin if (arg'length < 1 or result'length < 1) then return NASF; end if; ressns (arg'length-1 downto 0) := to_s (cleanvec(arg)); ressns (arg'length) := ressns (arg'length-1); -- expand sign bit result := to_fixed (-ressns, left_index, right_index); return result; end function "-"; -- Addition function "+" ( l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) + ufixed(c downto d) = return UNRESOLVED_ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mine(l'low, r'low); variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); variable result : UNRESOLVED_ufixed (left_index downto right_index); variable lslv, rslv : UNSIGNED (left_index-right_index downto 0); variable result_slv : UNSIGNED (left_index-right_index downto 0); begin if (l'length < 1 or r'length < 1 or result'length < 1) then return NAUF; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_uns (lresize); rslv := to_uns (rresize); result_slv := lslv + rslv; result := to_fixed(result_slv, left_index, right_index); return result; end function "+"; function "+" ( l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) + sfixed(c downto d) = return UNRESOLVED_sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mine(l'low, r'low); variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); variable result : UNRESOLVED_sfixed (left_index downto right_index); variable lslv, rslv : SIGNED (left_index-right_index downto 0); variable result_slv : SIGNED (left_index-right_index downto 0); begin if (l'length < 1 or r'length < 1 or result'length < 1) then return NASF; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_s (lresize); rslv := to_s (rresize); result_slv := lslv + rslv; result := to_fixed(result_slv, left_index, right_index); return result; end function "+"; -- Subtraction function "-" ( l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) - ufixed(c downto d) = return UNRESOLVED_ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mine(l'low, r'low); variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); variable result : UNRESOLVED_ufixed (left_index downto right_index); variable lslv, rslv : UNSIGNED (left_index-right_index downto 0); variable result_slv : UNSIGNED (left_index-right_index downto 0); begin if (l'length < 1 or r'length < 1 or result'length < 1) then return NAUF; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_uns (lresize); rslv := to_uns (rresize); result_slv := lslv - rslv; result := to_fixed(result_slv, left_index, right_index); return result; end function "-"; function "-" ( l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) - sfixed(c downto d) = return UNRESOLVED_sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mine(l'low, r'low); variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); variable result : UNRESOLVED_sfixed (left_index downto right_index); variable lslv, rslv : SIGNED (left_index-right_index downto 0); variable result_slv : SIGNED (left_index-right_index downto 0); begin if (l'length < 1 or r'length < 1 or result'length < 1) then return NASF; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_s (lresize); rslv := to_s (rresize); result_slv := lslv - rslv; result := to_fixed(result_slv, left_index, right_index); return result; end function "-"; function "*" ( l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) * ufixed(c downto d) = return UNRESOLVED_ufixed is -- ufixed(a+c+1 downto b+d) variable lslv : UNSIGNED (l'length-1 downto 0); variable rslv : UNSIGNED (r'length-1 downto 0); variable result_slv : UNSIGNED (r'length+l'length-1 downto 0); variable result : UNRESOLVED_ufixed (l'high + r'high+1 downto mine(l'low, l'low) + mine(r'low, r'low)); begin if (l'length < 1 or r'length < 1 or result'length /= result_slv'length) then return NAUF; end if; lslv := to_uns (cleanvec(l)); rslv := to_uns (cleanvec(r)); result_slv := lslv * rslv; result := to_fixed (result_slv, result'high, result'low); return result; end function "*"; function "*" ( l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) * sfixed(c downto d) = return UNRESOLVED_sfixed is -- sfixed(a+c+1 downto b+d) variable lslv : SIGNED (l'length-1 downto 0); variable rslv : SIGNED (r'length-1 downto 0); variable result_slv : SIGNED (r'length+l'length-1 downto 0); variable result : UNRESOLVED_sfixed (l'high + r'high+1 downto mine(l'low, l'low) + mine(r'low, r'low)); begin if (l'length < 1 or r'length < 1 or result'length /= result_slv'length) then return NASF; end if; lslv := to_s (cleanvec(l)); rslv := to_s (cleanvec(r)); result_slv := lslv * rslv; result := to_fixed (result_slv, result'high, result'low); return result; end function "*"; function "/" ( l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) / ufixed(c downto d) = return UNRESOLVED_ufixed is -- ufixed(a-d downto b-c-1) begin return divide (l, r); end function "/"; function "/" ( l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) / sfixed(c downto d) = return UNRESOLVED_sfixed is -- sfixed(a-d+1 downto b-c) begin return divide (l, r); end function "/"; -- This version of divide gives the user more control -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) function divide ( l, r : UNRESOLVED_ufixed; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (l'high - mine(r'low, r'low) downto mine (l'low, l'low) - r'high -1); variable dresult : UNRESOLVED_ufixed (result'high downto result'low -guard_bits); variable lresize : UNRESOLVED_ufixed (l'high downto l'high - dresult'length+1); variable lslv : UNSIGNED (lresize'length-1 downto 0); variable rslv : UNSIGNED (r'length-1 downto 0); variable result_slv : UNSIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1 or mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then return NAUF; end if; lresize := resize (arg => l, left_index => lresize'high, right_index => lresize'low, overflow_style => fixed_wrap, -- vector only grows round_style => fixed_truncate); lslv := to_uns (cleanvec (lresize)); rslv := to_uns (cleanvec (r)); if (rslv = 0) then report fixed_pkg'instance_name & "DIVIDE(ufixed) Division by zero" severity error; result := saturate (result'high, result'low); -- saturate else result_slv := lslv / rslv; dresult := to_fixed (result_slv, dresult'high, dresult'low); result := resize (arg => dresult, left_index => result'high, right_index => result'low, overflow_style => fixed_wrap, -- overflow impossible round_style => round_style); end if; return result; end function divide; -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) function divide ( l, r : UNRESOLVED_sfixed; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (l'high - mine(r'low, r'low) + 1 downto mine (l'low, l'low) - r'high); variable dresult : UNRESOLVED_sfixed (result'high downto result'low-guard_bits); variable lresize : UNRESOLVED_sfixed (l'high+1 downto l'high+1 -dresult'length+1); variable lslv : SIGNED (lresize'length-1 downto 0); variable rslv : SIGNED (r'length-1 downto 0); variable result_slv : SIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1 or mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then return NASF; end if; lresize := resize (arg => l, left_index => lresize'high, right_index => lresize'low, overflow_style => fixed_wrap, -- vector only grows round_style => fixed_truncate); lslv := to_s (cleanvec (lresize)); rslv := to_s (cleanvec (r)); if (rslv = 0) then report fixed_pkg'instance_name & "DIVIDE(sfixed) Division by zero" severity error; result := saturate (result'high, result'low); else result_slv := lslv / rslv; dresult := to_fixed (result_slv, dresult'high, dresult'low); result := resize (arg => dresult, left_index => result'high, right_index => result'low, overflow_style => fixed_wrap, -- overflow impossible round_style => round_style); end if; return result; end function divide; -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) function reciprocal ( arg : UNRESOLVED_ufixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed is constant one : UNRESOLVED_ufixed (0 downto 0) := "1"; begin return divide (l => one, r => arg, round_style => round_style, guard_bits => guard_bits); end function reciprocal; -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) function reciprocal ( arg : UNRESOLVED_sfixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed is constant one : UNRESOLVED_sfixed (1 downto 0) := "01"; -- extra bit. variable resultx : UNRESOLVED_sfixed (-mine(arg'low, arg'low)+2 downto -arg'high); begin if (arg'length < 1 or resultx'length < 1) then return NASF; else resultx := divide (l => one, r => arg, round_style => round_style, guard_bits => guard_bits); return resultx (resultx'high-1 downto resultx'low); -- remove extra bit end if; end function reciprocal; -- ufixed (a downto b) rem ufixed (c downto d) -- = ufixed (min(a,c) downto min(b,d)) function "rem" ( l, r : UNRESOLVED_ufixed) -- fixed point input return UNRESOLVED_ufixed is begin return remainder (l, r); end function "rem"; -- remainder -- sfixed (a downto b) rem sfixed (c downto d) -- = sfixed (min(a,c) downto min(b,d)) function "rem" ( l, r : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is begin return remainder (l, r); end function "rem"; -- ufixed (a downto b) rem ufixed (c downto d) -- = ufixed (min(a,c) downto min(b,d)) function remainder ( l, r : UNRESOLVED_ufixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (minimum(l'high, r'high) downto mine(l'low, r'low)); variable lresize : UNRESOLVED_ufixed (maximum(l'high, r'low) downto mins(r'low, r'low)-guard_bits); variable rresize : UNRESOLVED_ufixed (r'high downto r'low-guard_bits); variable dresult : UNRESOLVED_ufixed (rresize'range); variable lslv : UNSIGNED (lresize'length-1 downto 0); variable rslv : UNSIGNED (rresize'length-1 downto 0); variable result_slv : UNSIGNED (rslv'range); begin if (l'length < 1 or r'length < 1 or mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then return NAUF; end if; lresize := resize (arg => l, left_index => lresize'high, right_index => lresize'low, overflow_style => fixed_wrap, -- vector only grows round_style => fixed_truncate); lslv := to_uns (lresize); rresize := resize (arg => r, left_index => rresize'high, right_index => rresize'low, overflow_style => fixed_wrap, -- vector only grows round_style => fixed_truncate); rslv := to_uns (rresize); if (rslv = 0) then report fixed_pkg'instance_name & "remainder(ufixed) Division by zero" severity error; result := saturate (result'high, result'low); -- saturate else if (r'low <= l'high) then result_slv := lslv rem rslv; dresult := to_fixed (result_slv, dresult'high, dresult'low); result := resize (arg => dresult, left_index => result'high, right_index => result'low, overflow_style => fixed_wrap, -- can't overflow round_style => round_style); end if; if l'low < r'low then result(mins(r'low-1, l'high) downto l'low) := cleanvec(l(mins(r'low-1, l'high) downto l'low)); end if; end if; return result; end function remainder; -- remainder -- sfixed (a downto b) rem sfixed (c downto d) -- = sfixed (min(a,c) downto min(b,d)) function remainder ( l, r : UNRESOLVED_sfixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed is variable l_abs : UNRESOLVED_ufixed (l'range); variable r_abs : UNRESOLVED_ufixed (r'range); variable result : UNRESOLVED_sfixed (minimum(r'high, l'high) downto mine(r'low, l'low)); variable neg_result : UNRESOLVED_sfixed (minimum(r'high, l'high)+1 downto mins(r'low, l'low)); begin if (l'length < 1 or r'length < 1 or mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then return NASF; end if; l_abs := to_ufixed (l); r_abs := to_ufixed (r); result := UNRESOLVED_sfixed (remainder ( l => l_abs, r => r_abs, round_style => round_style)); neg_result := -result; if l(l'high) = '1' then result := neg_result(result'range); end if; return result; end function remainder; -- modulo -- ufixed (a downto b) mod ufixed (c downto d) -- = ufixed (min(a,c) downto min(b, d)) function "mod" ( l, r : UNRESOLVED_ufixed) -- fixed point input return UNRESOLVED_ufixed is begin return modulo (l, r); end function "mod"; -- sfixed (a downto b) mod sfixed (c downto d) -- = sfixed (c downto min(b, d)) function "mod" ( l, r : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is begin return modulo(l, r); end function "mod"; -- modulo -- ufixed (a downto b) mod ufixed (c downto d) -- = ufixed (min(a,c) downto min(b, d)) function modulo ( l, r : UNRESOLVED_ufixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed is begin return remainder(l => l, r => r, round_style => round_style, guard_bits => guard_bits); end function modulo; -- sfixed (a downto b) mod sfixed (c downto d) -- = sfixed (c downto min(b, d)) function modulo ( l, r : UNRESOLVED_sfixed; -- fixed point input constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed is variable l_abs : UNRESOLVED_ufixed (l'range); variable r_abs : UNRESOLVED_ufixed (r'range); variable result : UNRESOLVED_sfixed (r'high downto mine(r'low, l'low)); variable dresult : UNRESOLVED_sfixed (minimum(r'high, l'high)+1 downto mins(r'low, l'low)); variable dresult_not_zero : BOOLEAN; begin if (l'length < 1 or r'length < 1 or mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then return NASF; end if; l_abs := to_ufixed (l); r_abs := to_ufixed (r); dresult := "0" & UNRESOLVED_sfixed(remainder (l => l_abs, r => r_abs, round_style => round_style)); if (to_s(dresult) = 0) then dresult_not_zero := false; else dresult_not_zero := true; end if; if to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '0' and dresult_not_zero then result := resize (arg => r - dresult, left_index => result'high, right_index => result'low, overflow_style => overflow_style, round_style => round_style); elsif to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '1' then result := resize (arg => -dresult, left_index => result'high, right_index => result'low, overflow_style => overflow_style, round_style => round_style); elsif to_x01(l(l'high)) = '0' and to_x01(r(r'high)) = '1' and dresult_not_zero then result := resize (arg => dresult + r, left_index => result'high, right_index => result'low, overflow_style => overflow_style, round_style => round_style); else result := resize (arg => dresult, left_index => result'high, right_index => result'low, overflow_style => overflow_style, round_style => round_style); end if; return result; end function modulo; -- Procedure for those who need an "accumulator" function procedure add_carry ( L, R : in UNRESOLVED_ufixed; c_in : in STD_ULOGIC; result : out UNRESOLVED_ufixed; c_out : out STD_ULOGIC) is constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); variable lslv, rslv : UNSIGNED (left_index-right_index downto 0); variable result_slv : UNSIGNED (left_index-right_index downto 0); variable cx : UNSIGNED (0 downto 0); -- Carry in begin if (l'length < 1 or r'length < 1) then result := NAUF; c_out := '0'; else cx (0) := c_in; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_uns (lresize); rslv := to_uns (rresize); result_slv := lslv + rslv + cx; c_out := result_slv(left_index); result := to_fixed(result_slv (left_index-right_index-1 downto 0), left_index-1, right_index); end if; end procedure add_carry; procedure add_carry ( L, R : in UNRESOLVED_sfixed; c_in : in STD_ULOGIC; result : out UNRESOLVED_sfixed; c_out : out STD_ULOGIC) is constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); variable lslv, rslv : SIGNED (left_index-right_index downto 0); variable result_slv : SIGNED (left_index-right_index downto 0); variable cx : SIGNED (1 downto 0); -- Carry in begin if (l'length < 1 or r'length < 1) then result := NASF; c_out := '0'; else cx (1) := '0'; cx (0) := c_in; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_s (lresize); rslv := to_s (rresize); result_slv := lslv + rslv + cx; c_out := result_slv(left_index); result := to_fixed(result_slv (left_index-right_index-1 downto 0), left_index-1, right_index); end if; end procedure add_carry; -- Scales the result by a power of 2. Width of input = width of output with -- the decimal point moved. function scalb (y : UNRESOLVED_ufixed; N : INTEGER) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (y'high+N downto y'low+N); begin if y'length < 1 then return NAUF; else result := y; return result; end if; end function scalb; function scalb (y : UNRESOLVED_ufixed; N : SIGNED) return UNRESOLVED_ufixed is begin return scalb (y => y, N => to_integer(N)); end function scalb; function scalb (y : UNRESOLVED_sfixed; N : INTEGER) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (y'high+N downto y'low+N); begin if y'length < 1 then return NASF; else result := y; return result; end if; end function scalb; function scalb (y : UNRESOLVED_sfixed; N : SIGNED) return UNRESOLVED_sfixed is begin return scalb (y => y, N => to_integer(N)); end function scalb; function Is_Negative (arg : UNRESOLVED_sfixed) return BOOLEAN is begin if to_X01(arg(arg'high)) = '1' then return true; else return false; end if; end function Is_Negative; function find_rightmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'reverse_range loop if \?=\ (arg(i), y) = '1' then return i; end if; end loop; return arg'high+1; -- return out of bounds 'high end function find_rightmost; function find_leftmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'range loop if \?=\ (arg(i), y) = '1' then return i; end if; end loop; return arg'low-1; -- return out of bounds 'low end function find_leftmost; function find_rightmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'reverse_range loop if \?=\ (arg(i), y) = '1' then return i; end if; end loop; return arg'high+1; -- return out of bounds 'high end function find_rightmost; function find_leftmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'range loop if \?=\ (arg(i), y) = '1' then return i; end if; end loop; return arg'low-1; -- return out of bounds 'low end function find_leftmost; function "sll" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); argslv := argslv sll COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "sll"; function "srl" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); argslv := argslv srl COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "srl"; function "rol" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); argslv := argslv rol COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "rol"; function "ror" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); argslv := argslv ror COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "ror"; function "sla" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); -- Arithmetic shift on an unsigned is a logical shift argslv := argslv sll COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "sla"; function "sra" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); -- Arithmetic shift on an unsigned is a logical shift argslv := argslv srl COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "sra"; function "sll" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); argslv := argslv sll COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "sll"; function "srl" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); argslv := argslv srl COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "srl"; function "rol" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); argslv := argslv rol COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "rol"; function "ror" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); argslv := argslv ror COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "ror"; function "sla" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); if COUNT > 0 then -- Arithmetic shift left on a 2's complement number is a logic shift argslv := argslv sll COUNT; else argslv := argslv sra -COUNT; end if; result := to_fixed (argslv, result'high, result'low); return result; end function "sla"; function "sra" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); if COUNT > 0 then argslv := argslv sra COUNT; else -- Arithmetic shift left on a 2's complement number is a logic shift argslv := argslv sll -COUNT; end if; result := to_fixed (argslv, result'high, result'low); return result; end function "sra"; -- Because some people want the older functions. function SHIFT_LEFT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) return UNRESOLVED_ufixed is begin if (ARG'length < 1) then return NAUF; end if; return ARG sla COUNT; end function SHIFT_LEFT; function SHIFT_RIGHT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) return UNRESOLVED_ufixed is begin if (ARG'length < 1) then return NAUF; end if; return ARG sra COUNT; end function SHIFT_RIGHT; function SHIFT_LEFT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) return UNRESOLVED_sfixed is begin if (ARG'length < 1) then return NASF; end if; return ARG sla COUNT; end function SHIFT_LEFT; function SHIFT_RIGHT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) return UNRESOLVED_sfixed is begin if (ARG'length < 1) then return NASF; end if; return ARG sra COUNT; end function SHIFT_RIGHT; ---------------------------------------------------------------------------- -- logical functions ---------------------------------------------------------------------------- function "not" (L : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin RESULT := not to_suv(L); return to_ufixed(RESULT, L'high, L'low); end function "not"; function "and" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) and to_suv(R); else assert NO_WARNING report fixed_pkg'instance_name & """and"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'X'); end if; return to_ufixed(RESULT, L'high, L'low); end function "and"; function "or" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- fo