------------------------------------------------------------------------------ -- "fixed_pkg" 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.fixed_pkg.all; -- Last Modified: $Date: 2006-03-28 11:38:18-05 $ -- RCS ID: $Id: fixed_pkg_c.vhd,v 1.9 2006-03-28 11:38:18-05 l435385 Exp $ -- -- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) ------------------------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- synthesis translate_off use std.textio.all; -- synthesis translate_on package fixed_pkg is --%%% Uncomment the Generics -- new work.fixed_generic_pkg -- generic map ( -- fixed_round_style => true; -- fixed_round -- fixed_overflow_style => true; -- fixed_saturate -- fixed_guard_bits => 3; -- number of guard bits -- no_warning => false -- show warnings -- ); --%%% REMOVE THE REST OF THIS FILE. constant fixed_round_style : BOOLEAN := true; -- round constant fixed_overflow_style : BOOLEAN := true; -- saturate constant fixed_guard_bits : NATURAL := 3; -- number of guard bits constant no_warning : BOOLEAN := false; -- issue warnings -- Author David Bishop (dbishop@vhdl.org) -- These 5 constants are used as defaults. -- There is a mechanism to override them in every function constant fixed_round : BOOLEAN := true; -- Turn on rounding routine constant fixed_truncate : BOOLEAN := false; -- Trun off rounding routine constant fixed_saturate : BOOLEAN := true; -- Saturate large numbers constant fixed_wrap : BOOLEAN := false; -- Wrap large numbers constant fixedsynth_or_real : BOOLEAN; -- differed constant -- base Unsigned fixed point type, downto direction assumed type ufixed is array (INTEGER range <>) of STD_LOGIC; -- base Signed fixed point type, downto direction assumed type sfixed is array (INTEGER range <>) of STD_LOGIC; ----------------------------------------------------------------------------- -- Fixed point type is defined as follows: -- 0000000000 -- 4321012345 -- 4 0 -5 -- The decimal point is assumed between the "0" and "-1" index -- Thus "0011010000" = 6.5 and would be written as 00110.10000 -- All types are assumed to be in the "downto" direction. --=========================================================================== -- Arithmetic Operators: --=========================================================================== -- Modify the sign of the number, 2's complement function "abs" (arg : sfixed) return sfixed; function "-" (arg : sfixed)return sfixed; -- Convert a signed fixed to an unsigned fixed function "abs" (arg : sfixed) return ufixed; -- Addition -- ufixed(a downto b) + ufixed(c downto d) -- = ufixed(max(a,c)+1 downto min(b,d)) function "+" (l, r : ufixed) return ufixed; -- sfixed(a downto b) + sfixed(c downto d) -- = sfixed(max(a,c)+1 downto min(b,d)) function "+" (l, r : sfixed) return sfixed; -- Subtraction -- ufixed(a downto b) - ufixed(c downto d) -- = ufixed(max(a,c)+1 downto min(b,d)) function "-" (l, r : ufixed) return ufixed; -- sfixed(a downto b) - sfixed(c downto d) -- = sfixed(max(a,c)+1 downto min(b,d)) function "-" (l, r : sfixed) return sfixed; -- Multiplication -- ufixed(a downto b) * ufixed(c downto d) = ufixed(a+c+1 downto b+d) function "*" (l, r : ufixed) return ufixed; -- sfixed(a downto b) * sfixed(c downto d) = sfixed(a+c+1 downto b+d) function "*" (l, r : sfixed) return sfixed; -- Division -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) function "/" (l, r : ufixed) return ufixed; -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) function "/" (l, r : sfixed) return sfixed; -- Remainder -- ufixed (a downto b) rem ufixed (c downto d) -- = ufixed (min(a,c) downto min(b,d)) function "rem" (l, r : ufixed) return ufixed; -- sfixed (a downto b) rem sfixed (c downto d) -- = sfixed (min(a,c) downto min(b,d)) function "rem" (l, r : sfixed) return sfixed; -- Modulo -- ufixed (a downto b) mod ufixed (c downto d) -- = ufixed (min(a,c) downto min(b, d)) function "mod" (l, r : ufixed) return ufixed; -- sfixed (a downto b) mod sfixed (c downto d) -- = sfixed (c downto min(b, d)) function "mod" (l, r : sfixed) return sfixed; ---------------------------------------------------------------------------- -- Overload routines. 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 : ufixed; r : REAL) return ufixed; -- ufixed(c downto d) + ufixed(c downto d) = ufixed(c+1 downto d) function "+" (l : REAL; r : ufixed) return ufixed; -- ufixed(a downto b) + ufixed(a downto 0) = ufixed(a+1 downto min(0,b)) function "+" (l : ufixed; r : NATURAL) return ufixed; -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto min(0,d)) function "+" (l : NATURAL; r : ufixed) return ufixed; -- ufixed(a downto b) - ufixed(a downto b) = ufixed(a+1 downto b) function "-" (l : ufixed; r : REAL) return ufixed; -- ufixed(c downto d) - ufixed(c downto d) = ufixed(c+1 downto d) function "-" (l : REAL; r : ufixed) return ufixed; -- ufixed(a downto b) - ufixed(a downto 0) = ufixed(a+1 downto min(0,b)) function "-" (l : ufixed; r : NATURAL) return ufixed; -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto min(0,d)) function "-" (l : NATURAL; r : ufixed) return ufixed; -- ufixed(a downto b) * ufixed(a downto b) = ufixed(2a+1 downto 2b) function "*" (l : ufixed; r : REAL) return ufixed; -- ufixed(c downto d) * ufixed(c downto d) = ufixed(2c+1 downto 2d) function "*" (l : REAL; r : ufixed) return ufixed; -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) function "*" (l : ufixed; r : NATURAL) return ufixed; -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) function "*" (l : NATURAL; r : ufixed) return ufixed; -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) function "/" (l : ufixed; r : REAL) return ufixed; -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) function "/" (l : REAL; r : ufixed) return ufixed; -- ufixed(a downto b) / ufixed(a downto 0) = ufixed(a downto b-a-1) function "/" (l : ufixed; r : NATURAL) return ufixed; -- ufixed(c downto 0) / ufixed(c downto d) = ufixed(c-d downto -c-1) function "/" (l : NATURAL; r : ufixed) return ufixed; -- ufixed (a downto b) rem ufixed (a downto b) = ufixed (a downto b) function "rem" (l : ufixed; r : REAL) return ufixed; -- ufixed (c downto d) rem ufixed (c downto d) = ufixed (c downto d) function "rem" (l : REAL; r : ufixed) return ufixed; -- ufixed (a downto b) rem ufixed (a downto 0) = ufixed (a downto min(b,0)) function "rem" (l : ufixed; r : NATURAL) return ufixed; -- ufixed (c downto 0) rem ufixed (c downto d) = ufixed (c downto min(d,0)) function "rem" (l : NATURAL; r : ufixed) return ufixed; -- ufixed (a downto b) mod ufixed (a downto b) = ufixed (a downto b) function "mod" (l : ufixed; r : REAL) return ufixed; -- ufixed (c downto d) mod ufixed (c downto d) = ufixed (c downto d) function "mod" (l : REAL; r : ufixed) return ufixed; -- ufixed (a downto b) mod ufixed (a downto 0) = ufixed (a downto min(b,0)) function "mod" (l : ufixed; r : NATURAL) return ufixed; -- ufixed (c downto 0) mod ufixed (c downto d) = ufixed (c downto min(d,0)) function "mod" (l : NATURAL; r : ufixed) return ufixed; -- sfixed(a downto b) + sfixed(a downto b) = sfixed(a+1 downto b) function "+" (l : sfixed; r : REAL) return sfixed; -- sfixed(c downto d) + sfixed(c downto d) = sfixed(c+1 downto d) function "+" (l : REAL; r : sfixed) return sfixed; -- sfixed(a downto b) + sfixed(a downto 0) = sfixed(a+1 downto min(0,b)) function "+" (l : sfixed; r : INTEGER) return sfixed; -- sfixed(c downto 0) + sfixed(c downto d) = sfixed(c+1 downto min(0,d)) function "+" (l : INTEGER; r : sfixed) return sfixed; -- sfixed(a downto b) - sfixed(a downto b) = sfixed(a+1 downto b) function "-" (l : sfixed; r : REAL) return sfixed; -- sfixed(c downto d) - sfixed(c downto d) = sfixed(c+1 downto d) function "-" (l : REAL; r : sfixed) return sfixed; -- sfixed(a downto b) - sfixed(a downto 0) = sfixed(a+1 downto min(0,b)) function "-" (l : sfixed; r : INTEGER) return sfixed; -- sfixed(c downto 0) - sfixed(c downto d) = sfixed(c+1 downto min(0,d)) function "-" (l : INTEGER; r : sfixed) return sfixed; -- sfixed(a downto b) * sfixed(a downto b) = sfixed(2a+1 downto 2b) function "*" (l : sfixed; r : REAL) return sfixed; -- sfixed(c downto d) * sfixed(c downto d) = sfixed(2c+1 downto 2d) function "*" (l : REAL; r : sfixed) return sfixed; -- sfixed(a downto b) * sfixed(a downto 0) = sfixed(2a+1 downto b) function "*" (l : sfixed; r : INTEGER) return sfixed; -- sfixed(c downto 0) * sfixed(c downto d) = sfixed(2c+1 downto d) function "*" (l : INTEGER; r : sfixed) return sfixed; -- sfixed(a downto b) / sfixed(a downto b) = sfixed(a-b+1 downto b-a) function "/" (l : sfixed; r : REAL) return sfixed; -- sfixed(c downto d) / sfixed(c downto d) = sfixed(c-d+1 downto d-c) function "/" (l : REAL; r : sfixed) return sfixed; -- sfixed(a downto b) / sfixed(a downto 0) = sfixed(a+1 downto b-a) function "/" (l : sfixed; r : INTEGER) return sfixed; -- sfixed(c downto 0) / sfixed(c downto d) = sfixed(c-d+1 downto -c) function "/" (l : INTEGER; r : sfixed) return sfixed; -- sfixed (a downto b) rem sfixed (a downto b) = sfixed (a downto b) function "rem" (l : sfixed; r : REAL) return sfixed; -- sfixed (c downto d) rem sfixed (c downto d) = sfixed (c downto d) function "rem" (l : REAL; r : sfixed) return sfixed; -- sfixed (a downto b) rem sfixed (a downto 0) = sfixed (a downto min(b,0)) function "rem" (l : sfixed; r : INTEGER) return sfixed; -- sfixed (c downto 0) rem sfixed (c downto d) = sfixed (c downto min(d,0)) function "rem" (l : INTEGER; r : sfixed) return sfixed; -- sfixed (a downto b) mod sfixed (a downto b) = sfixed (a downto b) function "mod" (l : sfixed; r : REAL) return sfixed; -- sfixed (c downto d) mod sfixed (c downto d) = sfixed (c downto d) function "mod" (l : REAL; r : sfixed) return sfixed; -- sfixed (a downto b) mod sfixed (a downto 0) = sfixed (a downto min(b,0)) function "mod" (l : sfixed; r : INTEGER) return sfixed; -- sfixed (c downto 0) mod sfixed (c downto d) = sfixed (c downto min(d,0)) function "mod" (l : INTEGER; r : sfixed) return 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 : ufixed; constant round_style : BOOLEAN := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return 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 : sfixed; constant round_style : BOOLEAN := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return sfixed; -- These functions return 1/X -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) function reciprocal ( arg : ufixed; -- fixed point input constant round_style : BOOLEAN := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return ufixed; -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) function reciprocal ( arg : sfixed; -- fixed point input constant round_style : BOOLEAN := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return sfixed; -- REM function -- ufixed (a downto b) rem ufixed (c downto d) -- = ufixed (min(a,c) downto min(b,d)) function remainder ( l, r : ufixed; constant round_style : BOOLEAN := fixed_round_style) return ufixed; -- sfixed (a downto b) rem sfixed (c downto d) -- = sfixed (min(a,c) downto min(b,d)) function remainder ( l, r : sfixed; constant round_style : BOOLEAN := fixed_round_style) return sfixed; -- mod function -- ufixed (a downto b) mod ufixed (c downto d) -- = ufixed (min(a,c) downto min(b, d)) function modulo ( l, r : ufixed; constant round_style : BOOLEAN := fixed_round_style) return ufixed; -- sfixed (a downto b) mod sfixed (c downto d) -- = sfixed (c downto min(b, d)) function modulo ( l, r : sfixed; constant overflow_style : BOOLEAN := fixed_overflow_style; constant round_style : BOOLEAN := fixed_round_style) return sfixed; -- Procedure for those who need an "accumulator" function. -- add_carry (ufixed(a downto b), ufixed (c downto d)) -- = ufixed (max(a,c) downto min(b,d)) procedure add_carry ( L, R : in ufixed; c_in : in STD_ULOGIC; result : out ufixed; c_out : out STD_ULOGIC); -- add_carry (sfixed(a downto b), sfixed (c downto d)) -- = sfixed (max(a,c) downto min(b,d)) procedure add_carry ( L, R : in sfixed; c_in : in STD_ULOGIC; result : out sfixed; c_out : out STD_ULOGIC); -- Scales the result by a power of 2. Width of input = width of output with -- the decimal point moved. function scalb (y : ufixed; N : integer) return ufixed; function scalb (y : ufixed; N : SIGNED) return ufixed; function scalb (y : sfixed; N : integer) return sfixed; function scalb (y : sfixed; N : SIGNED) return sfixed; function Is_Negative (arg : sfixed) return BOOLEAN; --=========================================================================== -- Comparison Operators --=========================================================================== function ">" (l, r : ufixed) return BOOLEAN; function ">" (l, r : sfixed) return BOOLEAN; function "<" (l, r : ufixed) return BOOLEAN; function "<" (l, r : sfixed) return BOOLEAN; function "<=" (l, r : ufixed) return BOOLEAN; function "<=" (l, r : sfixed) return BOOLEAN; function ">=" (l, r : ufixed) return BOOLEAN; function ">=" (l, r : sfixed) return BOOLEAN; function "=" (l, r : ufixed) return BOOLEAN; function "=" (l, r : sfixed) return BOOLEAN; function "/=" (l, r : ufixed) return BOOLEAN; function "/=" (l, r : sfixed) return BOOLEAN; --%%% Uncomment the following (new syntax) -- function "?=" (L, R : ufixed) return BOOLEAN; -- function "?=" (L, R : sfixed) return BOOLEAN; -- --%%% remove the following (old syntax) function \?=\ (L, R : ufixed) return STD_ULOGIC; function \?=\ (L, R : sfixed) return STD_ULOGIC; -- These need to be overloaded for sfixed and ufixed function \?/=\ (L, R : ufixed) return STD_ULOGIC; function \?>\ (L, R : ufixed) return STD_ULOGIC; function \?>=\ (L, R : ufixed) return STD_ULOGIC; function \?<\ (L, R : ufixed) return STD_ULOGIC; function \?<=\ (L, R : ufixed) return STD_ULOGIC; function \?/=\ (L, R : sfixed) return STD_ULOGIC; function \?>\ (L, R : sfixed) return STD_ULOGIC; function \?>=\ (L, R : sfixed) return STD_ULOGIC; function \?<\ (L, R : sfixed) return STD_ULOGIC; function \?<=\ (L, R : sfixed) return STD_ULOGIC; -- %%% Replace with the following (new syntax) -- function "?=" (L, R : ufixed) return STD_ULOGIC; -- function "?/=" (L, R : ufixed) return STD_ULOGIC; -- function "?>" (L, R : ufixed) return STD_ULOGIC; -- function "?>=" (L, R : ufixed) return STD_ULOGIC; -- function "?<" (L, R : ufixed) return STD_ULOGIC; -- function "?<=" (L, R : ufixed) return STD_ULOGIC; -- function "?=" (L, R : sfixed) return STD_ULOGIC; -- function "?/=" (L, R : sfixed) return STD_ULOGIC; -- function "?>" (L, R : sfixed) return STD_ULOGIC; -- function "?>=" (L, R : sfixed) return STD_ULOGIC; -- function "?<" (L, R : sfixed) return STD_ULOGIC; -- function "?<=" (L, R : sfixed) return STD_ULOGIC; function std_match (L, R : ufixed) return BOOLEAN; function std_match (L, R : sfixed) return BOOLEAN; -- Overloads the default "maximum" and "minimum" function function maximum (l, r : ufixed) return ufixed; function minimum (l, r : ufixed) return ufixed; function maximum (l, r : sfixed) return sfixed; function minimum (l, r : sfixed) return sfixed; ---------------------------------------------------------------------------- -- In these compare functions a natural is converted into a -- fixed point number of the bounds "max(l'high,0) downto 0" ---------------------------------------------------------------------------- function "=" (l : ufixed; r : NATURAL) return BOOLEAN; function "/=" (l : ufixed; r : NATURAL) return BOOLEAN; function ">=" (l : ufixed; r : NATURAL) return BOOLEAN; function "<=" (l : ufixed; r : NATURAL) return BOOLEAN; function ">" (l : ufixed; r : NATURAL) return BOOLEAN; function "<" (l : ufixed; r : NATURAL) return BOOLEAN; function "=" (l : NATURAL; r : ufixed) return BOOLEAN; function "/=" (l : NATURAL; r : ufixed) return BOOLEAN; function ">=" (l : NATURAL; r : ufixed) return BOOLEAN; function "<=" (l : NATURAL; r : ufixed) return BOOLEAN; function ">" (l : NATURAL; r : ufixed) return BOOLEAN; function "<" (l : NATURAL; r : ufixed) return BOOLEAN; ---------------------------------------------------------------------------- -- In these compare functions a real is converted into a -- fixed point number of the bounds "l'high+1 downto l'low" ---------------------------------------------------------------------------- function "=" (l : ufixed; r : REAL) return BOOLEAN; function "/=" (l : ufixed; r : REAL) return BOOLEAN; function ">=" (l : ufixed; r : REAL) return BOOLEAN; function "<=" (l : ufixed; r : REAL) return BOOLEAN; function ">" (l : ufixed; r : REAL) return BOOLEAN; function "<" (l : ufixed; r : REAL) return BOOLEAN; function "=" (l : REAL; r : ufixed) return BOOLEAN; function "/=" (l : REAL; r : ufixed) return BOOLEAN; function ">=" (l : REAL; r : ufixed) return BOOLEAN; function "<=" (l : REAL; r : ufixed) return BOOLEAN; function ">" (l : REAL; r : ufixed) return BOOLEAN; function "<" (l : REAL; r : ufixed) return BOOLEAN; ---------------------------------------------------------------------------- -- In these compare functions an integer is converted into a -- fixed point number of the bounds "max(l'high,1) downto 0" ---------------------------------------------------------------------------- function "=" (l : sfixed; r : INTEGER) return BOOLEAN; function "/=" (l : sfixed; r : INTEGER) return BOOLEAN; function ">=" (l : sfixed; r : INTEGER) return BOOLEAN; function "<=" (l : sfixed; r : INTEGER) return BOOLEAN; function ">" (l : sfixed; r : INTEGER) return BOOLEAN; function "<" (l : sfixed; r : INTEGER) return BOOLEAN; function "=" (l : INTEGER; r : sfixed) return BOOLEAN; function "/=" (l : INTEGER; r : sfixed) return BOOLEAN; function ">=" (l : INTEGER; r : sfixed) return BOOLEAN; function "<=" (l : INTEGER; r : sfixed) return BOOLEAN; function ">" (l : INTEGER; r : sfixed) return BOOLEAN; function "<" (l : INTEGER; r : sfixed) return BOOLEAN; ---------------------------------------------------------------------------- -- In these compare functions a real is converted into a -- fixed point number of the bounds "l'high+1 downto l'low" ---------------------------------------------------------------------------- function "=" (l : sfixed; r : REAL) return BOOLEAN; function "/=" (l : sfixed; r : REAL) return BOOLEAN; function ">=" (l : sfixed; r : REAL) return BOOLEAN; function "<=" (l : sfixed; r : REAL) return BOOLEAN; function ">" (l : sfixed; r : REAL) return BOOLEAN; function "<" (l : sfixed; r : REAL) return BOOLEAN; function "=" (l : REAL; r : sfixed) return BOOLEAN; function "/=" (l : REAL; r : sfixed) return BOOLEAN; function ">=" (l : REAL; r : sfixed) return BOOLEAN; function "<=" (l : REAL; r : sfixed) return BOOLEAN; function ">" (l : REAL; r : sfixed) return BOOLEAN; function "<" (l : REAL; r : sfixed) return BOOLEAN; --=========================================================================== -- Shift and Rotate Functions. -- Note that sra and sla are not the same as the BIT_VECTOR version --=========================================================================== function "sll" (ARG : ufixed; COUNT : INTEGER) return ufixed; function "srl" (ARG : ufixed; COUNT : INTEGER) return ufixed; function "rol" (ARG : ufixed; COUNT : INTEGER) return ufixed; function "ror" (ARG : ufixed; COUNT : INTEGER) return ufixed; function "sla" (ARG : ufixed; COUNT : INTEGER) return ufixed; function "sra" (ARG : ufixed; COUNT : INTEGER) return ufixed; function "sll" (ARG : sfixed; COUNT : INTEGER) return sfixed; function "srl" (ARG : sfixed; COUNT : INTEGER) return sfixed; function "rol" (ARG : sfixed; COUNT : INTEGER) return sfixed; function "ror" (ARG : sfixed; COUNT : INTEGER) return sfixed; function "sla" (ARG : sfixed; COUNT : INTEGER) return sfixed; function "sra" (ARG : sfixed; COUNT : INTEGER) return sfixed; function SHIFT_LEFT (ARG : ufixed; COUNT : NATURAL) return ufixed; function SHIFT_RIGHT (ARG : ufixed; COUNT : NATURAL) return ufixed; function SHIFT_LEFT (ARG : sfixed; COUNT : NATURAL) return sfixed; function SHIFT_RIGHT (ARG : sfixed; COUNT : NATURAL) return sfixed; ---------------------------------------------------------------------------- -- logical functions ---------------------------------------------------------------------------- function "not" (L : ufixed) return ufixed; function "and" (L, R : ufixed) return ufixed; function "or" (L, R : ufixed) return ufixed; function "nand" (L, R : ufixed) return ufixed; function "nor" (L, R : ufixed) return ufixed; function "xor" (L, R : ufixed) return ufixed; function "xnor" (L, R : ufixed) return ufixed; function "not" (L : sfixed) return sfixed; function "and" (L, R : sfixed) return sfixed; function "or" (L, R : sfixed) return sfixed; function "nand" (L, R : sfixed) return sfixed; function "nor" (L, R : sfixed) return sfixed; function "xor" (L, R : sfixed) return sfixed; function "xnor" (L, R : sfixed) return sfixed; -- Vector and std_ulogic functions, same as functions in numeric_std function "and" (L : STD_ULOGIC; R : ufixed) return ufixed; function "and" (L : ufixed; R : STD_ULOGIC) return ufixed; function "or" (L : STD_ULOGIC; R : ufixed) return ufixed; function "or" (L : ufixed; R : STD_ULOGIC) return ufixed; function "nand" (L : STD_ULOGIC; R : ufixed) return ufixed; function "nand" (L : ufixed; R : STD_ULOGIC) return ufixed; function "nor" (L : STD_ULOGIC; R : ufixed) return ufixed; function "nor" (L : ufixed; R : STD_ULOGIC) return ufixed; function "xor" (L : STD_ULOGIC; R : ufixed) return ufixed; function "xor" (L : ufixed; R : STD_ULOGIC) return ufixed; function "xnor" (L : STD_ULOGIC; R : ufixed) return ufixed; function "xnor" (L : ufixed; R : STD_ULOGIC) return ufixed; function "and" (L : STD_ULOGIC; R : sfixed) return sfixed; function "and" (L : sfixed; R : STD_ULOGIC) return sfixed; function "or" (L : STD_ULOGIC; R : sfixed) return sfixed; function "or" (L : sfixed; R : STD_ULOGIC) return sfixed; function "nand" (L : STD_ULOGIC; R : sfixed) return sfixed; function "nand" (L : sfixed; R : STD_ULOGIC) return sfixed; function "nor" (L : STD_ULOGIC; R : sfixed) return sfixed; function "nor" (L : sfixed; R : STD_ULOGIC) return sfixed; function "xor" (L : STD_ULOGIC; R : sfixed) return sfixed; function "xor" (L : sfixed; R : STD_ULOGIC) return sfixed; function "xnor" (L : STD_ULOGIC; R : sfixed) return sfixed; function "xnor" (L : sfixed; R : STD_ULOGIC) return sfixed; -- Reduction operators, same as numeric_std functions -- %%% remove 12 functions (old syntax) function and_reduce(arg : ufixed) return STD_ULOGIC; function nand_reduce(arg : ufixed) return STD_ULOGIC; function or_reduce(arg : ufixed) return STD_ULOGIC; function nor_reduce(arg : ufixed) return STD_ULOGIC; function xor_reduce(arg : ufixed) return STD_ULOGIC; function xnor_reduce(arg : ufixed) return STD_ULOGIC; function and_reduce(arg : sfixed) return STD_ULOGIC; function nand_reduce(arg : sfixed) return STD_ULOGIC; function or_reduce(arg : sfixed) return STD_ULOGIC; function nor_reduce(arg : sfixed) return STD_ULOGIC; function xor_reduce(arg : sfixed) return STD_ULOGIC; function xnor_reduce(arg : sfixed) return STD_ULOGIC; -- %%% Uncomment the following 12 functions (new syntax) -- function "and" ( arg : ufixed ) RETURN std_ulogic; -- function "nand" ( arg : ufixed ) RETURN std_ulogic; -- function "or" ( arg : ufixed ) RETURN std_ulogic; -- function "nor" ( arg : ufixed ) RETURN std_ulogic; -- function "xor" ( arg : ufixed ) RETURN std_ulogic; -- function "xnor" ( arg : ufixed ) RETURN std_ulogic; -- function "and" ( arg : sfixed ) RETURN std_ulogic; -- function "nand" ( arg : sfixed ) RETURN std_ulogic; -- function "or" ( arg : sfixed ) RETURN std_ulogic; -- function "nor" ( arg : sfixed ) RETURN std_ulogic; -- function "xor" ( arg : sfixed ) RETURN std_ulogic; -- function "xnor" ( arg : sfixed ) RETURN std_ulogic; -- returns arg'low-1 if not found function find_msb (arg : ufixed; y : STD_ULOGIC) return INTEGER; function find_msb (arg : sfixed; y : STD_ULOGIC) return INTEGER; -- returns arg'high+1 if not found function find_lsb (arg : ufixed; y : STD_ULOGIC) return INTEGER; function find_lsb (arg : 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 true, then the result will be rounded. If the MSB -- of the remainder is a "1" AND the LSB of the unround 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. -- The default is "true" for round_style. -- "overflow_style" can be "true" (saturate mode) or "false" (wrap mode). -- 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 : ufixed; -- input constant left_index : INTEGER; -- integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow constant round_style : BOOLEAN := fixed_round_style) -- rounding return 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 : ufixed; -- input size_res : ufixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow constant round_style : BOOLEAN := fixed_round_style) -- rounding return 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 : sfixed; -- input constant left_index : INTEGER; -- integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return sfixed; function resize ( arg : sfixed; -- input size_res : sfixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return 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 : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding return ufixed; function to_ufixed ( arg : NATURAL; -- integer size_res : ufixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding return 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 : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style; -- rounding by default constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return ufixed; function to_ufixed ( arg : REAL; -- real size_res : ufixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style; -- rounding by default constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return 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 : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return ufixed; function to_ufixed ( arg : UNSIGNED; -- unsigned size_res : ufixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return ufixed; -- Performs a casting. ufixed (arg'range) is returned function to_ufixed ( arg : UNSIGNED) -- unsigned return ufixed; -- unsigned fixed point to unsigned function to_unsigned ( arg : ufixed; -- fixed point input constant size : NATURAL; -- length of output constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return UNSIGNED; -- unsigned fixed point to unsigned function to_unsigned ( arg : ufixed; -- fixed point input size_res : UNSIGNED; -- used for length of output constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return UNSIGNED; -- unsigned fixed point to real function to_real ( arg : ufixed) -- fixed point input return REAL; -- unsigned fixed point to integer function to_integer ( arg : ufixed; -- fixed point input constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return NATURAL; -- Integer to 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 : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return sfixed; function to_sfixed ( arg : INTEGER; -- integer size_res : sfixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return 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 : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style; -- rounding by default constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return sfixed; function to_sfixed ( arg : REAL; -- real size_res : sfixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style; -- rounding by default constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return 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 : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return sfixed; function to_sfixed ( arg : SIGNED; -- signed size_res : sfixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return sfixed; -- signed to sfixed (output assumed to be size of signed input) function to_sfixed ( arg : SIGNED) -- signed return sfixed; -- unsigned fixed point to signed fixed point (adds a "0" sign bit) function add_sign ( arg : ufixed) -- unsigned fixed point return sfixed; -- signed fixed point to signed function to_signed ( arg : sfixed; -- fixed point input constant size : NATURAL; -- length of output constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return SIGNED; -- signed fixed point to signed function to_signed ( arg : sfixed; -- fixed point input size_res : SIGNED; -- used for length of output constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return SIGNED; -- signed fixed point to real function to_real ( arg : sfixed) -- fixed point input return REAL; -- signed fixed point to integer function to_integer ( arg : sfixed; -- fixed point input constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return INTEGER; -- Because of the farily 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) 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 : ufixed; operation : CHARACTER := 'X'; size_res2 : ufixed) return INTEGER; function ufixed_low (size_res : ufixed; operation : CHARACTER := 'X'; size_res2 : ufixed) return INTEGER; function sfixed_high (size_res : sfixed; operation : CHARACTER := 'X'; size_res2 : sfixed) return INTEGER; function sfixed_low (size_res : sfixed; operation : CHARACTER := 'X'; size_res2 : sfixed) return INTEGER; -- purpose: returns a saturated number function saturate ( constant left_index : INTEGER; constant right_index : INTEGER) return ufixed; -- purpose: returns a saturated number function saturate ( constant left_index : INTEGER; constant right_index : INTEGER) return sfixed; function saturate ( size_res : ufixed) -- only the size of this is used return ufixed; function saturate ( size_res : sfixed) -- only the size of this is used return sfixed; --=========================================================================== -- Translation Functions --=========================================================================== -- Maps meta-logical values function to_01 ( s : ufixed; -- fixed point input constant XMAP : STD_LOGIC := '0') -- Map x to return ufixed; -- maps meta-logical values function to_01 ( s : sfixed; -- fixed point input constant XMAP : STD_LOGIC := '0') -- Map x to return sfixed; function Is_X (arg : ufixed) return BOOLEAN; function Is_X (arg : sfixed) return BOOLEAN; function to_X01 (arg : ufixed) return ufixed; function to_X01 (arg : sfixed) return sfixed; function to_X01Z (arg : ufixed) return ufixed; function to_X01Z (arg : sfixed) return sfixed; function to_UX01 (arg : ufixed) return ufixed; function to_UX01 (arg : sfixed) return 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 cast these vectors because of their negative index. function to_slv ( arg : ufixed) -- fp vector return STD_LOGIC_VECTOR; -- alias to_StdLogicVector is to_slv [ufixed return STD_LOGIC_VECTOR]; -- alias to_Std_Logic_Vector is to_slv [ufixed return STD_LOGIC_VECTOR]; function to_slv ( arg : sfixed) -- fp vector return STD_LOGIC_VECTOR; -- alias to_StdLogicVector is to_slv [sfixed return STD_LOGIC_VECTOR]; -- alias to_Std_Logic_Vector is to_slv [sfixed return STD_LOGIC_VECTOR]; function to_sulv ( arg : ufixed) -- fp vector return STD_ULOGIC_VECTOR; -- alias to_StdULogicVector is to_sulv [ufixed return STD_ULOGIC_VECTOR]; -- alias to_Std_ULogic_Vector is to_sulv [ufixed return STD_ULOGIC_VECTOR]; function to_sulv ( arg : sfixed) -- fp vector return STD_ULOGIC_VECTOR; -- alias to_StdULogicVector is to_sulv [sfixed return STD_ULOGIC_VECTOR]; -- alias to_Std_ULogic_Vector is to_sulv [sfixed return STD_ULOGIC_VECTOR]; function to_ufixed ( arg : STD_LOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return ufixed; function to_ufixed ( arg : STD_LOGIC_VECTOR; -- shifted vector size_res : ufixed) -- for size only return ufixed; function to_sfixed ( arg : STD_LOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return sfixed; function to_sfixed ( arg : STD_LOGIC_VECTOR; -- shifted vector size_res : sfixed) -- for size only return sfixed; function to_ufixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return ufixed; function to_ufixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector size_res : ufixed) -- for size only return ufixed; function to_sfixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return sfixed; function to_sfixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector size_res : sfixed) -- for size only return 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_LOGIC_VECTOR; width : NATURAL; -- width of vector fraction : NATURAL) -- width of fraction return ufixed; -- signed fixed point function to_SFix ( arg : STD_LOGIC_VECTOR; width : NATURAL; -- width of vector fraction : NATURAL) -- width of fraction return 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; --=========================================================================== -- string and textio Functions --=========================================================================== -- rtl_synthesis off -- synthesis translate_off -- purpose: writes fixed point into a line procedure WRITE ( L : inout LINE; -- input line VALUE : in 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 sfixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); procedure READ(L : inout LINE; VALUE : out ufixed); procedure READ(L : inout LINE; VALUE : out ufixed; GOOD : out BOOLEAN); procedure READ(L : inout LINE; VALUE : out sfixed); procedure READ(L : inout LINE; VALUE : out sfixed; GOOD : out BOOLEAN); alias bwrite is WRITE [LINE, ufixed, SIDE, width]; alias bwrite is WRITE [LINE, sfixed, SIDE, width]; alias bread is READ [LINE, ufixed]; alias bread is READ [LINE, ufixed, BOOLEAN]; alias bread is READ [LINE, sfixed]; alias bread is READ [LINE, sfixed, BOOLEAN]; -- octal read and write procedure OWRITE ( L : inout LINE; -- input line VALUE : in ufixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); procedure OWRITE ( L : inout LINE; -- input line VALUE : in sfixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); procedure OREAD(L : inout LINE; VALUE : out ufixed); procedure OREAD(L : inout LINE; VALUE : out ufixed; GOOD : out BOOLEAN); procedure OREAD(L : inout LINE; VALUE : out sfixed); procedure OREAD(L : inout LINE; VALUE : out sfixed; GOOD : out BOOLEAN); -- hex read and write procedure HWRITE ( L : inout LINE; -- input line VALUE : in 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 sfixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); procedure HREAD(L : inout LINE; VALUE : out ufixed); procedure HREAD(L : inout LINE; VALUE : out ufixed; GOOD : out BOOLEAN); procedure HREAD(L : inout LINE; VALUE : out sfixed); procedure HREAD(L : inout LINE; VALUE : out sfixed; GOOD : out BOOLEAN); -- returns a string, useful for: -- assert (x = y) report "error found " & to_string(x) severity error; function to_string ( value : ufixed; justified : SIDE := right; field : WIDTH := 0 ) return STRING; alias to_bstring is to_string [ufixed, SIDE, width return STRING]; function to_ostring ( value : ufixed; justified : SIDE := right; field : WIDTH := 0 ) return STRING; function to_hstring ( value : ufixed; justified : SIDE := right; field : WIDTH := 0 ) return STRING; function to_string ( value : sfixed; justified : SIDE := right; field : WIDTH := 0 ) return STRING; alias to_bstring is to_string [sfixed, SIDE, width return STRING]; function to_ostring ( value : sfixed; justified : SIDE := right; field : WIDTH := 0 ) return STRING; function to_hstring ( value : sfixed; justified : SIDE := right; field : WIDTH := 0 ) 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 ufixed; alias from_bstring is from_string [STRING, INTEGER, INTEGER return 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 ufixed; function from_hstring ( hstring : STRING; -- hex string constant left_index : INTEGER; constant right_index : INTEGER) return ufixed; function from_string ( bstring : STRING; -- binary string constant left_index : INTEGER; constant right_index : INTEGER) return sfixed; alias from_bstring is from_string [STRING, INTEGER, INTEGER return sfixed]; function from_ostring ( ostring : STRING; -- Octal string constant left_index : INTEGER; constant right_index : INTEGER) return sfixed; function from_hstring ( hstring : STRING; -- hex string constant left_index : INTEGER; constant right_index : INTEGER) return sfixed; -- Same as above, "size_res" is used for it's range only. function from_string ( bstring : STRING; -- binary string size_res : ufixed) return ufixed; alias from_bstring is from_string [STRING, ufixed return ufixed]; function from_ostring ( ostring : STRING; -- Octal string size_res : ufixed) return ufixed; function from_hstring ( hstring : STRING; -- hex string size_res : ufixed) return ufixed; function from_string ( bstring : STRING; -- binary string size_res : sfixed) return sfixed; alias from_bstring is from_string [STRING, sfixed return sfixed]; function from_ostring ( ostring : STRING; -- Octal string size_res : sfixed) return sfixed; function from_hstring ( hstring : STRING; -- hex string size_res : sfixed) return sfixed; -- Direct converstion 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 ufixed; alias from_bstring is from_string [STRING return ufixed]; -- Direct octal and hex converstion 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 ufixed; function from_hstring ( hstring : STRING) -- hex string return ufixed; function from_string ( bstring : STRING) -- binary string return sfixed; alias from_bstring is from_string [STRING return sfixed]; function from_ostring ( ostring : STRING) -- Octal string return sfixed; function from_hstring ( hstring : STRING) -- hex string return sfixed; -- synthesis translate_on -- rtl_synthesis on -- This type is here for the floating point package. type round_type is (round_nearest, -- Default, nearest LSB '0' round_inf, -- Round to positive round_neginf, -- Round to negate round_zero); -- Round towards zero -- These are the same as the C FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, -- and FE_TOWARDZERO floating point rounding macros. function to_StdLogicVector ( arg : ufixed) -- fp vector return STD_LOGIC_VECTOR; function to_Std_Logic_Vector ( arg : ufixed) -- fp vector return STD_LOGIC_VECTOR; function to_StdLogicVector ( arg : sfixed) -- fp vector return STD_LOGIC_VECTOR; function to_Std_Logic_Vector ( arg : sfixed) -- fp vector return STD_LOGIC_VECTOR; end package fixed_pkg; library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; use std.textio.all; use ieee.std_logic_textio.all; -- %%% for testing only 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 : ufixed (0 downto 1) := (others => '0'); constant NASF : sfixed (0 downto 1) := (others => '0'); constant NSLV : STD_LOGIC_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; --%%% Can be removed in vhdl-200x, will be implicit. -- purpose: To find the largest of 2 numbers function maximum (l, r : INTEGER) return INTEGER is begin -- function maximum if L > R then return L; else return R; end if; end function maximum; function minimum (l, r : INTEGER) return INTEGER is begin -- function minimum if L > R then return R; else return L; end if; end function minimum; -- %%% Remove the following function (duplicates of new numeric_std) 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"; -- %%% Replace or_reducex with "or", and_reducex with "and", and -- %%% xor_reducex with "xor", then remove the following 3 functions -- purpose: OR all of the bits in a vector together -- This is a copy of the proposed "or_reduce" from 1076.3 function or_reducex (arg : STD_LOGIC_VECTOR) return STD_LOGIC is variable Upper, Lower : STD_LOGIC; variable Half : INTEGER; variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0); variable Result : STD_LOGIC; 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_reducex (BUS_int (BUS_int'left downto Half)); Lower := or_reducex (BUS_int (Half - 1 downto BUS_int'right)); Result := Upper or Lower; end if; end if; return Result; end function or_reducex; -- purpose: AND all of the bits in a vector together -- This is a copy of the proposed "and_reduce" from 1076.3 function and_reducex (arg : STD_LOGIC_VECTOR) return STD_LOGIC is variable Upper, Lower : STD_LOGIC; variable Half : INTEGER; variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0); variable Result : STD_LOGIC; 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_reducex (BUS_int (BUS_int'left downto Half)); Lower := and_reducex (BUS_int (Half - 1 downto BUS_int'right)); Result := Upper and Lower; end if; end if; return Result; end function and_reducex; function xor_reducex (arg : STD_LOGIC_VECTOR) return STD_ULOGIC is variable Upper, Lower : STD_ULOGIC; variable Half : INTEGER; variable BUS_int : STD_LOGIC_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_reducex (BUS_int (BUS_int'left downto Half)); Lower := xor_reducex (BUS_int (Half - 1 downto BUS_int'right)); Result := Upper xor Lower; end if; end if; return Result; end function xor_reducex; --%%% remove the following function and table -- Match table, copied form new std_logic_1164 type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; constant match_logic_table : stdlogic_table := ( ----------------------------------------------------- -- U X 0 1 Z W L H - | | ----------------------------------------------------- ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1'), -- | U | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | X | ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | 0 | ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | 1 | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | Z | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | W | ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | L | ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | H | ('1', '1', '1', '1', '1', '1', '1', '1', '1') -- | - | ); constant no_match_logic_table : stdlogic_table := ( ----------------------------------------------------- -- U X 0 1 Z W L H - | | ----------------------------------------------------- ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '0'), -- | U | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | X | ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | 0 | ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | 1 | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | Z | ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | W | ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | L | ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | H | ('0', '0', '0', '0', '0', '0', '0', '0', '0') -- | - | ); ------------------------------------------------------------------- -- ?= functions, Similar to "std_match", but returns "std_ulogic". ------------------------------------------------------------------- -- %%% FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic IS function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is begin return match_logic_table (l, r); end function \?=\; -- %%% END FUNCTION "?="; -- %%% FUNCTION "?/=" ( l, r : std_ulogic ) RETURN std_ulogic is function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is begin return no_match_logic_table (l, r); end function \?/=\; -- %%% END FUNCTION "?/="; -- %%% end remove -- 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 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_GENERIC_PKG: 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 : sfixed) -- input return sfixed is constant left_index : INTEGER := maximum(arg'left, arg'right); constant right_index : INTEGER := mins(arg'left, arg'right); variable result : sfixed (arg'range); begin -- function cleanvec assert not ((arg'left < arg'right) and (arg'low /= INTEGER'low)) report "FIXED_GENERIC_PKG: 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 : ufixed) -- input return ufixed is constant left_index : INTEGER := maximum(arg'left, arg'right); constant right_index : INTEGER := mins(arg'left, arg'right); variable result : ufixed (arg'range); begin -- function cleanvec assert not ((arg'left < arg'right) and (arg'low /= INTEGER'low)) report "FIXED_GENERIC_PKG: Vector passed using a ""to"" range, expected is ""downto""" severity error; return arg; end function cleanvec; -- Type cast a "unsigned" into a "ufixed", used internally function to_fixed ( arg : UNSIGNED; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return ufixed is variable result : ufixed (left_index downto right_index); -- variable j : INTEGER := arg'high; -- index for arg begin -- function to_fixed result := ufixed(arg); -- floop : for i in result'range loop -- result(i) := arg(j); -- res(4) := arg (4 + 3) -- j := j - 1; -- end loop floop; return result; end function to_fixed; -- Type cast a "signed" into an "sfixed", used internally function to_fixed ( arg : SIGNED; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return sfixed is variable result : sfixed (left_index downto right_index); -- variable j : INTEGER := arg'high; -- index for arg begin -- function to_fixed result := sfixed(arg); -- floop : for i in result'range loop -- result(i) := arg(j); -- res(4) := arg (4 + 3) -- j := j - 1; -- end loop floop; return result; end function to_fixed; -- Type cast a "ufixed" into an "unsigned", used internally function to_uns ( arg : 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); -- floop : for i in slv'range loop -- slv(i) := arg(i + arg'low); -- slv(7) := arg (7 - 3) -- end loop floop; return UNSIGNED(to_X01(std_logic_vector(slv))); end function to_uns; -- Type cast an "sfixed" into a "signed", used internally function to_s ( arg : 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); -- floop : for i in slv'range loop -- slv(i) := arg(i + arg'low); -- slv(7) := arg (7 - 3) -- end loop floop; return SIGNED(to_X01(std_logic_vector(slv))); end function to_s; -- adds 1 to the LSB of the number procedure round_up (arg : in ufixed; result : out 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 sfixed; result : out 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_reducex (STD_LOGIC_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 : ufixed; remainder : ufixed; overflow_style : BOOLEAN := fixed_overflow_style) return ufixed is variable rounds : BOOLEAN; variable round_overflow : BOOLEAN; variable result : ufixed (arg'range); begin rounds := false; if (remainder'length > 1) then if (remainder (remainder'high) = '1') then rounds := (arg(arg'low) = '1') or (or_reducex (to_slv(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 : sfixed; remainder : sfixed; overflow_style : BOOLEAN := fixed_overflow_style) return sfixed is variable rounds : BOOLEAN; variable round_overflow : BOOLEAN; variable result : sfixed (arg'range); begin rounds := false; if (remainder'length > 1) then if (remainder (remainder'high) = '1') then rounds := (arg(arg'low) = '1') or (or_reducex (to_slv(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; -- else -- result(result'high) := arg(arg'high); -- fix sign bit in wrap end if; end if; return result; end function round_fixed; ----------------------------------------------------------------------------- -- Visible functions ----------------------------------------------------------------------------- -- casting functions. These are needed for synthesis where typically -- the only input and output type is a std_logic_vector. function to_slv ( arg : ufixed) -- fixed point vector return STD_LOGIC_VECTOR is subtype t is STD_LOGIC_VECTOR (arg'high - arg'low downto 0); variable slv : t; begin if arg'length < 1 then return NSLV; end if; slv := t (arg); return slv; end function to_slv; function to_slv ( arg : sfixed) -- fixed point vector return STD_LOGIC_VECTOR is subtype t is STD_LOGIC_VECTOR (arg'high - arg'low downto 0); variable slv : t; begin if arg'length < 1 then return NSLV; end if; slv := t (arg); return slv; end function to_slv; function to_sulv ( arg : ufixed) -- fixed point vector return STD_ULOGIC_VECTOR is begin return to_stdulogicvector (to_slv(arg)); end function to_sulv; function to_sulv ( arg : sfixed) -- fixed point vector return STD_ULOGIC_VECTOR is begin return to_stdulogicvector (to_slv(arg)); end function to_sulv; function to_ufixed ( arg : STD_LOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return ufixed is variable result : 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_GENERIC_PKG.TO_UFIXED (STD_LOGIC_VECTOR) " & "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_LOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return sfixed is variable result : 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_GENERIC_PKG.TO_SFIXED (STD_LOGIC_VECTOR) " & "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; function to_ufixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return ufixed is begin return to_ufixed (arg => to_stdlogicvector(arg), left_index => left_index, right_index => right_index); end function to_ufixed; function to_sfixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return sfixed is begin return to_sfixed (arg => to_stdlogicvector(arg), left_index => left_index, right_index => right_index); 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 : sfixed) -- fixed point input return 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 : 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 : sfixed) -- fixed point input return 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 : 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 "-"; function "abs" (arg : sfixed) return ufixed is constant left_index : INTEGER := arg'high; constant right_index : INTEGER := mine(arg'low, arg'low); variable xarg : sfixed(left_index+1 downto right_index); variable result : ufixed(left_index downto right_index); begin if arg'length < 1 then return NAUF; end if; xarg := abs(arg); result := ufixed (xarg (left_index downto right_index)); return result; end function "abs"; -- Addition function "+" ( l, r : ufixed) -- ufixed(a downto b) + ufixed(c downto d) = return 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 := mins(l'low, r'low); variable lresize, rresize : ufixed (left_index downto right_index); variable result : 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) 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 : sfixed) -- sfixed(a downto b) + sfixed(c downto d) = return 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 := mins(l'low, r'low); variable lresize, rresize : sfixed (left_index downto right_index); variable result : 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) 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 : ufixed) -- ufixed(a downto b) - ufixed(c downto d) = return 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 := mins(l'low, r'low); variable lresize, rresize : ufixed (left_index downto right_index); variable result : 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) 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 : sfixed) -- sfixed(a downto b) - sfixed(c downto d) = return 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 := mins(l'low, r'low); variable lresize, rresize : sfixed (left_index downto right_index); variable result : 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) 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 : ufixed) -- ufixed(a downto b) * ufixed(c downto d) = return 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 : 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 : sfixed) -- sfixed(a downto b) * sfixed(c downto d) = return 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 : 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 : ufixed) -- ufixed(a downto b) / ufixed(c downto d) = return ufixed is -- ufixed(a-d downto b-c-1) begin return divide (l, r); end function "/"; function "/" ( l, r : sfixed) -- sfixed(a downto b) / sfixed(c downto d) = return 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 : ufixed; constant round_style : BOOLEAN := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return ufixed is variable result : ufixed (l'high - mine(r'low, r'low) downto mine (l'low, l'low) - r'high -1); variable dresult : ufixed (result'high downto result'low -guard_bits); variable lresize : 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 (l, lresize'high, lresize'low); lslv := to_uns (cleanvec (lresize)); rslv := to_uns (cleanvec (r)); if (rslv = 0) then report "FIXED_GENERIC_PKG.DIVIDE uFixed point 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, round_style => round_style, overflow_style => fixed_wrap); -- overflow impossible 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 : sfixed; constant round_style : BOOLEAN := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return sfixed is variable result : sfixed (l'high - mine(r'low, r'low)+1 downto mine (l'low, l'low) - r'high); variable dresult : sfixed (result'high downto result'low-guard_bits); variable lresize : 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 (l, lresize'high, lresize'low); lslv := to_s (cleanvec (lresize)); rslv := to_s (cleanvec (r)); if (rslv = 0) then report "FIXED_GENERIC_PKG.DIVIDE uFixed point 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, round_style => round_style, overflow_style => fixed_wrap); -- overflow impossible end if; return result; end function divide; -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) function reciprocal ( arg : ufixed; -- fixed point input constant round_style : BOOLEAN := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return ufixed is constant one : 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 : sfixed; -- fixed point input constant round_style : BOOLEAN := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return sfixed is constant one : sfixed (1 downto 0) := "01"; -- extra bit. variable resultx : 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 : ufixed) -- fixed point input return ufixed is begin return remainder (l => l, r => r, round_style => fixed_round_style); 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 : sfixed) -- fixed point input return sfixed is begin return remainder (l => l, r => r, round_style => fixed_round_style); end function "rem"; -- ufixed (a downto b) rem ufixed (c downto d) -- = ufixed (min(a,c) downto min(b,d)) function remainder ( l, r : ufixed; -- fixed point input constant round_style : BOOLEAN := fixed_round_style) return ufixed is variable result : ufixed (minimum(l'high, r'high) downto mine(l'low, r'low)); variable dresult : ufixed (r'high downto r'low); variable lresize : ufixed (maximum(l'high, r'low) downto mins(r'low, r'low)); variable lslv : UNSIGNED (lresize'length-1 downto 0); variable rslv : UNSIGNED (r'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); rslv := to_uns (cleanvec(r)); if (rslv = 0) then report "FIXED_GENERIC_PKG.rem uFixed point 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, round_style => round_style); -- result(result'high downto r'low) := dresult(result'high downto r'low); 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 : sfixed; -- fixed point input constant round_style : BOOLEAN := fixed_round_style) return sfixed is variable l_abs : ufixed (l'range); variable r_abs : ufixed (r'range); variable result : sfixed (minimum(r'high, l'high) downto mine(r'low, l'low)); variable neg_result : 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 := abs(l); r_abs := abs(r); result := 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 : ufixed) -- fixed point input return ufixed is begin return modulo (l => l, r => r, round_style => fixed_round_style); end function "mod"; -- sfixed (a downto b) mod sfixed (c downto d) -- = sfixed (c downto min(b, d)) function "mod" ( l, r : sfixed) -- fixed point input return sfixed is begin return modulo(l => l, r => r, round_style => fixed_round_style); 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 : ufixed; -- fixed point input constant round_style : BOOLEAN := fixed_round_style) return ufixed is begin return remainder(l => l, r => r, round_style => round_style); end function modulo; -- sfixed (a downto b) mod sfixed (c downto d) -- = sfixed (c downto min(b, d)) function modulo ( l, r : sfixed; -- fixed point input constant overflow_style : BOOLEAN := fixed_overflow_style; constant round_style : BOOLEAN := fixed_round_style) return sfixed is variable l_abs : ufixed (l'range); variable r_abs : ufixed (r'range); variable result : sfixed (r'high downto mine(r'low, l'low)); variable dresult : 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 := abs(l); r_abs := abs(r); dresult := "0" & 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 ufixed; c_in : in STD_ULOGIC; result : out 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 : 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 sfixed; c_in : in STD_ULOGIC; result : out 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 : 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 : ufixed; N : integer) return ufixed is variable result : 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 : ufixed; N : SIGNED) return ufixed is begin return scalb (y => y, N => to_integer(N)); end function scalb; function scalb (y : sfixed; N : integer) return sfixed is variable result : 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 : sfixed; N : SIGNED) return sfixed is begin return scalb (y => y, N => to_integer(N)); end function scalb; function Is_Negative (arg : 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_lsb (arg : ufixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'low to arg'high loop if arg(i) = y then return i; end if; end loop; return arg'high+1; -- return out of bounds 'high end function find_lsb; function find_msb (arg : ufixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'high downto arg'low loop if arg(i) = y then return i; end if; end loop; return arg'low-1; -- return out of bounds 'low end function find_msb; function find_lsb (arg : sfixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'low to arg'high loop if arg(i) = y then return i; end if; end loop; return arg'high+1; -- return out of bounds 'high end function find_lsb; function find_msb (arg : sfixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'high downto arg'low loop if arg(i) = y then return i; end if; end loop; return arg'low-1; -- return out of bounds 'low end function find_msb; function "sll" (ARG : ufixed; COUNT : INTEGER) return ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : 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 : ufixed; COUNT : INTEGER) return ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : 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 : ufixed; COUNT : INTEGER) return ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : 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 : ufixed; COUNT : INTEGER) return ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : 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 : ufixed; COUNT : INTEGER) return ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : 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 : ufixed; COUNT : INTEGER) return ufixed is variable argslv : UNSIGNED (arg'length-1 downto 0); variable result : 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 : sfixed; COUNT : INTEGER) return sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : 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 : sfixed; COUNT : INTEGER) return sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : 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 : sfixed; COUNT : INTEGER) return sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : 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 : sfixed; COUNT : INTEGER) return sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : 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 : sfixed; COUNT : INTEGER) return sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : 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 : sfixed; COUNT : INTEGER) return sfixed is variable argslv : SIGNED (arg'length-1 downto 0); variable result : 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 : ufixed; COUNT : NATURAL) return ufixed is begin if (ARG'length < 1) then return NAUF; end if; return ARG sla COUNT; end function SHIFT_LEFT; function SHIFT_RIGHT (ARG : ufixed; COUNT : NATURAL) return ufixed is begin if (ARG'length < 1) then return NAUF; end if; return ARG sra COUNT; end function SHIFT_RIGHT; function SHIFT_LEFT (ARG : sfixed; COUNT : NATURAL) return sfixed is begin if (ARG'length < 1) then return NASF; end if; return ARG sla COUNT; end function SHIFT_LEFT; function SHIFT_RIGHT (ARG : sfixed; COUNT : NATURAL) return 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 : ufixed) return ufixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin RESULT := not to_slv(L); return to_ufixed(RESULT, L'high, L'low); end function "not"; function "and" (L, R : ufixed) return ufixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) and to_slv(R); else report "FIXED_GENERIC_PKG.""and"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "and"; function "or" (L, R : ufixed) return ufixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) or to_slv(R); else report "FIXED_GENERIC_PKG.""or"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "or"; function "nand" (L, R : ufixed) return ufixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) nand to_slv(R); else report "FIXED_GENERIC_PKG.""nand"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "nand"; function "nor" (L, R : ufixed) return ufixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) nor to_slv(R); else report "FIXED_GENERIC_PKG.""nor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "nor"; function "xor" (L, R : ufixed) return ufixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) xor to_slv(R); else report "FIXED_GENERIC_PKG.""xor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "xor"; function "xnor" (L, R : ufixed) return ufixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) xnor to_slv(R); else report "FIXED_GENERIC_PKG.""xnor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "xnor"; function "not" (L : sfixed) return sfixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin RESULT := not to_slv(L); return to_sfixed(RESULT, L'high, L'low); end function "not"; function "and" (L, R : sfixed) return sfixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) and to_slv(R); else report "FIXED_GENERIC_PKG.""and"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "and"; function "or" (L, R : sfixed) return sfixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) or to_slv(R); else report "FIXED_GENERIC_PKG.""or"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "or"; function "nand" (L, R : sfixed) return sfixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) nand to_slv(R); else report "FIXED_GENERIC_PKG.""nand"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "nand"; function "nor" (L, R : sfixed) return sfixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) nor to_slv(R); else report "FIXED_GENERIC_PKG.""nor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "nor"; function "xor" (L, R : sfixed) return sfixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) xor to_slv(R); else report "FIXED_GENERIC_PKG.""xor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "xor"; function "xnor" (L, R : sfixed) return sfixed is variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_slv(L) xnor to_slv(R); else report "FIXED_GENERIC_PKG.""xnor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "xnor"; -- Vector and std_ulogic functions, same as functions in numeric_std function "and" (L : STD_ULOGIC; R : ufixed) return ufixed is variable result : ufixed (R'range); begin for i in result'range loop result(i) := L and R(i); end loop; return result; end function "and"; function "and" (L : ufixed; R : STD_ULOGIC) return ufixed is variable result : ufixed (L'range); begin for i in result'range loop result(i) := L(i) and R; end loop; return result; end function "and"; function "or" (L : STD_ULOGIC; R : ufixed) return ufixed is variable result : ufixed (R'range); begin for i in result'range loop result(i) := L or R(i); end loop; return result; end function "or"; function "or" (L : ufixed; R : STD_ULOGIC) return ufixed is variable result : ufixed (L'range); begin for i in result'range loop result(i) := L(i) or R; end loop; return result; end function "or"; function "nand" (L : STD_ULOGIC; R : ufixed) return ufixed is variable result : ufixed (R'range); begin for i in result'range loop result(i) := L nand R(i); end loop; return result; end function "nand"; function "nand" (L : ufixed; R : STD_ULOGIC) return ufixed is variable result : ufixed (L'range); begin for i in result'range loop result(i) := L(i) nand R; end loop; return result; end function "nand"; function "nor" (L : STD_ULOGIC; R : ufixed) return ufixed is variable result : ufixed (R'range); begin for i in result'range loop result(i) := L nor R(i); end loop; return result; end function "nor"; function "nor" (L : ufixed; R : STD_ULOGIC) return ufixed is variable result : ufixed (L'range); begin for i in result'range loop result(i) := L(i) nor R; end loop; return result; end function "nor"; function "xor" (L : STD_ULOGIC; R : ufixed) return ufixed is variable result : ufixed (R'range); begin for i in result'range loop result(i) := L xor R(i); end loop; return result; end function "xor"; function "xor" (L : ufixed; R : STD_ULOGIC) return ufixed is variable result : ufixed (L'range); begin for i in result'range loop result(i) := L(i) xor R; end loop; return result; end function "xor"; function "xnor" (L : STD_ULOGIC; R : ufixed) return ufixed is variable result : ufixed (R'range); begin for i in result'range loop result(i) := L xnor R(i); end loop; return result; end function "xnor"; function "xnor" (L : ufixed; R : STD_ULOGIC) return ufixed is variable result : ufixed (L'range); begin for i in result'range loop result(i) := L(i) xnor R; end loop; return result; end function "xnor"; function "and" (L : STD_ULOGIC; R : sfixed) return sfixed is variable result : sfixed (R'range); begin for i in result'range loop result(i) := L and R(i); end loop; return result; end function "and"; function "and" (L : sfixed; R : STD_ULOGIC) return sfixed is variable result : sfixed (L'range); begin for i in result'range loop result(i) := L(i) and R; end loop; return result; end function "and"; function "or" (L : STD_ULOGIC; R : sfixed) return sfixed is variable result : sfixed (R'range); begin for i in result'range loop result(i) := L or R(i); end loop; return result; end function "or"; function "or" (L : sfixed; R : STD_ULOGIC) return sfixed is variable result : sfixed (L'range); begin for i in result'range loop result(i) := L(i) or R; end loop; return result; end function "or"; function "nand" (L : STD_ULOGIC; R : sfixed) return sfixed is variable result : sfixed (R'range); begin for i in result'range loop result(i) := L nand R(i); end loop; return result; end function "nand"; function "nand" (L : sfixed; R : STD_ULOGIC) return sfixed is variable result : sfixed (L'range); begin for i in result'range loop result(i) := L(i) nand R; end loop; return result; end function "nand"; function "nor" (L : STD_ULOGIC; R : sfixed) return sfixed is variable result : sfixed (R'range); begin for i in result'range loop result(i) := L nor R(i); end loop; return result; end function "nor"; function "nor" (L : sfixed; R : STD_ULOGIC) return sfixed is variable result : sfixed (L'range); begin for i in result'range loop result(i) := L(i) nor R; end loop; return result; end function "nor"; function "xor" (L : STD_ULOGIC; R : sfixed) return sfixed is variable result : sfixed (R'range); begin for i in result'range loop result(i) := L xor R(i); end loop; return result; end function "xor"; function "xor" (L : sfixed; R : STD_ULOGIC) return sfixed is variable result : sfixed (L'range); begin for i in result'range loop result(i) := L(i) xor R; end loop; return result; end function "xor"; function "xnor" (L : STD_ULOGIC; R : sfixed) return sfixed is variable result : sfixed (R'range); begin for i in result'range loop result(i) := L xnor R(i); end loop; return result; end function "xnor"; function "xnor" (L : sfixed; R : STD_ULOGIC) return sfixed is variable result : sfixed (L'range); begin for i in result'range loop result(i) := L(i) xnor R; end loop; return result; end function "xnor"; -- Reduction operators, same as numeric_std functions -- %%% remove 12 functions (old syntax) function and_reduce(arg : ufixed) return STD_ULOGIC is begin return and_reducex (to_slv(arg)); end function and_reduce; function nand_reduce(arg : ufixed) return STD_ULOGIC is begin return not and_reducex (to_slv(arg)); end function nand_reduce; function or_reduce(arg : ufixed) return STD_ULOGIC is begin return or_reducex (to_slv(arg)); end function or_reduce; function nor_reduce(arg : ufixed) return STD_ULOGIC is begin return not or_reducex (to_slv(arg)); end function nor_reduce; function xor_reduce(arg : ufixed) return STD_ULOGIC is begin return xor_reducex (to_slv(arg)); end function xor_reduce; function xnor_reduce(arg : ufixed) return STD_ULOGIC is begin return not xor_reducex (to_slv(arg)); end function xnor_reduce; function and_reduce(arg : sfixed) return STD_ULOGIC is begin return and_reducex (to_slv(arg)); end function and_reduce; function nand_reduce(arg : sfixed) return STD_ULOGIC is begin return not and_reducex (to_slv(arg)); end function nand_reduce; function or_reduce(arg : sfixed) return STD_ULOGIC is begin return or_reducex (to_slv(arg)); end function or_reduce; function nor_reduce(arg : sfixed) return STD_ULOGIC is begin return not or_reducex (to_slv(arg)); end function nor_reduce; function xor_reduce(arg : sfixed) return STD_ULOGIC is begin return xor_reducex (to_slv(arg)); end function xor_reduce; function xnor_reduce(arg : sfixed) return STD_ULOGIC is begin return not xor_reducex (to_slv(arg)); end function xnor_reduce; -- %%% Uncomment the following 12 functions (new syntax) -- function "and" ( arg : ufixed ) RETURN std_ulogic is -- begin -- return and to_slv(arg); -- end function "and"; -- function "nand" ( arg : ufixed ) RETURN std_ulogic is -- begin -- return nand to_slv(arg); -- end function "nand";; -- function "or" ( arg : ufixed ) RETURN std_ulogic is -- begin -- return or to_slv(arg); -- end function "or"; -- function "nor" ( arg : ufixed ) RETURN std_ulogic is -- begin -- return nor to_slv(arg); -- end function "nor"; -- function "xor" ( arg : ufixed ) RETURN std_ulogic is -- begin -- return xor to_slv(arg); -- end function "xor"; -- function "xnor" ( arg : ufixed ) RETURN std_ulogic is -- begin -- return xnor to_slv(arg); -- end function "xnor"; -- function "and" ( arg : sfixed ) RETURN std_ulogic is -- begin -- return and to_slv(arg); -- end function "and";; -- function "nand" ( arg : sfixed ) RETURN std_ulogic is -- begin -- return nand to_slv(arg); -- end function "nand";; -- function "or" ( arg : sfixed ) RETURN std_ulogic is -- begin -- return or to_slv(arg); -- end function "or"; -- function "nor" ( arg : sfixed ) RETURN std_ulogic is -- begin -- return nor to_slv(arg); -- end function "nor"; -- function "xor" ( arg : sfixed ) RETURN std_ulogic is -- begin -- return xor to_slv(arg); -- end function "xor"; -- function "xnor" ( arg : sfixed ) RETURN std_ulogic is -- begin -- return xnor to_slv(arg); -- end function "xnor"; -- %%% Replace with the following (new syntax) -- function "?=" (L, R : ufixed) return STD_ULOGIC is function \?=\ (L, R : ufixed) return STD_ULOGIC is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : ufixed (left_index downto right_index); variable result, result1 : STD_ULOGIC; -- result begin -- ?= if ((L'LENGTH < 1) or (R'LENGTH < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?="": null detected, returning X" severity warning; return 'X'; else lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); result := '1'; for i in lresize'reverse_range loop result1 := \?=\(lresize(i), rresize(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 \?=\; -- end function "?="; -- function "?/=" (L, R : ufixed) return STD_ULOGIC is function \?/=\ (L, R : ufixed) return STD_ULOGIC is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : ufixed (left_index downto right_index); variable result, result1 : STD_ULOGIC; -- result begin -- ?/= if ((L'LENGTH < 1) or (R'LENGTH < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?/="": null detected, returning X" severity warning; return 'X'; else lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); result := '0'; for i in lresize'reverse_range loop result1 := \?/=\ (lresize(i), rresize(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 \?/=\; -- end function "?/="; -- function "?>" (L, R : ufixed) return STD_ULOGIC is function \?>\ (L, R : ufixed) return STD_ULOGIC is begin -- ?> if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?>"": null detected, returning X" severity warning; return 'X'; elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then report "FIXED_GENERIC_PKG.""?>"": '-' found in compare string" severity error; return 'X'; else 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 function "?>"; -- function "?>=" (L, R : ufixed) return STD_ULOGIC is function \?>=\ (L, R : ufixed) return STD_ULOGIC is begin -- ?>= if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?>="": null detected, returning X" severity warning; return 'X'; elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then report "FIXED_GENERIC_PKG.""?>="": '-' found in compare string" severity error; return 'X'; else 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 function "?>="; -- function "?<" (L, R : ufixed) return STD_ULOGIC is function \?<\ (L, R : ufixed) return STD_ULOGIC is begin -- ?< if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?<"": null detected, returning X" severity warning; return 'X'; elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then report "FIXED_GENERIC_PKG.""?<"": '-' found in compare string" severity error; return 'X'; else 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 function "?<"; -- function "?<=" (L, R : ufixed) return STD_ULOGIC is function \?<=\ (L, R : ufixed) return STD_ULOGIC is begin -- ?<= if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?<="": null detected, returning X" severity warning; return 'X'; elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then report "FIXED_GENERIC_PKG.""?<="": '-' found in compare string" severity error; return 'X'; else 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 function "?<="; -- function "?=" (L, R : sfixed) return STD_ULOGIC is function \?=\ (L, R : sfixed) return STD_ULOGIC is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : sfixed (left_index downto right_index); variable result, result1 : STD_ULOGIC; -- result begin -- ?= if ((L'LENGTH < 1) or (R'LENGTH < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?="": null detected, returning X" severity warning; return 'X'; else lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); result := '1'; for i in lresize'reverse_range loop result1 := \?=\ (lresize(i), rresize(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 \?=\; -- end function "?="; -- function "?/=" (L, R : sfixed) return STD_ULOGIC is function \?/=\ (L, R : sfixed) return STD_ULOGIC is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : sfixed (left_index downto right_index); variable result, result1 : STD_ULOGIC; -- result begin -- ?/= if ((L'LENGTH < 1) or (R'LENGTH < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?/="": null detected, returning X" severity warning; return 'X'; else lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); result := '0'; for i in lresize'reverse_range loop result1 := \?/=\ (lresize(i), rresize(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 \?/=\; -- end function "?/="; -- function "?>" (L, R : sfixed) return STD_ULOGIC is function \?>\ (L, R : sfixed) return STD_ULOGIC is begin -- ?> if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?>"": null detected, returning X" severity warning; return 'X'; elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then report "FIXED_GENERIC_PKG.""?>"": '-' found in compare string" severity error; return 'X'; else 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 function "?>"; -- function "?>=" (L, R : sfixed) return STD_ULOGIC is function \?>=\ (L, R : sfixed) return STD_ULOGIC is begin -- ?>= if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?>="": null detected, returning X" severity warning; return 'X'; elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then report "FIXED_GENERIC_PKG.""?>="": '-' found in compare string" severity error; return 'X'; else 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 function "?>="; -- function "?<" (L, R : sfixed) return STD_ULOGIC is function \?<\ (L, R : sfixed) return STD_ULOGIC is begin -- ?< if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?<"": null detected, returning X" severity warning; return 'X'; elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then report "FIXED_GENERIC_PKG.""?<"": '-' found in compare string" severity error; return 'X'; else 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 function "?<"; -- function "?<=" (L, R : sfixed) return STD_ULOGIC is function \?<=\ (L, R : sfixed) return STD_ULOGIC is begin -- ?<= if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""?<="": null detected, returning X" severity warning; return 'X'; elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then report "FIXED_GENERIC_PKG.""?<="": '-' found in compare string" severity error; return 'X'; else 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 function "?<="; -- %%% end replace -- Match function, similar to "std_match" from numeric_std function std_match (L, R : ufixed) return BOOLEAN is begin if (L'high = R'high and L'low = R'low) then return std_match(to_slv(L), to_slv(R)); else report "FIXED_GENERIC_PKG.STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" severity warning; return false; end if; end function std_match; function std_match (L, R : sfixed) return BOOLEAN is begin if (L'high = R'high and L'low = R'low) then return std_match(to_slv(L), to_slv(R)); else report "FIXED_GENERIC_PKG.STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" severity warning; return false; end if; end function std_match; --%%% end remove -- compare functions function "=" ( l, r : ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : ufixed (left_index downto right_index); variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG.""="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""="": metavalue detected, returning FALSE" severity warning; return false; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_uns (lresize); rslv := to_uns (rresize); return lslv = rslv; end function "="; function "=" ( l, r : sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : sfixed (left_index downto right_index); variable lslv, rslv : SIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG.""="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""="": metavalue detected, returning FALSE" severity warning; return false; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_s (lresize); rslv := to_s (rresize); return lslv = rslv; end function "="; function "/=" ( l, r : ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : ufixed (left_index downto right_index); variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG.""/="": null argument detected, returning TRUE" severity warning; return true; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""/="": metavalue detected, returning TRUE" severity warning; return true; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_uns (lresize); rslv := to_uns (rresize); return lslv /= rslv; end function "/="; function "/=" ( l, r : sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : sfixed (left_index downto right_index); variable lslv, rslv : SIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG.""/="": null argument detected, returning TRUE" severity warning; return true; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""/="": metavalue detected, returning TRUE" severity warning; return true; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_s (lresize); rslv := to_s (rresize); return lslv /= rslv; end function "/="; function ">" ( l, r : ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : ufixed (left_index downto right_index); variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG."">"": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG."">"": metavalue detected, returning FALSE" severity warning; return false; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_uns (lresize); rslv := to_uns (rresize); return lslv > rslv; end function ">"; function ">" ( l, r : sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : sfixed (left_index downto right_index); variable lslv, rslv : SIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG."">"": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG."">"": metavalue detected, returning FALSE" severity warning; return false; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_s (lresize); rslv := to_s (rresize); return lslv > rslv; end function ">"; function "<" ( l, r : ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : ufixed (left_index downto right_index); variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG.""<"": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""<"": metavalue detected, returning FALSE" severity warning; return false; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_uns (lresize); rslv := to_uns (rresize); return lslv < rslv; end function "<"; function "<" ( l, r : sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : sfixed (left_index downto right_index); variable lslv, rslv : SIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG.""<"": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""<"": metavalue detected, returning FALSE" severity warning; return false; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_s (lresize); rslv := to_s (rresize); return lslv < rslv; end function "<"; function ">=" ( l, r : ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : ufixed (left_index downto right_index); variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG."">="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG."">="": metavalue detected, returning FALSE" severity warning; return false; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_uns (lresize); rslv := to_uns (rresize); return lslv >= rslv; end function ">="; function ">=" ( l, r : sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : sfixed (left_index downto right_index); variable lslv, rslv : SIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG."">="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG."">="": metavalue detected, returning FALSE" severity warning; return false; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_s (lresize); rslv := to_s (rresize); return lslv >= rslv; end function ">="; function "<=" ( l, r : ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : ufixed (left_index downto right_index); variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG.""<="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""<="": metavalue detected, returning FALSE" severity warning; return false; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_uns (lresize); rslv := to_uns (rresize); return lslv <= rslv; end function "<="; function "<=" ( l, r : sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : sfixed (left_index downto right_index); variable lslv, rslv : SIGNED (lresize'length-1 downto 0); begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report "FIXED_GENERIC_PKG.""<="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report "FIXED_GENERIC_PKG.""<="": metavalue detected, returning FALSE" severity warning; return false; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); lslv := to_s (lresize); rslv := to_s (rresize); return lslv <= rslv; end function "<="; -- overloads of the default maximum and minimum functions function maximum (l, r : ufixed) return ufixed is begin if l > r then return l; else return r; end if; end function maximum; function maximum (l, r : sfixed) return sfixed is begin if l > r then return l; else return r; end if; end function maximum; function minimum (l, r : ufixed) return ufixed is begin if l > r then return r; else return l; end if; end function minimum; function minimum (l, r : sfixed) return sfixed is begin if l > r then return r; else return l; end if; end function minimum; 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 : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default return ufixed is variable argx : INTEGER; constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : ufixed (left_index downto fw) := (others => '0'); variable sresult : UNSIGNED (left_index downto 0); -- integer portion variable bound : NATURAL; -- find the numerical bounds begin if (left_index < fw) then return NAUF; end if; if left_index >= 0 then if (left_index < 30) then bound := 2**(left_index+1); else bound := INTEGER'high; end if; end if; if (arg /= 0) then if arg >= bound or left_index < 0 then assert NO_WARNING report "FIXED_GENERIC_PKG.TO_UFIXED(NATURAL): vector truncated" severity warning; if (overflow_style = fixed_wrap) then -- wrap if bound = 0 then argx := 0; else argx := arg mod bound; end if; else -- saturate return saturate (result'high, result'low); end if; else argx := arg; end if; else return result; -- return zero end if; sresult := to_unsigned (argx, sresult'high+1); result := resize (arg => ufixed (sresult), left_index => left_index, right_index => right_index, round_style => round_style, overflow_style => overflow_style); return result; end function to_ufixed; 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 : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default return sfixed is variable argx : INTEGER; constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : sfixed (left_index downto fw) := (others => '0'); variable sresult : SIGNED (left_index+1 downto 0); -- integer portion variable bound : NATURAL := 0; begin if (left_index < fw) then -- null range return NASF; end if; if left_index >= 0 then if (left_index < 30) then bound := 2**(left_index); else bound := INTEGER'high; end if; end if; if (arg /= 0) then if (arg >= bound or arg < -bound or left_index < 0) then assert NO_WARNING report "FIXED_GENERIC_PKG.TO_SFIXED(INTEGER): vector truncated" severity warning; if overflow_style = fixed_wrap then -- wrap if bound = 0 then -- negative integer_range trap argx := 0; else -- shift off the top bits argx := arg rem (bound*2); end if; else -- saturate if arg < 0 then result := not saturate (result'high, result'low); -- underflow else result := saturate (result'high, result'low); -- overflow end if; return result; end if; else argx := arg; end if; else return result; -- return zero end if; sresult := to_signed (argx, sresult'length); result := resize (arg => sfixed (sresult), left_index => left_index, right_index => right_index, round_style => round_style, overflow_style => overflow_style); return result; end function to_sfixed; function to_ufixed ( arg : REAL; -- real constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return ufixed is constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : ufixed (left_index downto fw) := (others => '0'); variable Xresult : ufixed (left_index downto fw-guard_bits) := (others => '0'); variable presult : REAL; variable overflow_needed : BOOLEAN; begin -- If negative or null range, return. if (left_index < fw) then return NAUF; end if; if (arg < 0.0) then report "FIXED_GENERIC_PKG.TO_UFIXED: Negative argument passed " & REAL'image(arg) severity error; return result; end if; presult := arg; if presult >= (2.0**(left_index+1)) then assert NO_WARNING report "FIXED_GENERIC_PKG.TO_UFIXED(REAL): vector truncated" severity warning; overflow_needed := (overflow_style = fixed_saturate); if overflow_style = fixed_wrap then presult := presult mod (2.0**(left_index+1)); -- wrap else return saturate (result'high, result'low); end if; end if; for i in Xresult'range loop if presult >= 2.0**i then Xresult(i) := '1'; presult := presult - 2.0**i; else Xresult(i) := '0'; end if; end loop; if guard_bits > 0 and round_style = fixed_round then result := round_fixed (arg => Xresult (left_index downto right_index), remainder => Xresult (right_index-1 downto right_index-guard_bits), overflow_style => overflow_style); else result := Xresult (result'range); end if; return result; end function to_ufixed; function to_sfixed ( arg : REAL; -- real constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return sfixed is constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : sfixed (left_index downto fw) := (others => '0'); variable Xresult : sfixed (left_index+1 downto fw-guard_bits) := (others => '0'); variable presult : REAL; begin if (left_index < fw) then -- null range return NASF; end if; if (arg >= (2.0**left_index) or arg < -(2.0**left_index)) then assert NO_WARNING report "FIXED_GENERIC_PKG.TO_SFIXED(REAL): vector truncated" severity warning; if overflow_style = fixed_saturate then if arg < 0.0 then -- saturate result := not saturate (result'high, result'low); -- underflow else result := saturate (result'high, result'low); -- overflow end if; return result; else presult := abs(arg) mod (2.0**(left_index+1)); -- wrap end if; else presult := abs(arg); end if; for i in Xresult'range loop if presult >= 2.0**i then Xresult(i) := '1'; presult := presult - 2.0**i; else Xresult(i) := '0'; end if; end loop; if arg < 0.0 then Xresult := to_fixed(-to_s(Xresult), Xresult'high, Xresult'low); end if; if guard_bits > 0 and round_style then result := round_fixed (arg => Xresult (left_index downto right_index), remainder => Xresult (right_index-1 downto right_index-guard_bits), overflow_style => overflow_style); else result := Xresult (result'range); end if; return result; end function to_sfixed; 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 : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default return ufixed is constant ARG_LEFT : INTEGER := ARG'length-1; alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : ufixed (left_index downto fw); begin if arg'length < 1 or (left_index < fw) then return NAUF; end if; result := resize (arg => ufixed (XARG), left_index => left_index, right_index => right_index, round_style => round_style, overflow_style => overflow_style); return result; end function to_ufixed; -- casted version function to_ufixed ( arg : UNSIGNED) -- unsigned return ufixed is constant ARG_LEFT : INTEGER := ARG'length-1; alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; begin if arg'length < 1 then return NAUF; end if; return ufixed(xarg); end function to_ufixed; 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 : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default return sfixed is constant ARG_LEFT : INTEGER := ARG'length-1; alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : sfixed (left_index downto fw); begin if arg'length < 1 or (left_index < fw) then return NASF; end if; result := resize (arg => sfixed (XARG), left_index => left_index, right_index => right_index, round_style => round_style, overflow_style => overflow_style); return result; end function to_sfixed; -- casted version function to_sfixed ( arg : SIGNED) -- signed return sfixed is constant ARG_LEFT : INTEGER := ARG'length-1; alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; begin if arg'length < 1 then return NASF; end if; return sfixed(xarg); end function to_sfixed; function add_sign (arg : ufixed) return sfixed is variable result : sfixed (arg'high+1 downto arg'low); begin if arg'length < 1 then return NASF; end if; result (arg'high downto arg'low) := sfixed(cleanvec(arg)); result (arg'high+1) := '0'; return result; end function add_sign; -- Because of the farily 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', 'a' (abs), 'N', 'n' (-sfixed) function ufixed_high (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER is begin case operation is when '+'| '-' => return maximum (left_index, left_index2) + 1; when '*' => return left_index + left_index2 + 1; when '/' => return left_index - right_index2; when '1' => return -right_index; -- reciprocal when 'R'|'r' => return mins (left_index, left_index2); -- "rem" when 'M'|'m' => return mins (left_index, left_index2); -- "mod" when others => return left_index; -- For abs and default end case; end function ufixed_high; function ufixed_low (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER is begin case operation is when '+'| '-' => return mins (right_index, right_index2); when '*' => return right_index + right_index2; when '/' => return right_index - left_index2 - 1; when '1' => return -left_index - 1; -- reciprocal when 'R'|'r' => return mins (right_index, right_index2); -- "rem" when 'M'|'m' => return mins (right_index, right_index2); -- "mod" when others => return right_index; -- for abs and default end case; end function ufixed_low; function sfixed_high (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER is begin case operation is when '+'| '-' => return maximum (left_index, left_index2) + 1; when '*' => return left_index + left_index2 + 1; when '/' => return left_index - right_index2 + 1; when '1' => return -right_index + 1; -- reciprocal when 'R'|'r' => return mins (left_index, left_index2); -- "rem" when 'M'|'m' => return left_index2; -- "mod" when 'A'|'a' => return left_index + 1; -- "abs" when 'N'|'n' => return left_index + 1; -- -sfixed when others => return left_index; end case; end function sfixed_high; function sfixed_low (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER is begin case operation is when '+'| '-' => return mins (right_index, right_index2); when '*' => return right_index + right_index2; when '/' => return right_index - left_index2; when '1' => return -left_index; -- reciprocal when 'R'|'r' => return mins (right_index, right_index2); -- "rem" when 'M'|'m' => return mins (right_index, right_index2); -- "mod" when others => return right_index; -- default for abs, neg and default end case; end function sfixed_low; -- 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 : ufixed; operation : CHARACTER := 'X'; size_res2 : ufixed) return INTEGER is begin return ufixed_high (left_index => size_res'high, right_index => size_res'low, operation => operation, left_index2 => size_res2'high, right_index2 => size_res2'low); end function ufixed_high; function ufixed_low (size_res : ufixed; operation : CHARACTER := 'X'; size_res2 : ufixed) return INTEGER is begin return ufixed_low (left_index => size_res'high, right_index => size_res'low, operation => operation, left_index2 => size_res2'high, right_index2 => size_res2'low); end function ufixed_low; function sfixed_high (size_res : sfixed; operation : CHARACTER := 'X'; size_res2 : sfixed) return INTEGER is begin return sfixed_high (left_index => size_res'high, right_index => size_res'low, operation => operation, left_index2 => size_res2'high, right_index2 => size_res2'low); end function sfixed_high; function sfixed_low (size_res : sfixed; operation : CHARACTER := 'X'; size_res2 : sfixed) return INTEGER is begin return sfixed_low (left_index => size_res'high, right_index => size_res'low, operation => operation, left_index2 => size_res2'high, right_index2 => size_res2'low); end function sfixed_low; -- purpose: returns a saturated number function saturate ( constant left_index : INTEGER; constant right_index : INTEGER) return ufixed is constant sat : ufixed (left_index downto right_index) := (others => '1'); begin return sat; end function saturate; -- purpose: returns a saturated number function saturate ( constant left_index : INTEGER; constant right_index : INTEGER) return sfixed is variable sat : sfixed (left_index downto right_index) := (others => '1'); begin -- saturate positive, to saturate negative, just do "not saturate()" sat (left_index) := '0'; return sat; end function saturate; function saturate ( size_res : ufixed) -- only the size of this is used return ufixed is begin return saturate (size_res'high, size_res'low); end function saturate; function saturate ( size_res : sfixed) -- only the size of this is used return sfixed is begin return saturate (size_res'high, size_res'low); end function saturate; -- 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_LOGIC_VECTOR; width : NATURAL; -- width of vector fraction : NATURAL) -- width of fraction return ufixed is variable result : ufixed (width-fraction-1 downto -fraction); begin if (arg'length /= result'length) then report "FIXED_GENERIC_PKG.TO_UFIX (STD_LOGIC_VECTOR) " & "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_ufixed (arg, result'high, result'low); return result; end if; end function to_UFix; -- signed fixed point function to_SFix ( arg : STD_LOGIC_VECTOR; width : NATURAL; -- width of vector fraction : NATURAL) -- width of fraction return sfixed is variable result : sfixed (width-fraction-1 downto -fraction); begin if (arg'length /= result'length) then report "FIXED_GENERIC_PKG.TO_SFIX (STD_LOGIC_VECTOR) " & "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_sfixed (arg, result'high, result'low); return result; end if; end function to_SFix; -- 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 is begin return ufixed_high (left_index => width - 1 - fraction, right_index => -fraction, operation => operation, left_index2 => width2 - 1 - fraction2, right_index2 => -fraction2); end function ufix_high; function ufix_low ( width, fraction : NATURAL; operation : CHARACTER := 'X'; width2, fraction2 : NATURAL := 0) return INTEGER is begin return ufixed_low (left_index => width - 1 - fraction, right_index => -fraction, operation => operation, left_index2 => width2 - 1 - fraction2, right_index2 => -fraction2); end function ufix_low; function sfix_high ( width, fraction : NATURAL; operation : CHARACTER := 'X'; width2, fraction2 : NATURAL := 0) return INTEGER is begin return sfixed_high (left_index => width - fraction, right_index => -fraction, operation => operation, left_index2 => width2 - fraction2, right_index2 => -fraction2); end function sfix_high; function sfix_low ( width, fraction : NATURAL; operation : CHARACTER := 'X'; width2, fraction2 : NATURAL := 0) return INTEGER is begin return sfixed_low (left_index => width - fraction, right_index => -fraction, operation => operation, left_index2 => width2 - fraction2, right_index2 => -fraction2); end function sfix_low; function to_unsigned ( arg : ufixed; -- ufixed point input constant size : NATURAL; -- length of output constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return UNSIGNED is begin return to_uns(resize (arg => arg, left_index => size-1, right_index => 0, round_style => round_style, overflow_style => overflow_style)); end function to_unsigned; function to_unsigned ( arg : ufixed; -- ufixed point input size_res : UNSIGNED; -- length of output constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return UNSIGNED is begin return to_unsigned (arg => arg, size => size_res'length, round_style => round_style, overflow_style => overflow_style); end function to_unsigned; function to_signed ( arg : sfixed; -- ufixed point input constant size : NATURAL; -- length of output constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return SIGNED is begin return to_s(resize (arg => arg, left_index => size-1, right_index => 0, round_style => round_style, overflow_style => overflow_style)); end function to_signed; function to_signed ( arg : sfixed; -- ufixed point input size_res : SIGNED; -- used for length of output constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return SIGNED is begin return to_signed (arg => arg, size => size_res'length, round_style => round_style, overflow_style => overflow_style); end function to_signed; function to_real ( arg : ufixed) -- ufixed point input return REAL is constant left_index : INTEGER := arg'high; constant right_index : INTEGER := arg'low; variable result : REAL; -- result variable arg_int : ufixed (left_index downto right_index); begin if (arg'length < 1) then return 0.0; end if; arg_int := cleanvec(arg); if (Is_X(arg_int)) then assert NO_WARNING report "FIXED_GENERIC_PKG.TO_REAL: metavalue detected, returning 0.0" severity warning; return 0.0; end if; result := 0.0; for i in arg_int'range loop if (arg_int(i) = '1') then result := result + (2.0**i); end if; end loop; return result; end function to_real; function to_real ( arg : sfixed) -- ufixed point input return REAL is constant left_index : INTEGER := arg'high; constant right_index : INTEGER := arg'low; variable result : REAL; -- result variable arg_int : sfixed (left_index downto right_index); -- unsigned version of argument variable arg_uns : ufixed (left_index downto right_index); -- absolute of argument begin if (arg'length < 1) then return 0.0; end if; arg_int := cleanvec(arg); if (Is_X(arg_int)) then assert NO_WARNING report "FIXED_GENERIC_PKG.TO_REAL: metavalue detected, returning 0.0" severity warning; return 0.0; end if; arg_uns := abs(arg_int); result := to_real (arg_uns); if (arg_int(arg_int'high) = '1') then result := -result; end if; return result; end function to_real; function to_integer ( arg : ufixed; -- fixed point input constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return NATURAL is constant left_index : INTEGER := arg'high; variable arg_uns : UNSIGNED (minimum(31, left_index+1) downto 0) := (others => '0'); begin if (arg'length < 1) then return 0; end if; if (Is_X (arg)) then assert NO_WARNING report "FIXED_GENERIC_PKG.TO_INTEGER: metavalue detected, returning 0" severity warning; return 0; end if; if (left_index < -1) then return 0; end if; arg_uns := to_uns(resize (arg => arg, left_index => arg_uns'high, right_index => 0, round_style => round_style, overflow_style => overflow_style)); return to_integer (arg_uns); end function to_integer; function to_integer ( arg : sfixed; -- fixed point input constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- rounding by default return INTEGER is constant left_index : INTEGER := arg'high; constant right_index : INTEGER := arg'low; variable arg_s : SIGNED (minimum(31, left_index+1) downto 0); begin if (arg'length < 1) then return 0; end if; if (Is_X (arg)) then assert NO_WARNING report "FIXED_GENERIC_PKG.TO_INTEGER: metavalue detected, returning 0" severity warning; return 0; end if; if (left_index < -1) then return 0; end if; arg_s := to_s(resize (arg => arg, left_index => arg_s'high, right_index => 0, round_style => round_style, overflow_style => overflow_style)); return to_integer (arg_s); end function to_integer; function to_01 ( s : ufixed; -- ufixed point input constant XMAP : STD_LOGIC := '0') -- Map x to return ufixed is variable result : ufixed (s'range); -- result begin for i in s'range loop case s(i) is when '0' | 'L' => result(i) := '0'; when '1' | 'H' => result(i) := '1'; when others => result(i) := XMAP; end case; end loop; return result; end function to_01; function to_01 ( s : sfixed; -- ufixed point input constant XMAP : STD_LOGIC := '0') -- Map x to return sfixed is variable result : sfixed (s'range); begin for i in s'range loop case s(i) is when '0' | 'L' => result(i) := '0'; when '1' | 'H' => result(i) := '1'; when others => result(i) := XMAP; end case; end loop; return result; end function to_01; function Is_X ( arg : ufixed) return BOOLEAN is variable argslv : STD_LOGIC_VECTOR (arg'length-1 downto 0); -- slv begin argslv := to_slv(arg); return Is_X(argslv); end function Is_X; function Is_X ( arg : sfixed) return BOOLEAN is variable argslv : STD_LOGIC_VECTOR (arg'length-1 downto 0); -- slv begin argslv := to_slv(arg); return Is_X(argslv); end function Is_X; function To_X01 ( arg : ufixed) return ufixed is begin return to_ufixed (To_X01(to_slv(arg)), arg'high, arg'low); end function To_X01; function to_X01 ( arg : sfixed) return sfixed is begin return to_sfixed (To_X01(to_slv(arg)), arg'high, arg'low); end function To_X01; function To_X01Z ( arg : ufixed) return ufixed is begin return to_ufixed (To_X01Z(to_slv(arg)), arg'high, arg'low); end function To_X01Z; function to_X01Z ( arg : sfixed) return sfixed is begin return to_sfixed (To_X01Z(to_slv(arg)), arg'high, arg'low); end function To_X01Z; function To_UX01 ( arg : ufixed) return ufixed is begin return to_ufixed (To_UX01(to_slv(arg)), arg'high, arg'low); end function To_UX01; function to_UX01 ( arg : sfixed) return sfixed is begin return to_sfixed (To_UX01(to_slv(arg)), arg'high, arg'low); end function To_UX01; function resize ( arg : ufixed; -- input constant left_index : INTEGER; -- integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow constant round_style : BOOLEAN := fixed_round_style) -- rounding return ufixed is constant arghigh : INTEGER := maximum (arg'high, arg'low); constant arglow : INTEGER := mine (arg'high, arg'low); variable invec : ufixed (arghigh downto arglow); variable result : ufixed(left_index downto right_index) := (others => '0'); variable needs_rounding : BOOLEAN := false; begin -- resize if (arg'length < 1) or (result'length < 1) then return NAUF; elsif (invec'length < 1) then return result; -- string literal value else invec := cleanvec(arg); if (right_index > arghigh) then -- return top zeros needs_rounding := (round_style = fixed_round) and (right_index = arghigh+1); elsif (left_index < arglow) then -- return overflow if (overflow_style = fixed_saturate) and (or_reducex(to_slv(invec)) = '1') then result := saturate (result'high, result'low); -- saturate end if; elsif (arghigh > left_index) then -- wrap or saturate? if (overflow_style and or_reducex(to_slv(invec(arghigh downto left_index+1))) = '1') then result := saturate (result'high, result'low); -- saturate else if (arglow >= right_index) then result (left_index downto arglow) := invec(left_index downto arglow); else result (left_index downto right_index) := invec (left_index downto right_index); needs_rounding := (round_style = fixed_round); -- round end if; end if; else -- arghigh <= integer width if (arglow >= right_index) then result (arghigh downto arglow) := invec; else result (arghigh downto right_index) := invec (arghigh downto right_index); needs_rounding := (round_style = fixed_round); -- round end if; end if; -- Round result if needs_rounding then result := round_fixed (arg => result, remainder => invec (right_index-1 downto arglow), overflow_style => overflow_style); end if; return result; end if; end function resize; function resize ( arg : sfixed; -- input constant left_index : INTEGER; -- integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow constant round_style : BOOLEAN := fixed_round_style) -- rounding return sfixed is constant arghigh : INTEGER := maximum (arg'high, arg'low); constant arglow : INTEGER := mine (arg'high, arg'low); variable invec : sfixed (arghigh downto arglow); variable result : sfixed(left_index downto right_index) := (others => '0'); variable reduced : STD_ULOGIC; variable needs_rounding : BOOLEAN := false; -- rounding begin -- resize if (arg'length < 1) or (result'length < 1) then return NASF; elsif (invec'length < 1) then return result; -- string literal value else invec := cleanvec(arg); if (right_index > arghigh) then -- return top zeros if (arg'low /= INTEGER'low) then -- check for a literal result := (others => arg(arghigh)); -- sign extend end if; needs_rounding := (round_style = fixed_round) and (right_index = arghigh+1); elsif (left_index < arglow) then -- return overflow if (overflow_style) then reduced := or_reducex(to_slv(invec)); if (reduced = '1') then if (invec(arghigh) = '0') then -- saturate POSITIVE result := saturate (result'high, result'low); else -- saturate negative result := not saturate (result'high, result'low); end if; -- else return 0 (input was 0) end if; -- else return 0 (wrap) end if; elsif (arghigh > left_index) then if (invec(arghigh) = '0') then reduced := or_reducex(to_slv(invec(arghigh-1 downto left_index))); if overflow_style and reduced = '1' then -- saturate positive result := saturate (result'high, result'low); else if (right_index > arglow) then result := invec (left_index downto right_index); needs_rounding := (round_style = fixed_round); else result (left_index downto arglow) := invec (left_index downto arglow); end if; end if; else reduced := and_reducex(to_slv(invec(arghigh-1 downto left_index))); if overflow_style and reduced = '0' then result := not saturate (result'high, result'low); else if (right_index > arglow) then result := invec (left_index downto right_index); needs_rounding := (round_style = fixed_round); else result (left_index downto arglow) := invec (left_index downto arglow); end if; end if; end if; else -- arghigh <= integer width if (arglow >= right_index) then result (arghigh downto arglow) := invec; else result (arghigh downto right_index) := invec (arghigh downto right_index); needs_rounding := (round_style = fixed_round); -- round end if; if (left_index > arghigh) then -- sign extend result(left_index downto arghigh+1) := (others => invec(arghigh)); end if; end if; -- Round result if (needs_rounding) then result := round_fixed (arg => result, remainder => invec (right_index-1 downto arglow), overflow_style => overflow_style); end if; return result; end if; end function resize; -- size_res functions -- These functions compute the size from a passed variable named "size_res" -- The only part of this variable used it it's size, it is never passed -- to a lower level routine. function to_ufixed ( arg : STD_LOGIC_VECTOR; -- shifted vector size_res : ufixed) -- for size only return ufixed is variable result : ufixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_ufixed (arg => arg, left_index => size_res'high, right_index => size_res'low); return result; end if; end function to_ufixed; function to_sfixed ( arg : STD_LOGIC_VECTOR; -- shifted vector size_res : sfixed) -- for size only return sfixed is variable result : sfixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_sfixed (arg => arg, left_index => size_res'high, right_index => size_res'low); return result; end if; end function to_sfixed; function to_ufixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector size_res : ufixed) -- for size only return ufixed is variable result : ufixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_ufixed (arg => to_stdlogicvector(arg), left_index => size_res'high, right_index => size_res'low); return result; end if; end function to_ufixed; function to_sfixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector size_res : sfixed) -- for size only return sfixed is variable result : sfixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_sfixed (arg => to_stdlogicvector(arg), left_index => size_res'high, right_index => size_res'low); return result; end if; end function to_sfixed; function to_ufixed ( arg : NATURAL; -- integer size_res : ufixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default return ufixed is variable result : ufixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_ufixed (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_ufixed; function to_sfixed ( arg : INTEGER; -- integer size_res : sfixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default return sfixed is variable result : sfixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_sfixed (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_sfixed; function to_ufixed ( arg : REAL; -- real size_res : ufixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return ufixed is variable result : ufixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_ufixed (arg => arg, left_index => size_res'high, right_index => size_res'low, guard_bits => guard_bits, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_ufixed; function to_sfixed ( arg : REAL; -- real size_res : sfixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return sfixed is variable result : sfixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_sfixed (arg => arg, left_index => size_res'high, right_index => size_res'low, guard_bits => guard_bits, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_sfixed; function to_ufixed ( arg : UNSIGNED; -- unsigned size_res : ufixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow constant round_style : BOOLEAN := fixed_round_style) -- rounding return ufixed is variable result : ufixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_ufixed (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_ufixed; function to_sfixed ( arg : SIGNED; -- signed size_res : sfixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default return sfixed is variable result : sfixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_sfixed (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_sfixed; function resize ( arg : ufixed; -- input size_res : ufixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow constant round_style : BOOLEAN := fixed_round_style) -- rounding return ufixed is variable result : ufixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := resize (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function resize; function resize ( arg : sfixed; -- input size_res : sfixed; -- for size only constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow constant round_style : BOOLEAN := fixed_round_style) -- rounding return sfixed is variable result : sfixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := resize (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function resize; -- Overloaded functions function "+" ( l : ufixed; -- fixed point input r : REAL) return ufixed is begin return (l + to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "+"; function "+" ( l : REAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) + r); end function "+"; function "+" ( l : sfixed; -- fixed point input r : REAL) return sfixed is begin return (l + to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "+"; function "+" ( l : REAL; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) + r); end function "+"; -- Overloaded functions function "-" ( l : ufixed; -- fixed point input r : REAL) return ufixed is begin return (l - to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "-"; function "-" ( l : REAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) - r); end function "-"; function "-" ( l : sfixed; -- fixed point input r : REAL) return sfixed is begin return (l - to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "-"; function "-" ( l : REAL; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) - r); end function "-"; -- Overloaded functions function "*" ( l : ufixed; -- fixed point input r : REAL) return ufixed is begin return (l * to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "*"; function "*" ( l : REAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) * r); end function "*"; function "*" ( l : sfixed; -- fixed point input r : REAL) return sfixed is begin return (l * to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "*"; function "*" ( l : REAL; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) * r); end function "*"; -- Overloaded functions function "/" ( l : ufixed; -- fixed point input r : REAL) return ufixed is begin return (l / to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "/"; function "/" ( l : REAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) / r); end function "/"; function "/" ( l : sfixed; -- fixed point input r : REAL) return sfixed is begin return (l / to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "/"; function "/" ( l : REAL; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) / r); end function "/"; -- Overloaded functions function "rem" ( l : ufixed; -- fixed point input r : REAL) return ufixed is begin return (l rem to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "rem"; function "rem" ( l : REAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) rem r); end function "rem"; function "rem" ( l : sfixed; -- fixed point input r : REAL) return sfixed is begin return (l rem to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "rem"; function "rem" ( l : REAL; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) rem r); end function "rem"; function "mod" ( l : ufixed; -- fixed point input r : REAL) return ufixed is begin return (l mod to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "mod"; function "mod" ( l : REAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) mod r); end function "mod"; function "mod" ( l : sfixed; -- fixed point input r : REAL) return sfixed is begin return (l mod to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "mod"; function "mod" ( l : REAL; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) mod r); end function "mod"; -- Overloaded functions for integers function "+" ( l : ufixed; -- fixed point input r : NATURAL) return ufixed is begin return (l + to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); -- rounding not needed end function "+"; function "+" ( l : NATURAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) + r); end function "+"; function "+" ( l : sfixed; -- fixed point input r : INTEGER) return sfixed is begin return (l + to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "+"; function "+" ( l : INTEGER; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) + r); end function "+"; -- Overloaded functions function "-" ( l : ufixed; -- fixed point input r : NATURAL) return ufixed is begin return (l - to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "-"; function "-" ( l : NATURAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) - r); end function "-"; function "-" ( l : sfixed; -- fixed point input r : INTEGER) return sfixed is begin return (l - to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "-"; function "-" ( l : INTEGER; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) - r); end function "-"; -- Overloaded functions function "*" ( l : ufixed; -- fixed point input r : NATURAL) return ufixed is begin return (l * to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "*"; function "*" ( l : NATURAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) * r); end function "*"; function "*" ( l : sfixed; -- fixed point input r : INTEGER) return sfixed is begin return (l * to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "*"; function "*" ( l : INTEGER; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) * r); end function "*"; -- Overloaded functions function "/" ( l : ufixed; -- fixed point input r : NATURAL) return ufixed is begin return (l / to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "/"; function "/" ( l : NATURAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) / r); end function "/"; function "/" ( l : sfixed; -- fixed point input r : INTEGER) return sfixed is begin return (l / to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "/"; function "/" ( l : INTEGER; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) / r); end function "/"; -- Overloaded functions function "rem" ( l : ufixed; -- fixed point input r : NATURAL) return ufixed is begin return (l rem to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "rem"; function "rem" ( l : NATURAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) rem r); end function "rem"; function "rem" ( l : sfixed; -- fixed point input r : INTEGER) return sfixed is begin return (l rem to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "rem"; function "rem" ( l : INTEGER; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) rem r); end function "rem"; function "mod" ( l : ufixed; -- fixed point input r : NATURAL) return ufixed is begin return (l mod to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "mod"; function "mod" ( l : NATURAL; r : ufixed) -- fixed point input return ufixed is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) mod r); end function "mod"; function "mod" ( l : sfixed; -- fixed point input r : INTEGER) return sfixed is begin return (l mod to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "mod"; function "mod" ( l : INTEGER; r : sfixed) -- fixed point input return sfixed is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) mod r); end function "mod"; -- overloaded compare functions function "=" ( l : ufixed; r : NATURAL) -- fixed point input return BOOLEAN is begin return (l = to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "="; function "/=" ( l : ufixed; r : NATURAL) -- fixed point input return BOOLEAN is begin return (l /= to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "/="; function ">=" ( l : ufixed; r : NATURAL) -- fixed point input return BOOLEAN is begin return (l >= to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function ">="; function "<=" ( l : ufixed; r : NATURAL) -- fixed point input return BOOLEAN is begin return (l <= to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "<="; function ">" ( l : ufixed; r : NATURAL) -- fixed point input return BOOLEAN is begin return (l > to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function ">"; function "<" ( l : ufixed; r : NATURAL) -- fixed point input return BOOLEAN is begin return (l < to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "<"; function "=" ( l : NATURAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) = r); end function "="; function "/=" ( l : NATURAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) /= r); end function "/="; function ">=" ( l : NATURAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) >= r); end function ">="; function "<=" ( l : NATURAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) <= r); end function "<="; function ">" ( l : NATURAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) > r); end function ">"; function "<" ( l : NATURAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) < r); end function "<"; function "=" ( l : ufixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l = to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "="; function "/=" ( l : ufixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l /= to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "/="; function ">=" ( l : ufixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l >= to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function ">="; function "<=" ( l : ufixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l <= to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "<="; function ">" ( l : ufixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l > to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function ">"; function "<" ( l : ufixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l < to_ufixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "<"; function "=" ( l : REAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) = r); end function "="; function "/=" ( l : REAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) /= r); end function "/="; function ">=" ( l : REAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) >= r); end function ">="; function "<=" ( l : REAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) <= r); end function "<="; function ">" ( l : REAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) > r); end function ">"; function "<" ( l : REAL; r : ufixed) -- fixed point input return BOOLEAN is begin return (to_ufixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) < r); end function "<"; function "=" ( l : sfixed; r : INTEGER) -- fixed point input return BOOLEAN is begin return (l = to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "="; function "/=" ( l : sfixed; r : INTEGER) -- fixed point input return BOOLEAN is begin return (l /= to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "/="; function ">=" ( l : sfixed; r : INTEGER) -- fixed point input return BOOLEAN is begin return (l >= to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function ">="; function "<=" ( l : sfixed; r : INTEGER) -- fixed point input return BOOLEAN is begin return (l <= to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "<="; function ">" ( l : sfixed; r : INTEGER) -- fixed point input return BOOLEAN is begin return (l > to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function ">"; function "<" ( l : sfixed; r : INTEGER) -- fixed point input return BOOLEAN is begin return (l < to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style)); end function "<"; function "=" ( l : INTEGER; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) = r); end function "="; function "/=" ( l : INTEGER; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) /= r); end function "/="; function ">=" ( l : INTEGER; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) >= r); end function ">="; function "<=" ( l : INTEGER; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) <= r); end function "<="; function ">" ( l : INTEGER; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) > r); end function ">"; function "<" ( l : INTEGER; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style) < r); end function "<"; function "=" ( l : sfixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l = to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "="; function "/=" ( l : sfixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l /= to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "/="; function ">=" ( l : sfixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l >= to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function ">="; function "<=" ( l : sfixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l <= to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "<="; function ">" ( l : sfixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l > to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function ">"; function "<" ( l : sfixed; r : REAL) -- fixed point input return BOOLEAN is begin return (l < to_sfixed (arg => r, left_index => l'high, right_index => l'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits)); end function "<"; function "=" ( l : REAL; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) = r); end function "="; function "/=" ( l : REAL; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) /= r); end function "/="; function ">=" ( l : REAL; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) >= r); end function ">="; function "<=" ( l : REAL; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) <= r); end function "<="; function ">" ( l : REAL; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) > r); end function ">"; function "<" ( l : REAL; r : sfixed) -- fixed point input return BOOLEAN is begin return (to_sfixed (arg => l, left_index => r'high, right_index => r'low, overflow_style => fixed_overflow_style, round_style => fixed_round_style, guard_bits => fixed_guard_bits) < r); end function "<"; -- rtl_synthesis off -- synthesis translate_off -- copied from std_logic_textio type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', error); type char_indexed_by_MVL9 is array (STD_ULOGIC) of CHARACTER; type MVL9_indexed_by_char is array (CHARACTER) of STD_ULOGIC; type MVL9plus_indexed_by_char is array (CHARACTER) of MVL9plus; constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-"; constant char_to_MVL9 : MVL9_indexed_by_char := ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); constant char_to_MVL9plus : MVL9plus_indexed_by_char := ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => error); constant NBSP : CHARACTER := CHARACTER'val(160); -- space character constant NUS : STRING(2 to 1) := (others => ' '); -- purpose: writes fixed point into a line procedure write ( L : inout LINE; -- input line VALUE : in ufixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is variable s : STRING(1 to value'length +1) := (others => ' '); variable sindx : INTEGER; begin -- function write Example: 0011.1100 sindx := 1; for i in value'high downto value'low loop if i = -1 then s(sindx) := '.'; sindx := sindx +1; end if; s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); sindx := sindx +1; end loop; write(l, s, justified, field); end procedure write; -- purpose: writes fixed point into a line procedure write ( L : inout LINE; -- input line VALUE : in sfixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is variable s : STRING(1 to value'length +1); variable sindx : INTEGER; begin -- function write Example: 0011.1100 sindx := 1; for i in value'high downto value'low loop if i = -1 then s(sindx) := '.'; sindx := sindx +1; end if; s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); sindx := sindx +1; end loop; write(l, s, justified, field); end procedure write; procedure READ(L : inout LINE; VALUE : out ufixed) is -- Possible data: 00000.0000000 -- 000000000000 variable c : CHARACTER; variable s : STRING(1 to value'length-1); variable readOk : BOOLEAN; variable i : INTEGER; -- index variable begin -- READ VALUE (VALUE'range) := (others => 'U'); loop -- skip white space read(l, c, readOk); exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; i := value'high; readloop : loop if readOk = false then -- Bail out if there was a bad read report "FIXED_GENERIC_PKG.READ(ufixed) " & "Error: end of string encountered" severity error; return; elsif c = ' ' or c = NBSP or c = HT then -- reading done. assert i = value'low report "FIXED_GENERIC_PKG.READ(ufixed) " & "Warning: Value truncated " severity warning; return; elsif c = '.' then -- separator, ignore assert (i = -1) report "FIXED_GENERIC_PKG.READ(ufixed) " & "Warning: Decimal point does not match number format " severity warning; elsif (char_to_MVL9plus(c) = error) then report "FIXED_GENERIC_PKG.READ(ufixed) " & "Error: Character '" & c & "' read, expected STD_ULOGIC literal." severity error; return; else value (i) := char_to_MVL9(c); i := i - 1; if i < value'low then return; end if; end if; read(l, c, readOk); end loop readloop; end procedure READ; procedure READ(L : inout LINE; VALUE : out ufixed; GOOD : out BOOLEAN) is -- Possible data: 00000.0000000 -- 000000000000 variable c : CHARACTER; variable i : INTEGER; -- index variable variable readOk : BOOLEAN; begin -- READ VALUE (VALUE'range) := (others => 'U'); loop -- skip white space read(l, c, readOk); exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; i := value'high; good := true; readloop : loop if readOk = false then -- Bail out if there was a bad read good := false; return; elsif c = ' ' or c = NBSP or c = HT then -- reading done good := false; return; elsif c = '.' then -- separator, ignore good := (i = -1); elsif (char_to_MVL9plus(c) = error) then good := false; return; else value (i) := char_to_MVL9(c); i := i - 1; if i < value'low then return; end if; end if; read(l, c, readOk); end loop readloop; end procedure READ; procedure READ(L : inout LINE; VALUE : out sfixed) is -- Possible data: 00000.0000000 -- 000000000000 variable c : CHARACTER; variable readOk : BOOLEAN; variable i : INTEGER; -- index variable begin -- READ VALUE (VALUE'range) := (others => 'U'); loop -- skip white space read(l, c, readOk); exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; i := value'high; readloop : loop if readOk = false then -- Bail out if there was a bad read report "FIXED_GENERIC_PKG.READ(sfixed) " & "Error end of string encountered" severity error; return; elsif c = ' ' or c = NBSP or c = HT then -- reading done. assert i = value'low report "FIXED_GENERIC_PKG.READ(sfixed) " & "Warning: Value truncated " severity warning; return; elsif c = '.' then -- separator, ignore assert (i = -1) report "FIXED_GENERIC_PKG.READ(sfixed) " & "Warning: Decimal point does not match number format " severity warning; elsif (char_to_MVL9plus(c) = error) then report "FIXED_GENERIC_PKG.READ(sfixed) " & "Error: Character '" & c & "' read, expected STD_ULOGIC literal." severity error; return; else value (i) := char_to_MVL9(c); i := i - 1; if i < value'low then return; end if; end if; read(l, c, readOk); end loop readloop; end procedure READ; procedure READ(L : inout LINE; VALUE : out sfixed; GOOD : out BOOLEAN) is -- Possible data: 00000.0000000 -- 000000000000 variable c : CHARACTER; variable i : INTEGER; -- index variable variable readOk : BOOLEAN; begin -- READ VALUE (VALUE'range) := (others => 'U'); loop -- skip white space read(l, c, readOk); exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; i := value'high; good := true; readloop : loop if readOk = false then -- Bail out if there was a bad read good := false; return; elsif c = ' ' or c = NBSP or c = HT then -- reading done good := false; return; elsif c = '.' then -- separator, ignore good := (i = -1); elsif (char_to_MVL9plus(c) = error) then good := false; return; else value (i) := char_to_MVL9(c); i := i - 1; if i < value'low then return; end if; end if; read(l, c, readOk); end loop readloop; end procedure READ; -- octal read and write procedure owrite ( L : inout LINE; -- input line VALUE : in ufixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is begin -- Example 03.30 write (L => L, VALUE => to_ostring (VALUE), JUSTIFIED => JUSTIFIED, FIELD => FIELD); end procedure owrite; procedure owrite ( L : inout LINE; -- input line VALUE : in sfixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is begin -- Example 03.30 write (L => L, VALUE => to_ostring (VALUE), JUSTIFIED => JUSTIFIED, FIELD => FIELD); end procedure owrite; procedure Char2TriBits (C : CHARACTER; RESULT : out STD_LOGIC_VECTOR(2 downto 0); GOOD : out BOOLEAN; ISSUE_ERROR : in BOOLEAN) is begin case c is when '0' => result := o"0"; good := true; when '1' => result := o"1"; good := true; when '2' => result := o"2"; good := true; when '3' => result := o"3"; good := true; when '4' => result := o"4"; good := true; when '5' => result := o"5"; good := true; when '6' => result := o"6"; good := true; when '7' => result := o"7"; good := true; when 'Z' => result := "ZZZ"; good := true; when 'X' => result := "XXX"; good := true; when others => assert not ISSUE_ERROR report "FIXED_GENERIC_PKG.OREAD Error: Read a '" & c & "', expected an Octal character (0-7)." severity error; result := "UUU"; good := false; end case; end procedure Char2TriBits; -- Note that for Octal and Hex read, you can not start with a ".", -- the read is for numbers formatted "A.BC". These routines go to -- the nearest bounds, so "F.E" will fit into an sfixed (2 downto -3). procedure OREAD(L : inout LINE; VALUE : out ufixed) is constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits variable c : CHARACTER; -- to read the "." variable valuex : ufixed (hbv downto lbv); variable igood : BOOLEAN; variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits variable i : INTEGER; begin VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" loop -- skip white space read(L, c, igood); exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; if igood = false then report "FIXED_GENERIC_PKG.OREAD(ufixed): " & "Error end of string encountered" severity error; return; else Char2triBits(c, nybble, igood, true); i := hbv-lbv - 3; -- Top - 3 slv (hbv-lbv downto i+1) := nybble; end if; while (i /= -1) and igood and L.all'length /= 0 loop read (L, c, igood); if igood = false then report "FIXED_GENERIC_PKG.OREAD(ufixed): " & "Error end of string encountered" severity error; elsif (c = '.') then if (i + 1 /= -lbv) then igood := false; report "FIXED_GENERIC_PKG.OREAD(ufixed): " & "encountered ""."" at wrong index" severity error; end if; else Char2TriBits(c, nybble, igood, true); slv (i downto i-2) := nybble; i := i - 3; end if; end loop; if igood then -- We did not get another error assert (i = -1) and -- We read everything, and high bits 0 (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') report "FIXED_GENERIC_PKG.OREAD(ufixed): Vector truncated." severity error; if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then assert NO_WARNING report "FIXED_GENERIC_PKG.OREAD(ufixed): Vector truncated" severity warning; end if; end if; valuex := to_ufixed (slv, hbv, lbv); VALUE := valuex (VALUE'range); end procedure OREAD; procedure OREAD(L : inout LINE; VALUE : out ufixed; GOOD : out BOOLEAN) is constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits variable c : CHARACTER; -- to read the "." variable valuex : ufixed (hbv downto lbv); variable igood : BOOLEAN; variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits variable i : INTEGER; begin VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" loop -- skip white space read(L, c, igood); exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; if igood = false then return; else Char2triBits(c, nybble, igood, false); i := hbv-lbv - 3; -- Top - 3 slv (hbv-lbv downto i+1) := nybble; end if; while (i /= -1) and igood and L.all'length /= 0 loop read (L, c, igood); if igood then if (c = '.') then igood := igood and (i + 1 = -lbv); else Char2TriBits(c, nybble, igood, false); slv (i downto i-2) := nybble; i := i - 3; end if; end if; end loop; good := igood and -- We did not get another error (i = -1) and -- We read everything, and high bits 0 (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0'); valuex := to_ufixed (slv, hbv, lbv); VALUE := valuex (VALUE'range); end procedure OREAD; procedure OREAD(L : inout LINE; VALUE : out sfixed) is constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits variable c : CHARACTER; -- to read the "." variable valuex : sfixed (hbv downto lbv); variable igood : BOOLEAN; variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits variable i : INTEGER; begin VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" loop -- skip white space read(L, c, igood); exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; if igood = false then report "FIXED_GENERIC_PKG.OREAD(sfixed): " & "Error end of string encountered" severity error; return; else Char2triBits(c, nybble, igood, true); i := hbv-lbv - 3; -- Top - 3 slv (hbv-lbv downto i+1) := nybble; end if; while (i /= -1) and igood and L.all'length /= 0 loop read (L, c, igood); if igood = false then report "FIXED_GENERIC_PKG.OREAD(sfixed): " & "Error end of string encountered" severity error; elsif (c = '.') then if (i + 1 /= -lbv) then igood := false; report "FIXED_GENERIC_PKG.OREAD(sfixed): " & "encountered ""."" at wrong index" severity error; end if; else Char2TriBits(c, nybble, igood, true); slv (i downto i-2) := nybble; i := i - 3; end if; end loop; if igood then -- We did not get another error assert (i = -1) and -- We read everything ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or (slv(VALUE'high-lbv) = '1' and and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')) report "FIXED_GENERIC_PKG.OREAD(sfixed): Vector truncated." severity error; if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then assert NO_WARNING report "FIXED_GENERIC_PKG.OREAD(sfixed): Vector truncated" severity warning; end if; end if; valuex := to_sfixed (slv, hbv, lbv); VALUE := valuex (VALUE'range); end procedure OREAD; procedure OREAD(L : inout LINE; VALUE : out sfixed; GOOD : out BOOLEAN) is constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits variable c : CHARACTER; -- to read the "." variable valuex : sfixed (hbv downto lbv); variable igood : BOOLEAN; variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits variable i : INTEGER; begin VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" loop -- skip white space read(L, c, igood); exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; if igood = false then return; else Char2triBits(c, nybble, igood, false); i := hbv-lbv - 3; -- Top - 3 slv (hbv-lbv downto i+1) := nybble; end if; while (i /= -1) and igood and L.all'length /= 0 loop read (L, c, igood); if igood then if (c = '.') then igood := igood and (i + 1 = -lbv); else Char2TriBits(c, nybble, igood, false); slv (i downto i-2) := nybble; i := i - 3; end if; end if; end loop; good := igood -- We did not get another error and (i = -1) -- We read everything and ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or (slv(VALUE'high-lbv) = '1' and and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')); valuex := to_sfixed (slv, hbv, lbv); VALUE := valuex (VALUE'range); end procedure OREAD; -- hex read and write procedure hwrite ( L : inout LINE; -- input line VALUE : in ufixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is begin -- Example 03.30 write (L => L, VALUE => to_hstring (VALUE), JUSTIFIED => JUSTIFIED, FIELD => FIELD); end procedure hwrite; -- purpose: writes fixed point into a line procedure hwrite ( L : inout LINE; -- input line VALUE : in sfixed; -- fixed point input JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is begin -- Example 03.30 write (L => L, VALUE => to_hstring (VALUE), JUSTIFIED => JUSTIFIED, FIELD => FIELD); end procedure hwrite; -- Hex Read and Write procedures for STD_ULOGIC_VECTOR. -- Modified from the original to be more forgiving. procedure Char2QuadBits (C : CHARACTER; RESULT : out STD_LOGIC_VECTOR(3 downto 0); GOOD : out BOOLEAN; ISSUE_ERROR : in BOOLEAN) is begin case c is when '0' => result := x"0"; good := true; when '1' => result := x"1"; good := true; when '2' => result := x"2"; good := true; when '3' => result := x"3"; good := true; when '4' => result := x"4"; good := true; when '5' => result := x"5"; good := true; when '6' => result := x"6"; good := true; when '7' => result := x"7"; good := true; when '8' => result := x"8"; good := true; when '9' => result := x"9"; good := true; when 'A' | 'a' => result := x"A"; good := true; when 'B' | 'b' => result := x"B"; good := true; when 'C' | 'c' => result := x"C"; good := true; when 'D' | 'd' => result := x"D"; good := true; when 'E' | 'e' => result := x"E"; good := true; when 'F' | 'f' => result := x"F"; good := true; when 'Z' => result := "ZZZZ"; good := true; when 'X' => result := "XXXX"; good := true; when others => assert not ISSUE_ERROR report "FIXED_GENERIC_PKG.HREAD Error: Read a '" & c & "', expected a Hex character (0-F)." severity error; result := "UUUU"; good := false; end case; end procedure Char2QuadBits; procedure HREAD(L : inout LINE; VALUE : out ufixed) is constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits variable c : CHARACTER; -- to read the "." variable valuex : ufixed (hbv downto lbv); variable igood : BOOLEAN; variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits variable i : INTEGER; begin VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" loop -- skip white space read(L, c, igood); exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; if igood = false then report "FIXED_GENERIC_PKG.HREAD(ufixed): " & "Error end of string encountered" severity error; return; else Char2QuadBits(c, nybble, igood, true); i := hbv-lbv - 4; -- Top - 4 slv (hbv-lbv downto i+1) := nybble; end if; while (i /= -1) and igood and L.all'length /= 0 loop read (L, c, igood); if igood = false then report "FIXED_GENERIC_PKG.HREAD(ufixed): " & "Error end of string encountered" severity error; elsif (c = '.') then if (i + 1 /= -lbv) then igood := false; report "FIXED_GENERIC_PKG.HREAD(ufixed): " & "encountered ""."" at wrong index" severity error; end if; else Char2QuadBits(c, nybble, igood, true); slv (i downto i-3) := nybble; i := i - 4; end if; end loop; if igood then -- We did not get another error assert (i = -1) and -- We read everything, and high bits 0 (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') report "FIXED_GENERIC_PKG.HREAD(ufixed): Vector truncated." severity error; if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then assert NO_WARNING report "FIXED_GENERIC_PKG.HREAD(ufixed): Vector truncated" severity warning; end if; end if; valuex := to_ufixed (slv, hbv, lbv); VALUE := valuex (VALUE'range); end procedure HREAD; procedure HREAD(L : inout LINE; VALUE : out ufixed; GOOD : out BOOLEAN) is constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits variable c : CHARACTER; -- to read the "." variable valuex : ufixed (hbv downto lbv); variable igood : BOOLEAN; variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits variable i : INTEGER; begin VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" loop -- skip white space read(L, c, igood); exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; if igood = false then return; else Char2QuadBits(c, nybble, igood, false); i := hbv-lbv - 4; -- Top - 4 slv (hbv-lbv downto i+1) := nybble; end if; while (i /= -1) and igood and L.all'length /= 0 loop read (L, c, igood); if igood then if (c = '.') then igood := igood and (i + 1 = -lbv); else Char2QuadBits(c, nybble, igood, false); slv (i downto i-3) := nybble; i := i - 4; end if; end if; end loop; good := igood and -- We did not get another error (i = -1) and -- We read everything, and high bits 0 (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0'); valuex := to_ufixed (slv, hbv, lbv); VALUE := valuex (VALUE'range); end procedure HREAD; procedure HREAD(L : inout LINE; VALUE : out sfixed) is constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits variable c : CHARACTER; -- to read the "." variable valuex : sfixed (hbv downto lbv); variable igood : BOOLEAN; variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits variable i : INTEGER; begin VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" loop -- skip white space read(L, c, igood); exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; if igood = false then report "FIXED_GENERIC_PKG.HREAD(sfixed): " & "Error end of string encountered" severity error; return; else Char2QuadBits(c, nybble, igood, true); i := hbv-lbv - 4; -- Top - 4 slv (hbv-lbv downto i+1) := nybble; end if; while (i /= -1) and igood and L.all'length /= 0 loop read (L, c, igood); if igood = false then report "FIXED_GENERIC_PKG.HREAD(sfixed): " & "Error end of string encountered" severity error; elsif (c = '.') then if (i + 1 /= -lbv) then igood := false; report "FIXED_GENERIC_PKG.HREAD(sfixed): " & "encountered ""."" at wrong index" severity error; end if; else Char2QuadBits(c, nybble, igood, true); slv (i downto i-3) := nybble; i := i - 4; end if; end loop; if igood then -- We did not get another error assert (i = -1) -- We read everything and ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or (slv(VALUE'high-lbv) = '1' and and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')) report "FIXED_GENERIC_PKG.HREAD(sfixed): Vector truncated." severity error; if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then assert NO_WARNING report "FIXED_GENERIC_PKG.HREAD(sfixed): Vector truncated" severity warning; end if; end if; valuex := to_sfixed (slv, hbv, lbv); VALUE := valuex (VALUE'range); end procedure HREAD; procedure HREAD(L : inout LINE; VALUE : out sfixed; GOOD : out BOOLEAN) is constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits variable c : CHARACTER; -- to read the "." variable valuex : sfixed (hbv downto lbv); variable igood : BOOLEAN; variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits variable i : INTEGER; begin VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" loop -- skip white space read(L, c, igood); exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); end loop; if igood = false then return; else Char2QuadBits(c, nybble, igood, false); i := hbv-lbv - 4; -- Top - 4 slv (hbv-lbv downto i+1) := nybble; end if; while (i /= -1) and igood and L.all'length /= 0 loop read (L, c, igood); if igood then if (c = '.') then igood := igood and (i + 1 = -lbv); else Char2QuadBits(c, nybble, igood, false); slv (i downto i-3) := nybble; i := i - 4; end if; end if; end loop; good := igood and -- We did not get another error (i = -1) and -- We read everything ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or (slv(VALUE'high-lbv) = '1' and and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')); valuex := to_sfixed (slv, hbv, lbv); VALUE := valuex (VALUE'range); end procedure HREAD; ----------------------------------------------------------------------------- -- %%% Remove the following 3 functions. They are a duplicate needed for -- testing ----------------------------------------------------------------------------- -- purpose: Justify a string to the right function justify ( value : STRING; justified : SIDE := right; field : width := 0) return STRING is constant VAL_LEN : INTEGER := value'length; variable result : STRING (1 to field) := (others => ' '); begin -- function justify -- return value if field is too small if VAL_LEN >= field then return value; end if; if justified = left then result(1 to VAL_LEN) := value; elsif justified = right then result(field - VAL_LEN + 1 to field) := value; end if; return result; end function justify; function to_ostring ( value : STD_LOGIC_VECTOR; justified : SIDE := right; field : width := 0 ) return STRING is constant ne : INTEGER := (value'length+2)/3; variable pad : STD_LOGIC_VECTOR(0 to (ne*3 - value'length) - 1); variable ivalue : STD_LOGIC_VECTOR(0 to ne*3 - 1); variable result : STRING(1 to ne); variable tri : STD_LOGIC_VECTOR(0 to 2); begin if value'length < 1 then return NUS; else if value (value'left) = 'Z' then pad := (others => 'Z'); else pad := (others => '0'); end if; ivalue := pad & value; for i in 0 to ne-1 loop tri := To_X01Z(ivalue(3*i to 3*i+2)); case tri is when o"0" => result(i+1) := '0'; when o"1" => result(i+1) := '1'; when o"2" => result(i+1) := '2'; when o"3" => result(i+1) := '3'; when o"4" => result(i+1) := '4'; when o"5" => result(i+1) := '5'; when o"6" => result(i+1) := '6'; when o"7" => result(i+1) := '7'; when "ZZZ" => result(i+1) := 'Z'; when others => result(i+1) := 'X'; end case; end loop; return justify(result, justified, field); end if; end function to_ostring; ------------------------------------------------------------------- function to_hstring ( value : STD_LOGIC_VECTOR; justified : SIDE := right; field : width := 0 ) return STRING is constant ne : INTEGER := (value'length+3)/4; variable pad : STD_LOGIC_VECTOR(0 to (ne*4 - value'length) - 1); variable ivalue : STD_LOGIC_VECTOR(0 to ne*4 - 1); variable result : STRING(1 to ne); variable quad : STD_LOGIC_VECTOR(0 to 3); begin if value'length < 1 then return NUS; else if value (value'left) = 'Z' then pad := (others => 'Z'); else pad := (others => '0'); end if; ivalue := pad & value; for i in 0 to ne-1 loop quad := To_X01Z(ivalue(4*i to 4*i+3)); case quad is when x"0" => result(i+1) := '0'; when x"1" => result(i+1) := '1'; when x"2" => result(i+1) := '2'; when x"3" => result(i+1) := '3'; when x"4" => result(i+1) := '4'; when x"5" => result(i+1) := '5'; when x"6" => result(i+1) := '6'; when x"7" => result(i+1) := '7'; when x"8" => result(i+1) := '8'; when x"9" => result(i+1) := '9'; when x"A" => result(i+1) := 'A'; when x"B" => result(i+1) := 'B'; when x"C" => result(i+1) := 'C'; when x"D" => result(i+1) := 'D'; when x"E" => result(i+1) := 'E'; when x"F" => result(i+1) := 'F'; when "ZZZZ" => result(i+1) := 'Z'; when others => result(i+1) := 'X'; end case; end loop; return justify(result, justified, field); end if; end function to_hstring; -- %%% End remove here function to_string ( value : ufixed; justified : SIDE := right; field : width := 0 ) return STRING is variable s : STRING(1 to value'length +1) := (others => ' '); variable sindx : INTEGER; begin if value'length < 1 then return NUS; else if value'high < 0 then return to_string (resize (value, 0, value'low), justified, field); elsif value'low > 0 then return to_string (resize (value, value'high, -1), justified, field); else sindx := 1; for i in value'high downto value'low loop if i = -1 then s(sindx) := '.'; sindx := sindx +1; end if; s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); sindx := sindx +1; end loop; return justify(s, justified, field); end if; end if; end function to_string; function to_string ( value : sfixed; justified : SIDE := right; field : width := 0 ) return STRING is variable s : STRING(1 to value'length +1) := (others => ' '); variable sindx : INTEGER; begin if value'length < 1 then return NUS; else if value'high < 0 then return to_string (resize (value, 0, value'low), justified, field); elsif value'low > 0 then return to_string (resize (value, value'high, -1), justified, field); else sindx := 1; for i in value'high downto value'low loop if i = -1 then s(sindx) := '.'; sindx := sindx +1; end if; s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); sindx := sindx +1; end loop; return justify(s, justified, field); end if; end if; end function to_string; function to_ostring ( value : ufixed; justified : SIDE := right; field : width := 0 ) return STRING is constant lne : INTEGER := (-VALUE'low+2)/3; constant lpad : STD_LOGIC_VECTOR (0 to (lne*3 + VALUE'low) -1) := (others => '0'); variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); begin if value'length < 1 then return NUS; else if value'high < 0 then return to_ostring (resize (value, 2, value'low), justified, field); elsif value'low > 0 then return to_ostring (resize (value, value'high, -3), justified, field); else slv := to_slv (value); return justify(to_ostring(slv(slv'high downto slv'high-VALUE'high)) & "." & to_ostring(slv(slv'high-VALUE'high-1 downto 0)&lpad), justified, field); end if; end if; end function to_ostring; function to_hstring ( value : ufixed; justified : SIDE := right; field : width := 0 ) return STRING is constant lne : INTEGER := (-VALUE'low+3)/4; constant lpad : STD_LOGIC_VECTOR (0 to (lne*4 + VALUE'low) -1) := (others => '0'); variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); begin if value'length < 1 then return NUS; else if value'high < 0 then return to_hstring (resize (value, 3, value'low), justified, field); elsif value'low > 0 then return to_hstring (resize (value, value'high, -4), justified, field); else slv := to_slv (value); return justify(to_hstring(slv(slv'high downto slv'high-VALUE'high)) & "." & to_hstring(slv(slv'high-VALUE'high-1 downto 0)&lpad), justified, field); end if; end if; end function to_hstring; function to_ostring ( value : sfixed; justified : SIDE := right; field : width := 0 ) return STRING is constant ne : INTEGER := ((value'high+1)+2)/3; variable pad : STD_LOGIC_VECTOR(0 to (ne*3 - (value'high+1)) - 1); constant lne : INTEGER := (-VALUE'low+2)/3; constant lpad : STD_LOGIC_VECTOR (0 to (lne*3 + VALUE'low) -1) := (others => '0'); variable slv : STD_LOGIC_VECTOR (VALUE'high - VALUE'low downto 0); begin if value'length < 1 then return NUS; else pad := (others => value(value'high)); if value'high < 0 then return to_ostring (resize (value, 2, value'low), justified, field); elsif value'low > 0 then return to_ostring (resize (value, value'high, -3), justified, field); else slv := to_slv (value); return justify(to_ostring(pad & slv(slv'high downto slv'high-VALUE'high)) & "." & to_ostring(slv(slv'high-VALUE'high-1 downto 0) & lpad), justified, field); end if; end if; end function to_ostring; function to_hstring ( value : sfixed; justified : SIDE := right; field : width := 0 ) return STRING is constant ne : INTEGER := ((value'high+1)+3)/4; variable pad : STD_LOGIC_VECTOR(0 to (ne*4 - (value'high+1)) - 1); constant lne : INTEGER := (-VALUE'low+3)/4; constant lpad : STD_LOGIC_VECTOR (0 to (lne*4 + VALUE'low) -1) := (others => '0'); variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); begin if value'length < 1 then return NUS; else pad := (others => value(value'high)); if value'high < 0 then return to_hstring (resize (value, 3, value'low), justified, field); elsif value'low > 0 then return to_hstring (resize (value, value'high, -4), justified, field); else slv := to_slv (value); return justify(to_hstring(pad&slv(slv'high downto slv'high-VALUE'high)) & "." & to_hstring(slv(slv'high-VALUE'high-1 downto 0)&lpad), justified, field); end if; end if; end function to_hstring; -- 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 ufixed is variable result : ufixed (left_index downto right_index); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(bstring); read (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; return result; end function from_string; -- 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 ufixed is variable result : ufixed (left_index downto right_index); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(ostring); oread (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; return result; end function from_ostring; function from_hstring ( hstring : STRING; -- hex string constant left_index : INTEGER; constant right_index : INTEGER) return ufixed is variable result : ufixed (left_index downto right_index); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(hstring); hread (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; return result; end function from_hstring; function from_string ( bstring : STRING; -- binary string constant left_index : INTEGER; constant right_index : INTEGER) return sfixed is variable result : sfixed (left_index downto right_index); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(bstring); read (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; return result; end function from_string; function from_ostring ( ostring : STRING; -- Octal string constant left_index : INTEGER; constant right_index : INTEGER) return sfixed is variable result : sfixed (left_index downto right_index); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(ostring); oread (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; return result; end function from_ostring; function from_hstring ( hstring : STRING; -- hex string constant left_index : INTEGER; constant right_index : INTEGER) return sfixed is variable result : sfixed (left_index downto right_index); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(hstring); hread (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; return result; end function from_hstring; -- Same as above, "size_res" is used for it's range only. function from_string ( bstring : STRING; -- binary string size_res : ufixed) return ufixed is variable result : ufixed (size_res'high downto size_res'low); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(bstring); read (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; return result; end function from_string; function from_ostring ( ostring : STRING; -- Octal string size_res : ufixed) return ufixed is variable result : ufixed (size_res'high downto size_res'low); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(ostring); oread (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; return result; end function from_ostring; function from_hstring ( hstring : STRING; -- hex string size_res : ufixed) return ufixed is variable result : ufixed (size_res'high downto size_res'low); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(hstring); hread (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; return result; end function from_hstring; function from_string ( bstring : STRING; -- binary string size_res : sfixed) return sfixed is variable result : sfixed (size_res'high downto size_res'low); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(bstring); read (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; return result; end function from_string; function from_ostring ( ostring : STRING; -- Octal string size_res : sfixed) return sfixed is variable result : sfixed (size_res'high downto size_res'low); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(ostring); oread (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; return result; end function from_ostring; function from_hstring ( hstring : STRING; -- hex string size_res : sfixed) return sfixed is variable result : sfixed (size_res'high downto size_res'low); variable L : LINE; variable good : BOOLEAN; begin L := new STRING'(hstring); hread (L, result, good); deallocate (L); assert (good) report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; return result; end function from_hstring; -- purpose: find a dot in a string, return -1 if no dot (internal function) function finddot ( arg : STRING) return INTEGER is alias xarg : STRING (arg'length downto 1) is arg; -- make it a downto begin for i in xarg'reverse_range loop if (xarg(i) = '.') then return i-1; end if; end loop; return -1; end function finddot; -- Direct converstion 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 ufixed is variable result : ufixed (bstring'length-2 downto 0); variable result_nodot : ufixed (bstring'length-1 downto 0); variable bstring_nodot : STRING (1 to bstring'length-1); variable L : LINE; variable good : BOOLEAN; variable dot, i, j : INTEGER; begin dot := finddot(bstring); if (dot = -1) then L := new STRING'(bstring); read (L, result_nodot, good); assert (good) report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; deallocate (L); return result_nodot; else j := 1; for i in 1 to bstring'high loop if (bstring(i) /= '.') then bstring_nodot(j) := bstring(i); -- get rid of the dot. j := j + 1; end if; end loop; L := new STRING'(bstring_nodot); read (L, result, good); assert (good) report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; deallocate (L); return to_ufixed(to_slv(result), bstring'length-dot-2, -dot); end if; end function from_string; -- Direct octal and hex converstion 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 ufixed is variable result : STD_LOGIC_VECTOR((ostring'length-1)*3-1 downto 0); variable result_nodot : STD_LOGIC_VECTOR((ostring'length)*3-1 downto 0); variable ostring_nodot : STRING (1 to ostring'length-1); variable L : LINE; variable good : BOOLEAN; variable dot, i, j : INTEGER; begin dot := finddot(ostring); if (dot = -1) then L := new STRING'(ostring); oread (L, result_nodot, good); assert (good) report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; deallocate (L); return to_ufixed(UNSIGNED(result_nodot)); else j := 1; for i in 1 to ostring'high loop if (ostring(i) /= '.') then ostring_nodot(j) := ostring(i); -- get rid of the dot. j := j + 1; end if; end loop; L := new STRING'(ostring_nodot); oread (L, result, good); assert (good) report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; deallocate (L); return to_ufixed(result, (ostring'length-1-dot)*3-1, -dot*3); end if; end function from_ostring; function from_hstring ( hstring : STRING) -- hex string return ufixed is variable result : STD_LOGIC_VECTOR((hstring'length-1)*4-1 downto 0); variable result_nodot : STD_LOGIC_VECTOR((hstring'length)*4-1 downto 0); variable hstring_nodot : STRING (1 to hstring'length-1); variable L : LINE; variable good : BOOLEAN; variable dot, i, j : INTEGER; begin dot := finddot(hstring); if (dot = -1) then L := new STRING'(hstring); hread (L, result_nodot, good); assert (good) report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; deallocate (L); return to_ufixed(UNSIGNED(result_nodot)); else j := 1; for i in 1 to hstring'high loop if (hstring(i) /= '.') then hstring_nodot(j) := hstring(i); -- get rid of the dot. j := j + 1; end if; end loop; L := new STRING'(hstring_nodot); hread (L, result, good); assert (good) report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; deallocate (L); return to_ufixed(result, (hstring'length-1-dot)*4-1, -dot*4); end if; end function from_hstring; function from_string ( bstring : STRING) -- binary string return sfixed is variable result : sfixed (bstring'length-2 downto 0); variable result_nodot : sfixed (bstring'length-1 downto 0); variable bstring_nodot : STRING (1 to bstring'length-1); variable L : LINE; variable good : BOOLEAN; variable dot, i, j : INTEGER; begin dot := finddot(bstring); if (dot = -1) then L := new STRING'(bstring); read (L, result_nodot, good); assert (good) report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; deallocate (L); return result_nodot; else j := 1; for i in 1 to bstring'high loop if (bstring(i) /= '.') then bstring_nodot(j) := bstring(i); -- get rid of the dot. j := j + 1; end if; end loop; L := new STRING'(bstring_nodot); read (L, result, good); assert (good) report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; deallocate (L); return to_sfixed(to_slv(result), bstring'length-dot-2, -dot); end if; end function from_string; function from_ostring ( ostring : STRING) -- Octal string return sfixed is variable result : STD_LOGIC_VECTOR((ostring'length-1)*3-1 downto 0); variable result_nodot : STD_LOGIC_VECTOR((ostring'length)*3-1 downto 0); variable ostring_nodot : STRING (1 to ostring'length-1); variable L : LINE; variable good : BOOLEAN; variable dot, i, j : INTEGER; begin dot := finddot(ostring); if (dot = -1) then L := new STRING'(ostring); oread (L, result_nodot, good); assert (good) report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; deallocate (L); return to_sfixed(SIGNED(result_nodot)); else j := 1; for i in 1 to ostring'high loop if (ostring(i) /= '.') then ostring_nodot(j) := ostring(i); -- get rid of the dot. j := j + 1; end if; end loop; L := new STRING'(ostring_nodot); oread (L, result, good); assert (good) report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; deallocate (L); return to_sfixed(result, (ostring'length-1-dot)*3-1, -dot*3); end if; end function from_ostring; function from_hstring ( hstring : STRING) -- hex string return sfixed is variable result : STD_LOGIC_VECTOR((hstring'length-1)*4-1 downto 0); variable result_nodot : STD_LOGIC_VECTOR((hstring'length)*4-1 downto 0); variable hstring_nodot : STRING (1 to hstring'length-1); variable L : LINE; variable good : BOOLEAN; variable dot, i, j : INTEGER; begin dot := finddot(hstring); if (dot = -1) then L := new STRING'(hstring); hread (L, result_nodot, good); assert (good) report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; deallocate (L); return sfixed(SIGNED(result_nodot)); else j := 1; for i in 1 to hstring'high loop if (hstring(i) /= '.') then hstring_nodot(j) := hstring(i); -- get rid of the dot. j := j + 1; end if; end loop; L := new STRING'(hstring_nodot); hread (L, result, good); assert (good) report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; deallocate (L); return to_sfixed(result, (hstring'length-1-dot)*4-1, -dot*4); end if; end function from_hstring; -- synthesis translate_on -- rtl_synthesis on function to_StdLogicVector ( arg : ufixed) -- fp vector return STD_LOGIC_VECTOR is begin return to_slv (arg); end function to_StdLogicVector; function to_Std_Logic_Vector ( arg : ufixed) -- fp vector return STD_LOGIC_VECTOR is begin return to_slv (arg); end function to_Std_Logic_Vector; function to_StdLogicVector ( arg : sfixed) -- fp vector return STD_LOGIC_VECTOR is begin return to_slv (arg); end function to_StdLogicVector; function to_Std_Logic_Vector ( arg : sfixed) -- fp vector return STD_LOGIC_VECTOR is begin return to_slv (arg); end function to_Std_Logic_Vector; function to_StdULogicVector ( arg : ufixed) -- fp vector return STD_ULOGIC_VECTOR is begin return to_sulv (arg); end function to_StdULogicVector; function to_Std_ULogic_Vector ( arg : ufixed) -- fp vector return STD_ULOGIC_VECTOR is begin return to_sulv (arg); end function to_Std_ULogic_Vector; function to_StdULogicVector ( arg : sfixed) -- fp vector return STD_ULOGIC_VECTOR is begin return to_sulv (arg); end function to_StdULogicVector; function to_Std_ULogic_Vector ( arg : sfixed) -- fp vector return STD_ULOGIC_VECTOR is begin return to_sulv (arg); end function to_Std_ULogic_Vector; end package body fixed_pkg;