From 09b62e30ab072eafd4792104eb1f0971d1f96b5c Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Mon, 7 Nov 2011 15:03:51 +0100 Subject: initial commit --- ieee_proposed/doc/link.txt | 1 + ieee_proposed/rtl/env_c.vhd | 48 + ieee_proposed/rtl/fixed_float_types_c.vhd | 34 + ieee_proposed/rtl/fixed_pkg_c.vhd | 8390 +++++++++++++++++++++ ieee_proposed/rtl/float_pkg_c.vhd | 7190 ++++++++++++++++++ ieee_proposed/rtl/numeric_std_additions.vhd | 2886 +++++++ ieee_proposed/rtl/numeric_std_unsigned_c.vhd | 2207 ++++++ ieee_proposed/rtl/standard_additions_c.vhd | 2073 +++++ ieee_proposed/rtl/standard_textio_additions_c.vhd | 478 ++ ieee_proposed/rtl/std_logic_1164_additions.vhd | 1808 +++++ ieee_proposed/simulation/modelsim.ini | 3 + 11 files changed, 25118 insertions(+) create mode 100644 ieee_proposed/doc/link.txt create mode 100644 ieee_proposed/rtl/env_c.vhd create mode 100644 ieee_proposed/rtl/fixed_float_types_c.vhd create mode 100644 ieee_proposed/rtl/fixed_pkg_c.vhd create mode 100644 ieee_proposed/rtl/float_pkg_c.vhd create mode 100644 ieee_proposed/rtl/numeric_std_additions.vhd create mode 100644 ieee_proposed/rtl/numeric_std_unsigned_c.vhd create mode 100644 ieee_proposed/rtl/standard_additions_c.vhd create mode 100644 ieee_proposed/rtl/standard_textio_additions_c.vhd create mode 100644 ieee_proposed/rtl/std_logic_1164_additions.vhd create mode 100644 ieee_proposed/simulation/modelsim.ini diff --git a/ieee_proposed/doc/link.txt b/ieee_proposed/doc/link.txt new file mode 100644 index 0000000..a34854d --- /dev/null +++ b/ieee_proposed/doc/link.txt @@ -0,0 +1 @@ +http://www.eda-stds.org/fphdl/ diff --git a/ieee_proposed/rtl/env_c.vhd b/ieee_proposed/rtl/env_c.vhd new file mode 100644 index 0000000..e6703fa --- /dev/null +++ b/ieee_proposed/rtl/env_c.vhd @@ -0,0 +1,48 @@ +package ENV is + + procedure STOP (STATUS : INTEGER); + procedure FINISH (STATUS : INTEGER); + + function RESOLUTION_LIMIT return DELAY_LENGTH; + +end package ENV; +library ieee_proposed; +use ieee_proposed.standard_additions.all; +package body ENV is + + procedure STOP (STATUS : INTEGER) is + begin + report "Procedure STOP called with status: " & INTEGER'image(STATUS) + severity failure; + end procedure STOP; + procedure FINISH (STATUS : INTEGER) is + begin + report "Procedure FINISH called with status: " & INTEGER'image(STATUS) + severity failure; + end procedure FINISH; + + constant BASE_TIME_ARRAY : time_vector := + ( + 1 fs, 10 fs, 100 fs, + 1 ps, 10 ps, 100 ps, + 1 ns, 10 ns, 100 ns, + 1 us, 10 us, 100 us, + 1 ms, 10 ms, 100 ms, + 1 sec, 10 sec, 100 sec, + 1 min, 10 min, 100 min, + 1 hr, 10 hr, 100 hr + ) ; + + function RESOLUTION_LIMIT return DELAY_LENGTH is + begin + for i in BASE_TIME_ARRAY'range loop + if BASE_TIME_ARRAY(i) > 0 hr then + return BASE_TIME_ARRAY(i); + end if; + end loop; + report "STANDATD.RESOLUTION_LIMIT: Simulator resolution not less than 100 hr" + severity failure; + return 1 ns; + end function RESOLUTION_LIMIT; + +end package body ENV; diff --git a/ieee_proposed/rtl/fixed_float_types_c.vhd b/ieee_proposed/rtl/fixed_float_types_c.vhd new file mode 100644 index 0000000..315b628 --- /dev/null +++ b/ieee_proposed/rtl/fixed_float_types_c.vhd @@ -0,0 +1,34 @@ +-- -------------------------------------------------------------------- +-- "fixed_float_types" package contains types used in the fixed and floating +-- point packages.. +-- Please see the documentation for the floating point package. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- +-- This verison is designed to work with the VHDL-93 compilers. Please +-- note the "%%%" comments. These are where we diverge from the +-- VHDL-200X LRM. +-- +-- -------------------------------------------------------------------- +-- Version : $Revision: 1.21 $ +-- Date : $Date: 2007-09-11 14:52:13-04 $ +-- -------------------------------------------------------------------- + +package fixed_float_types is + + -- Types used for generics of fixed_generic_pkg + + type fixed_round_style_type is (fixed_round, fixed_truncate); + + type fixed_overflow_style_type is (fixed_saturate, fixed_wrap); + + -- Type used for generics of float_generic_pkg + + -- These are the same as the C FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, + -- and FE_TOWARDZERO floating point rounding macros. + + type round_type is (round_nearest, -- Default, nearest LSB '0' + round_inf, -- Round toward positive infinity + round_neginf, -- Round toward negative infinity + round_zero); -- Round toward zero (truncate) + +end package fixed_float_types; diff --git a/ieee_proposed/rtl/fixed_pkg_c.vhd b/ieee_proposed/rtl/fixed_pkg_c.vhd new file mode 100644 index 0000000..bb32709 --- /dev/null +++ b/ieee_proposed/rtl/fixed_pkg_c.vhd @@ -0,0 +1,8390 @@ +-- -------------------------------------------------------------------- +-- "fixed_pkg_c.vhdl" package contains functions for fixed point math. +-- Please see the documentation for the fixed point package. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee.std_logic_1164.all; +-- use ieee.numeric_std.all; +-- use ieee_proposed.fixed_float_types.all; +-- use ieee_proposed.fixed_pkg.all; +-- +-- This verison is designed to work with the VHDL-93 compilers +-- synthesis tools. Please note the "%%%" comments. These are where we +-- diverge from the VHDL-200X LRM. +-- -------------------------------------------------------------------- +-- Version : $Revision: 1.21 $ +-- Date : $Date: 2007/09/26 18:08:53 $ +-- -------------------------------------------------------------------- + +use STD.TEXTIO.all; +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.all; +library IEEE_PROPOSED; +use IEEE_PROPOSED.fixed_float_types.all; + +package fixed_pkg is +-- generic ( + -- Rounding routine to use in fixed point, fixed_round or fixed_truncate + constant fixed_round_style : fixed_round_style_type := fixed_round; + -- Overflow routine to use in fixed point, fixed_saturate or fixed_wrap + constant fixed_overflow_style : fixed_overflow_style_type := fixed_saturate; + -- Extra bits used in divide routines + constant fixed_guard_bits : NATURAL := 3; + -- If TRUE, then turn off warnings on "X" propagation + constant no_warning : BOOLEAN := (false + ); + + -- Author David Bishop (dbishop@vhdl.org) + + -- base Unsigned fixed point type, downto direction assumed + type UNRESOLVED_ufixed is array (INTEGER range <>) of STD_ULOGIC; + -- base Signed fixed point type, downto direction assumed + type UNRESOLVED_sfixed is array (INTEGER range <>) of STD_ULOGIC; + + subtype U_ufixed is UNRESOLVED_ufixed; + subtype U_sfixed is UNRESOLVED_sfixed; + + subtype ufixed is UNRESOLVED_ufixed; + subtype sfixed is UNRESOLVED_sfixed; + + --=========================================================================== + -- Arithmetic Operators: + --=========================================================================== + + -- Absolute value, 2's complement + -- abs sfixed(a downto b) = sfixed(a+1 downto b) + function "abs" (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Negation, 2's complement + -- - sfixed(a downto b) = sfixed(a+1 downto b) + function "-" (arg : UNRESOLVED_sfixed)return UNRESOLVED_sfixed; + + -- Addition + -- ufixed(a downto b) + ufixed(c downto d) + -- = ufixed(maximum(a,c)+1 downto minimum(b,d)) + function "+" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed(a downto b) + sfixed(c downto d) + -- = sfixed(maximum(a,c)+1 downto minimum(b,d)) + function "+" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Subtraction + -- ufixed(a downto b) - ufixed(c downto d) + -- = ufixed(maximum(a,c)+1 downto minimum(b,d)) + function "-" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed(a downto b) - sfixed(c downto d) + -- = sfixed(maximum(a,c)+1 downto minimum(b,d)) + function "-" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Multiplication + -- ufixed(a downto b) * ufixed(c downto d) = ufixed(a+c+1 downto b+d) + function "*" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed(a downto b) * sfixed(c downto d) = sfixed(a+c+1 downto b+d) + function "*" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Division + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) +-- function "/" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) +-- function "/" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Remainder + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (minimum(a,c) downto minimum(b,d)) +-- function "rem" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (minimum(a,c) downto minimum(b,d)) +-- function "rem" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Modulo + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (minimum(a,c) downto minimum(b, d)) +-- function "mod" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto minimum(b, d)) +-- function "mod" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + ---------------------------------------------------------------------------- + -- In these routines the "real" or "natural" (integer) + -- are converted into a fixed point number and then the operation is + -- performed. It is assumed that the array will be large enough. + -- If the input is "real" then the real number is converted into a fixed of + -- the same size as the fixed point input. If the number is an "integer" + -- then it is converted into fixed with the range (l'high downto 0). + ---------------------------------------------------------------------------- + + -- ufixed(a downto b) + ufixed(a downto b) = ufixed(a+1 downto b) + function "+" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + + -- ufixed(c downto d) + ufixed(c downto d) = ufixed(c+1 downto d) + function "+" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) + ufixed(a downto 0) = ufixed(a+1 downto minimum(0,b)) + function "+" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + + -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto minimum(0,d)) + function "+" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) - ufixed(a downto b) = ufixed(a+1 downto b) + function "-" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + + -- ufixed(c downto d) - ufixed(c downto d) = ufixed(c+1 downto d) + function "-" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) - ufixed(a downto 0) = ufixed(a+1 downto minimum(0,b)) + function "-" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + + -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto minimum(0,d)) + function "-" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) * ufixed(a downto b) = ufixed(2a+1 downto 2b) + function "*" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + + -- ufixed(c downto d) * ufixed(c downto d) = ufixed(2c+1 downto 2d) + function "*" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) + function "*" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + + -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) + function "*" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) +-- function "/" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + +-- -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) +-- function "/" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) / ufixed(a downto 0) = ufixed(a downto b-a-1) +-- function "/" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + + -- ufixed(c downto 0) / ufixed(c downto d) = ufixed(c-d downto -c-1) +-- function "/" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed (a downto b) rem ufixed (a downto b) = ufixed (a downto b) +-- function "rem" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + +-- -- ufixed (c downto d) rem ufixed (c downto d) = ufixed (c downto d) +-- function "rem" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + +-- -- ufixed (a downto b) rem ufixed (a downto 0) = ufixed (a downto minimum(b,0)) +-- function "rem" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + +-- -- ufixed (c downto 0) rem ufixed (c downto d) = ufixed (c downto minimum(d,0)) +-- function "rem" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + +-- -- ufixed (a downto b) mod ufixed (a downto b) = ufixed (a downto b) +-- function "mod" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + +-- -- ufixed (c downto d) mod ufixed (c downto d) = ufixed (c downto d) +-- function "mod" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + +-- -- ufixed (a downto b) mod ufixed (a downto 0) = ufixed (a downto minimum(b,0)) +-- function "mod" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + +-- -- ufixed (c downto 0) mod ufixed (c downto d) = ufixed (c downto minimum(d,0)) +-- function "mod" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed(a downto b) + sfixed(a downto b) = sfixed(a+1 downto b) + function "+" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + + -- sfixed(c downto d) + sfixed(c downto d) = sfixed(c+1 downto d) + function "+" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) + sfixed(a downto 0) = sfixed(a+1 downto minimum(0,b)) + function "+" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + + -- sfixed(c downto 0) + sfixed(c downto d) = sfixed(c+1 downto minimum(0,d)) + function "+" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) - sfixed(a downto b) = sfixed(a+1 downto b) + function "-" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + + -- sfixed(c downto d) - sfixed(c downto d) = sfixed(c+1 downto d) + function "-" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) - sfixed(a downto 0) = sfixed(a+1 downto minimum(0,b)) + function "-" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + + -- sfixed(c downto 0) - sfixed(c downto d) = sfixed(c+1 downto minimum(0,d)) + function "-" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) * sfixed(a downto b) = sfixed(2a+1 downto 2b) + function "*" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + + -- sfixed(c downto d) * sfixed(c downto d) = sfixed(2c+1 downto 2d) + function "*" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) * sfixed(a downto 0) = sfixed(2a+1 downto b) + function "*" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + + -- sfixed(c downto 0) * sfixed(c downto d) = sfixed(2c+1 downto d) + function "*" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) / sfixed(a downto b) = sfixed(a-b+1 downto b-a) +-- function "/" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + + -- sfixed(c downto d) / sfixed(c downto d) = sfixed(c-d+1 downto d-c) +-- function "/" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) / sfixed(a downto 0) = sfixed(a+1 downto b-a) +-- function "/" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + + -- sfixed(c downto 0) / sfixed(c downto d) = sfixed(c-d+1 downto -c) +-- function "/" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed (a downto b) rem sfixed (a downto b) = sfixed (a downto b) +-- function "rem" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + +-- -- sfixed (c downto d) rem sfixed (c downto d) = sfixed (c downto d) +-- function "rem" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + +-- -- sfixed (a downto b) rem sfixed (a downto 0) = sfixed (a downto minimum(b,0)) +-- function "rem" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + +-- -- sfixed (c downto 0) rem sfixed (c downto d) = sfixed (c downto minimum(d,0)) +-- function "rem" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + +-- -- sfixed (a downto b) mod sfixed (a downto b) = sfixed (a downto b) +-- function "mod" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + +-- -- sfixed (c downto d) mod sfixed (c downto d) = sfixed (c downto d) +-- function "mod" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + +-- -- sfixed (a downto b) mod sfixed (a downto 0) = sfixed (a downto minimum(b,0)) +-- function "mod" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + +-- -- sfixed (c downto 0) mod sfixed (c downto d) = sfixed (c downto minimum(d,0)) +-- function "mod" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- This version of divide gives the user more control + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) +-- function divide ( +-- l, r : UNRESOLVED_ufixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed; + + -- This version of divide gives the user more control + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) +-- function divide ( +-- l, r : UNRESOLVED_sfixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed; + + -- These functions return 1/X + -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) +-- function reciprocal ( +-- arg : UNRESOLVED_ufixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed; + + -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) +-- function reciprocal ( +-- arg : UNRESOLVED_sfixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed; + + -- REM function + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (minimum(a,c) downto minimum(b,d)) +-- function remainder ( +-- l, r : UNRESOLVED_ufixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed; + + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (minimum(a,c) downto minimum(b,d)) +-- function remainder ( +-- l, r : UNRESOLVED_sfixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed; + + -- mod function + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (minimum(a,c) downto minimum(b, d)) +-- function modulo ( +-- l, r : UNRESOLVED_ufixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto minimum(b, d)) +-- function modulo ( +-- l, r : UNRESOLVED_sfixed; +-- constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed; + + -- Procedure for those who need an "accumulator" function. + -- add_carry (ufixed(a downto b), ufixed (c downto d)) + -- = ufixed (maximum(a,c) downto minimum(b,d)) + procedure add_carry ( + L, R : in UNRESOLVED_ufixed; + c_in : in STD_ULOGIC; + result : out UNRESOLVED_ufixed; + c_out : out STD_ULOGIC); + + -- add_carry (sfixed(a downto b), sfixed (c downto d)) + -- = sfixed (maximum(a,c) downto minimum(b,d)) + procedure add_carry ( + L, R : in UNRESOLVED_sfixed; + c_in : in STD_ULOGIC; + result : out UNRESOLVED_sfixed; + c_out : out STD_ULOGIC); + + -- Scales the result by a power of 2. Width of input = width of output with + -- the binary point moved. + function scalb (y : UNRESOLVED_ufixed; N : INTEGER) return UNRESOLVED_ufixed; + function scalb (y : UNRESOLVED_ufixed; N : SIGNED) return UNRESOLVED_ufixed; + function scalb (y : UNRESOLVED_sfixed; N : INTEGER) return UNRESOLVED_sfixed; + function scalb (y : UNRESOLVED_sfixed; N : SIGNED) return UNRESOLVED_sfixed; + + function Is_Negative (arg : UNRESOLVED_sfixed) return BOOLEAN; + + --=========================================================================== + -- Comparison Operators + --=========================================================================== + + function ">" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function ">" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + function "<" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function "<" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + function "<=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function "<=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + function ">=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function ">=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + function "=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function "=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + function "/=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function "/=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + + function \?=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?/=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?/=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + + function std_match (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function std_match (l, r : UNRESOLVED_sfixed) return BOOLEAN; + + -- Overloads the default "maximum" and "minimum" function + + function maximum (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function minimum (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function maximum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function minimum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + ---------------------------------------------------------------------------- + -- In these compare functions a natural is converted into a + -- fixed point number of the bounds "maximum(l'high,0) downto 0" + ---------------------------------------------------------------------------- + + function "=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + function "/=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + function ">=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + function "<=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + function ">" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + function "<" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + + function "=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "/=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function ">=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "<=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function ">" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "<" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + + function \?=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + function \?/=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + function \?>=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + function \?<=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + function \?>\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + function \?<\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + + function \?=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?/=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + + function maximum (l : UNRESOLVED_ufixed; r : NATURAL) + return UNRESOLVED_ufixed; + function minimum (l : UNRESOLVED_ufixed; r : NATURAL) + return UNRESOLVED_ufixed; + function maximum (l : NATURAL; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function minimum (l : NATURAL; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + ---------------------------------------------------------------------------- + -- In these compare functions a real is converted into a + -- fixed point number of the bounds "l'high+1 downto l'low" + ---------------------------------------------------------------------------- + + function "=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + function "/=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + function ">=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + function "<=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + function ">" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + function "<" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + + function "=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "/=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function ">=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "<=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function ">" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "<" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + + function \?=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + function \?/=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + function \?>=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + function \?<=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + function \?>\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + function \?<\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + + function \?=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?/=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + + function maximum (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + function maximum (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function minimum (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + function minimum (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + ---------------------------------------------------------------------------- + -- In these compare functions an integer is converted into a + -- fixed point number of the bounds "maximum(l'high,1) downto 0" + ---------------------------------------------------------------------------- + + function "=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + function "/=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + function ">=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + function "<=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + function ">" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + function "<" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + + function "=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + function "/=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + function ">=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + function "<=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + function ">" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + function "<" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + + function \?=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + function \?/=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + function \?>=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + function \?<=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + function \?>\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + function \?<\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + + function \?=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?/=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + + function maximum (l : UNRESOLVED_sfixed; r : INTEGER) + return UNRESOLVED_sfixed; + function maximum (l : INTEGER; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function minimum (l : UNRESOLVED_sfixed; r : INTEGER) + return UNRESOLVED_sfixed; + function minimum (l : INTEGER; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + ---------------------------------------------------------------------------- + -- In these compare functions a real is converted into a + -- fixed point number of the bounds "l'high+1 downto l'low" + ---------------------------------------------------------------------------- + + function "=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + function "/=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + function ">=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + function "<=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + function ">" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + function "<" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + + function "=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + function "/=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + function ">=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + function "<=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + function ">" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + function "<" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + + function \?=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + function \?/=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + function \?>=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + function \?<=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + function \?>\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + function \?<\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + + function \?=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?/=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + + function maximum (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + function maximum (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function minimum (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + function minimum (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + --=========================================================================== + -- Shift and Rotate Functions. + -- Note that sra and sla are not the same as the BIT_VECTOR version + --=========================================================================== + + function "sll" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "srl" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "rol" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "ror" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "sla" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "sra" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "sll" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function "srl" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function "rol" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function "ror" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function "sla" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function "sra" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function SHIFT_LEFT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) + return UNRESOLVED_ufixed; + function SHIFT_RIGHT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) + return UNRESOLVED_ufixed; + function SHIFT_LEFT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) + return UNRESOLVED_sfixed; + function SHIFT_RIGHT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) + return UNRESOLVED_sfixed; + + ---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + + function "not" (l : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "and" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "or" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "nand" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "nor" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "xor" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "xnor" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "not" (l : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "and" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "or" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "nand" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "nor" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "xor" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "xnor" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Vector and std_ulogic functions, same as functions in numeric_std + function "and" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "and" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "or" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "or" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "nand" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "nand" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "nor" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "nor" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "xor" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "xor" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "xnor" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "xnor" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "and" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "and" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + function "or" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "or" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + function "nand" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "nand" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + function "nor" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "nor" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + function "xor" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "xor" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + function "xnor" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "xnor" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + + -- Reduction operators, same as numeric_std functions + function and_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function nand_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function or_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function nor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function xor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function xnor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function and_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + function nand_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + function or_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + function nor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + function xor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + function xnor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + + -- returns arg'low-1 if not found + function find_leftmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) + return INTEGER; + function find_leftmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) + return INTEGER; + + -- returns arg'high+1 if not found + function find_rightmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) + return INTEGER; + function find_rightmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) + return INTEGER; + + --=========================================================================== + -- RESIZE Functions + --=========================================================================== + -- resizes the number (larger or smaller) + -- The returned result will be ufixed (left_index downto right_index) + -- If "round_style" is fixed_round, then the result will be rounded. + -- If the MSB of the remainder is a "1" AND the LSB of the unrounded result + -- is a '1' or the lower bits of the remainder include a '1' then the result + -- will be increased by the smallest representable number for that type. + -- "overflow_style" can be fixed_saturate or fixed_wrap. + -- In saturate mode, if the number overflows then the largest possible + -- representable number is returned. If wrap mode, then the upper bits + -- of the number are truncated. + + function resize ( + arg : UNRESOLVED_ufixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + -- "size_res" functions create the size of the output from the indices + -- of the "size_res" input. The actual value of "size_res" is not used. + function resize ( + arg : UNRESOLVED_ufixed; -- input + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + -- Note that in "wrap" mode the sign bit is not replicated. Thus the + -- resize of a negative number can have a positive result in wrap mode. + function resize ( + arg : UNRESOLVED_sfixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + function resize ( + arg : UNRESOLVED_sfixed; -- input + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + --=========================================================================== + -- Conversion Functions + --=========================================================================== + + -- integer (natural) to unsigned fixed point. + -- arguments are the upper and lower bounds of the number, thus + -- ufixed (7 downto -3) <= to_ufixed (int, 7, -3); + function to_ufixed ( + arg : NATURAL; -- integer + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + function to_ufixed ( + arg : NATURAL; -- integer + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + -- real to unsigned fixed point + function to_ufixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return UNRESOLVED_ufixed; + + function to_ufixed ( + arg : REAL; -- real + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return UNRESOLVED_ufixed; + + -- unsigned to unsigned fixed point + function to_ufixed ( + arg : UNSIGNED; -- unsigned + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + function to_ufixed ( + arg : UNSIGNED; -- unsigned + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + -- Performs a conversion. ufixed (arg'range) is returned + function to_ufixed ( + arg : UNSIGNED) -- unsigned + return UNRESOLVED_ufixed; + + -- unsigned fixed point to unsigned + function to_unsigned ( + arg : UNRESOLVED_ufixed; -- fixed point input + constant size : NATURAL; -- length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNSIGNED; + + -- unsigned fixed point to unsigned + function to_unsigned ( + arg : UNRESOLVED_ufixed; -- fixed point input + size_res : UNSIGNED; -- used for length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNSIGNED; + + -- unsigned fixed point to real + function to_real ( + arg : UNRESOLVED_ufixed) -- fixed point input + return REAL; + + -- unsigned fixed point to integer + function to_integer ( + arg : UNRESOLVED_ufixed; -- fixed point input + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return NATURAL; + + -- Integer to UNRESOLVED_sfixed + function to_sfixed ( + arg : INTEGER; -- integer + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + function to_sfixed ( + arg : INTEGER; -- integer + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + -- Real to sfixed + function to_sfixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return UNRESOLVED_sfixed; + + function to_sfixed ( + arg : REAL; -- real + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return UNRESOLVED_sfixed; + + -- signed to sfixed + function to_sfixed ( + arg : SIGNED; -- signed + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + function to_sfixed ( + arg : SIGNED; -- signed + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + -- signed to sfixed (output assumed to be size of signed input) + function to_sfixed ( + arg : SIGNED) -- signed + return UNRESOLVED_sfixed; + + -- Conversion from ufixed to sfixed + function to_sfixed ( + arg : UNRESOLVED_ufixed) + return UNRESOLVED_sfixed; + + -- signed fixed point to signed + function to_signed ( + arg : UNRESOLVED_sfixed; -- fixed point input + constant size : NATURAL; -- length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return SIGNED; + + -- signed fixed point to signed + function to_signed ( + arg : UNRESOLVED_sfixed; -- fixed point input + size_res : SIGNED; -- used for length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return SIGNED; + + -- signed fixed point to real + function to_real ( + arg : UNRESOLVED_sfixed) -- fixed point input + return REAL; + + -- signed fixed point to integer + function to_integer ( + arg : UNRESOLVED_sfixed; -- fixed point input + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return INTEGER; + + -- Because of the fairly complicated sizing rules in the fixed point + -- packages these functions are provided to compute the result ranges + -- Example: + -- signal uf1 : ufixed (3 downto -3); + -- signal uf2 : ufixed (4 downto -2); + -- signal uf1multuf2 : ufixed (ufixed_high (3, -3, '*', 4, -2) downto + -- ufixed_low (3, -3, '*', 4, -2)); + -- uf1multuf2 <= uf1 * uf2; + -- Valid characters: '+', '-', '*', '/', 'r' or 'R' (rem), 'm' or 'M' (mod), + -- '1' (reciprocal), 'a' or 'A' (abs), 'n' or 'N' (unary -) + function ufixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + + function ufixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + + function sfixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + + function sfixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + + -- Same as above, but using the "size_res" input only for their ranges: + -- signal uf1multuf2 : ufixed (ufixed_high (uf1, '*', uf2) downto + -- ufixed_low (uf1, '*', uf2)); + -- uf1multuf2 <= uf1 * uf2; + -- + function ufixed_high (size_res : UNRESOLVED_ufixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_ufixed) + return INTEGER; + + function ufixed_low (size_res : UNRESOLVED_ufixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_ufixed) + return INTEGER; + + function sfixed_high (size_res : UNRESOLVED_sfixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_sfixed) + return INTEGER; + + function sfixed_low (size_res : UNRESOLVED_sfixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_sfixed) + return INTEGER; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + + function saturate ( + size_res : UNRESOLVED_ufixed) -- only the size of this is used + return UNRESOLVED_ufixed; + + function saturate ( + size_res : UNRESOLVED_sfixed) -- only the size of this is used + return UNRESOLVED_sfixed; + + --=========================================================================== + -- Translation Functions + --=========================================================================== + + -- maps meta-logical values + function to_01 ( + s : UNRESOLVED_ufixed; -- fixed point input + constant XMAP : STD_ULOGIC := '0') -- Map x to + return UNRESOLVED_ufixed; + + -- maps meta-logical values + function to_01 ( + s : UNRESOLVED_sfixed; -- fixed point input + constant XMAP : STD_ULOGIC := '0') -- Map x to + return UNRESOLVED_sfixed; + + function Is_X (arg : UNRESOLVED_ufixed) return BOOLEAN; + function Is_X (arg : UNRESOLVED_sfixed) return BOOLEAN; + function to_X01 (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function to_X01 (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function to_X01Z (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function to_X01Z (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function to_UX01 (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function to_UX01 (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- straight vector conversion routines, needed for synthesis. + -- These functions are here so that a std_logic_vector can be + -- converted to and from sfixed and ufixed. Note that you can + -- not convert these vectors because of their negative index. + + function to_slv ( + arg : UNRESOLVED_ufixed) -- fixed point vector + return STD_LOGIC_VECTOR; +-- alias to_StdLogicVector is to_slv [UNRESOLVED_ufixed +-- return STD_LOGIC_VECTOR]; +-- alias to_Std_Logic_Vector is to_slv [UNRESOLVED_ufixed +-- return STD_LOGIC_VECTOR]; + + function to_slv ( + arg : UNRESOLVED_sfixed) -- fixed point vector + return STD_LOGIC_VECTOR; +-- alias to_StdLogicVector is to_slv [UNRESOLVED_sfixed +-- return STD_LOGIC_VECTOR]; +-- alias to_Std_Logic_Vector is to_slv [UNRESOLVED_sfixed +-- return STD_LOGIC_VECTOR]; + + function to_sulv ( + arg : UNRESOLVED_ufixed) -- fixed point vector + return STD_ULOGIC_VECTOR; +-- alias to_StdULogicVector is to_sulv [UNRESOLVED_ufixed +-- return STD_ULOGIC_VECTOR]; +-- alias to_Std_ULogic_Vector is to_sulv [UNRESOLVED_ufixed +-- return STD_ULOGIC_VECTOR]; + + function to_sulv ( + arg : UNRESOLVED_sfixed) -- fixed point vector + return STD_ULOGIC_VECTOR; +-- alias to_StdULogicVector is to_sulv [UNRESOLVED_sfixed +-- return STD_ULOGIC_VECTOR]; +-- alias to_Std_ULogic_Vector is to_sulv [UNRESOLVED_sfixed +-- return STD_ULOGIC_VECTOR]; + + function to_ufixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + + function to_ufixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_ufixed) -- for size only + return UNRESOLVED_ufixed; + + function to_sfixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + + function to_sfixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_sfixed) -- for size only + return UNRESOLVED_sfixed; + + -- As a concession to those who use a graphical DSP environment, + -- these functions take parameters in those tools format and create + -- fixed point numbers. These functions are designed to convert from + -- a std_logic_vector to the VHDL fixed point format using the conventions + -- of these packages. In a pure VHDL environment you should use the + -- "to_ufixed" and "to_sfixed" routines. + + -- unsigned fixed point + function to_UFix ( + arg : STD_ULOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_ufixed; + + -- signed fixed point + function to_SFix ( + arg : STD_ULOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_sfixed; + + -- finding the bounds of a number. These functions can be used like this: + -- signal xxx : ufixed (7 downto -3); + -- -- Which is the same as "ufixed (UFix_high (11,3) downto UFix_low(11,3))" + -- signal yyy : ufixed (UFix_high (11, 3, "+", 11, 3) + -- downto UFix_low(11, 3, "+", 11, 3)); + -- Where "11" is the width of xxx (xxx'length), + -- and 3 is the lower bound (abs (xxx'low)) + -- In a pure VHDL environment use "ufixed_high" and "ufixed_low" + + function UFix_high (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + + function UFix_low (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + + -- Same as above but for signed fixed point. Note that the width + -- of a signed fixed point number ignores the sign bit, thus + -- width = sxxx'length-1 + + function SFix_high (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + + function SFix_low (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; +-- rtl_synthesis off +-- pragma synthesis_off + --=========================================================================== + -- string and textio Functions + --=========================================================================== + + -- purpose: writes fixed point into a line + procedure WRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + -- purpose: writes fixed point into a line + procedure WRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_ufixed); + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN); + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_sfixed); + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN); + + alias bwrite is WRITE [LINE, UNRESOLVED_ufixed, SIDE, width]; + alias bwrite is WRITE [LINE, UNRESOLVED_sfixed, SIDE, width]; + alias bread is READ [LINE, UNRESOLVED_ufixed]; + alias bread is READ [LINE, UNRESOLVED_ufixed, BOOLEAN]; + alias bread is READ [LINE, UNRESOLVED_sfixed]; + alias bread is READ [LINE, UNRESOLVED_sfixed, BOOLEAN]; + alias BINARY_WRITE is WRITE [LINE, UNRESOLVED_ufixed, SIDE, width]; + alias BINARY_WRITE is WRITE [LINE, UNRESOLVED_sfixed, SIDE, width]; + alias BINARY_READ is READ [LINE, UNRESOLVED_ufixed, BOOLEAN]; + alias BINARY_READ is READ [LINE, UNRESOLVED_ufixed]; + alias BINARY_READ is READ [LINE, UNRESOLVED_sfixed, BOOLEAN]; + alias BINARY_READ is READ [LINE, UNRESOLVED_sfixed]; + + -- octal read and write + procedure OWRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure OWRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed); + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN); + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed); + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN); + alias OCTAL_READ is OREAD [LINE, UNRESOLVED_ufixed, BOOLEAN]; + alias OCTAL_READ is OREAD [LINE, UNRESOLVED_ufixed]; + alias OCTAL_READ is OREAD [LINE, UNRESOLVED_sfixed, BOOLEAN]; + alias OCTAL_READ is OREAD [LINE, UNRESOLVED_sfixed]; + alias OCTAL_WRITE is OWRITE [LINE, UNRESOLVED_ufixed, SIDE, WIDTH]; + alias OCTAL_WRITE is OWRITE [LINE, UNRESOLVED_sfixed, SIDE, WIDTH]; + + -- hex read and write + procedure HWRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + -- purpose: writes fixed point into a line + procedure HWRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed); + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN); + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed); + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN); + alias HEX_READ is HREAD [LINE, UNRESOLVED_ufixed, BOOLEAN]; + alias HEX_READ is HREAD [LINE, UNRESOLVED_sfixed, BOOLEAN]; + alias HEX_READ is HREAD [LINE, UNRESOLVED_ufixed]; + alias HEX_READ is HREAD [LINE, UNRESOLVED_sfixed]; + alias HEX_WRITE is HWRITE [LINE, UNRESOLVED_ufixed, SIDE, WIDTH]; + alias HEX_WRITE is HWRITE [LINE, UNRESOLVED_sfixed, SIDE, WIDTH]; + + -- returns a string, useful for: + -- assert (x = y) report "error found " & to_string(x) severity error; + function to_string (value : UNRESOLVED_ufixed) return STRING; + alias to_bstring is to_string [UNRESOLVED_ufixed return STRING]; + alias TO_BINARY_STRING is TO_STRING [UNRESOLVED_ufixed return STRING]; + + function to_ostring (value : UNRESOLVED_ufixed) return STRING; + alias TO_OCTAL_STRING is TO_OSTRING [UNRESOLVED_ufixed return STRING]; + + function to_hstring (value : UNRESOLVED_ufixed) return STRING; + alias TO_HEX_STRING is TO_HSTRING [UNRESOLVED_ufixed return STRING]; + + function to_string (value : UNRESOLVED_sfixed) return STRING; + alias to_bstring is to_string [UNRESOLVED_sfixed return STRING]; + alias TO_BINARY_STRING is TO_STRING [UNRESOLVED_sfixed return STRING]; + + function to_ostring (value : UNRESOLVED_sfixed) return STRING; + alias TO_OCTAL_STRING is TO_OSTRING [UNRESOLVED_sfixed return STRING]; + + function to_hstring (value : UNRESOLVED_sfixed) return STRING; + alias TO_HEX_STRING is TO_HSTRING [UNRESOLVED_sfixed return STRING]; + + -- From string functions allow you to convert a string into a fixed + -- point number. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100", uf1'high, uf1'low); -- 6.5 + -- The "." is optional in this syntax, however it exist and is + -- in the wrong location an error is produced. Overflow will + -- result in saturation. + + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + alias from_bstring is from_string [STRING, INTEGER, INTEGER + return UNRESOLVED_ufixed]; + alias from_binary_string is from_string [STRING, INTEGER, INTEGER + return UNRESOLVED_ufixed]; + + -- Octal and hex conversions work as follows: + -- uf1 <= from_hstring ("6.8", 3, -3); -- 6.5 (bottom zeros dropped) + -- uf1 <= from_ostring ("06.4", 3, -3); -- 6.5 (top zeros dropped) + + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + alias from_octal_string is from_ostring [STRING, INTEGER, INTEGER + return UNRESOLVED_ufixed]; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + alias from_hex_string is from_hstring [STRING, INTEGER, INTEGER + return UNRESOLVED_ufixed]; + + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + alias from_bstring is from_string [STRING, INTEGER, INTEGER + return UNRESOLVED_sfixed]; + alias from_binary_string is from_string [STRING, INTEGER, INTEGER + return UNRESOLVED_sfixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + alias from_octal_string is from_ostring [STRING, INTEGER, INTEGER + return UNRESOLVED_sfixed]; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + alias from_hex_string is from_hstring [STRING, INTEGER, INTEGER + return UNRESOLVED_sfixed]; + + -- Same as above, "size_res" is used for it's range only. + function from_string ( + bstring : STRING; -- binary string + size_res : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + alias from_bstring is from_string [STRING, UNRESOLVED_ufixed + return UNRESOLVED_ufixed]; + alias from_binary_string is from_string [STRING, UNRESOLVED_ufixed + return UNRESOLVED_ufixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + alias from_octal_string is from_ostring [STRING, UNRESOLVED_ufixed + return UNRESOLVED_ufixed]; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + alias from_hex_string is from_hstring [STRING, UNRESOLVED_ufixed + return UNRESOLVED_ufixed]; + + function from_string ( + bstring : STRING; -- binary string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + alias from_bstring is from_string [STRING, UNRESOLVED_sfixed + return UNRESOLVED_sfixed]; + alias from_binary_string is from_string [STRING, UNRESOLVED_sfixed + return UNRESOLVED_sfixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + alias from_octal_string is from_ostring [STRING, UNRESOLVED_sfixed + return UNRESOLVED_sfixed]; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + alias from_hex_string is from_hstring [STRING, UNRESOLVED_sfixed + return UNRESOLVED_sfixed]; + + -- Direct conversion functions. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100"); -- 6.5 + -- In this case the "." is not optional, and the size of + -- the output must match exactly. + + function from_string ( + bstring : STRING) -- binary string + return UNRESOLVED_ufixed; + alias from_bstring is from_string [STRING return UNRESOLVED_ufixed]; + alias from_binary_string is from_string [STRING return UNRESOLVED_ufixed]; + + -- Direct octal and hex conversion functions. In this case + -- the string lengths must match. Example: + -- signal sf1 := sfixed (5 downto -3); + -- sf1 <= from_ostring ("71.4") -- -6.5 + + function from_ostring ( + ostring : STRING) -- Octal string + return UNRESOLVED_ufixed; + alias from_octal_string is from_ostring [STRING return UNRESOLVED_ufixed]; + + function from_hstring ( + hstring : STRING) -- hex string + return UNRESOLVED_ufixed; + alias from_hex_string is from_hstring [STRING return UNRESOLVED_ufixed]; + + function from_string ( + bstring : STRING) -- binary string + return UNRESOLVED_sfixed; + alias from_bstring is from_string [STRING return UNRESOLVED_sfixed]; + alias from_binary_string is from_string [STRING return UNRESOLVED_sfixed]; + + function from_ostring ( + ostring : STRING) -- Octal string + return UNRESOLVED_sfixed; + alias from_octal_string is from_ostring [STRING return UNRESOLVED_sfixed]; + + function from_hstring ( + hstring : STRING) -- hex string + return UNRESOLVED_sfixed; + alias from_hex_string is from_hstring [STRING return UNRESOLVED_sfixed]; +-- rtl_synthesis on +-- pragma synthesis_on + + -- IN VHDL-2006 std_logic_vector is a subtype of std_ulogic_vector, so these + -- extra functions are needed for compatability. + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_ufixed) -- for size only + return UNRESOLVED_ufixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_sfixed) -- for size only + return UNRESOLVED_sfixed; + + -- unsigned fixed point + function to_UFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_ufixed; + + -- signed fixed point + function to_SFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_sfixed; + +end package fixed_pkg; +------------------------------------------------------------------------------- +-- Proposed package body for the VHDL-200x-FT fixed_pkg package +-- (Fixed point math package) +-- This package body supplies a recommended implementation of these functions +-- Version : $Revision: 1.21 $ +-- Date : $Date: 2007/09/26 18:08:53 $ +-- +-- Created for VHDL-200X-ft, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------- +library IEEE; +use IEEE.MATH_REAL.all; + +package body fixed_pkg is + -- Author David Bishop (dbishop@vhdl.org) + -- Other contributers: Jim Lewis, Yannick Grugni, Ryan W. Hilton + -- null array constants + constant NAUF : UNRESOLVED_ufixed (0 downto 1) := (others => '0'); + constant NASF : UNRESOLVED_sfixed (0 downto 1) := (others => '0'); + constant NSLV : STD_ULOGIC_VECTOR (0 downto 1) := (others => '0'); + + -- This differed constant will tell you if the package body is synthesizable + -- or implemented as real numbers, set to "true" if synthesizable. + constant fixedsynth_or_real : BOOLEAN := true; + + -- %%% Replicated functions + function maximum ( + l, r : integer) -- inputs + return integer is + begin -- function max + if l > r then return l; + else return r; + end if; + end function maximum; + + function minimum ( + l, r : integer) -- inputs + return integer is + begin -- function min + if l > r then return r; + else return l; + end if; + end function minimum; + + function "sra" (arg : SIGNED; count : INTEGER) + return SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(arg, count); + else + return SHIFT_LEFT(arg, -count); + end if; + end function "sra"; + + function or_reduce (arg : STD_ULOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '0'; + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) or BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := or_reduce (BUS_int (BUS_int'left downto Half)); + Lower := or_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper or Lower; + end if; + end if; + return Result; + end function or_reduce; + + -- purpose: AND all of the bits in a vector together + -- This is a copy of the proposed "and_reduce" from 1076.3 + function and_reduce (arg : STD_ULOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '1'; + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) and BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := and_reduce (BUS_int (BUS_int'left downto Half)); + Lower := and_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper and Lower; + end if; + end if; + return Result; + end function and_reduce; + + function xor_reduce (arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range + begin + if (arg'length >= 1) then + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := xor_reduce (BUS_int (BUS_int'left downto Half)); + Lower := xor_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper xor Lower; + end if; + end if; + return Result; + end function xor_reduce; + + function nand_reduce(arg : std_ulogic_vector) return STD_ULOGIC is + begin + return not and_reduce (arg); + end function nand_reduce; + function nor_reduce(arg : std_ulogic_vector) return STD_ULOGIC is + begin + return not or_reduce (arg); + end function nor_reduce; + function xnor_reduce(arg : std_ulogic_vector) return STD_ULOGIC is + begin + return not xor_reduce (arg); + end function xnor_reduce; + -- Match table, copied form new std_logic_1164 +-- type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; +-- constant match_logic_table : stdlogic_table := ( +-- ----------------------------------------------------- +-- -- U X 0 1 Z W L H - | | +-- ----------------------------------------------------- +-- ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1'), -- | U | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | X | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | 0 | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | 1 | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | Z | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | W | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | L | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | H | +-- ('1', '1', '1', '1', '1', '1', '1', '1', '1') -- | - | +-- ); + +-- constant no_match_logic_table : stdlogic_table := ( +-- ----------------------------------------------------- +-- -- U X 0 1 Z W L H - | | +-- ----------------------------------------------------- +-- ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '0'), -- | U | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | X | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | 0 | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | 1 | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | Z | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | W | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | L | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | H | +-- ('0', '0', '0', '0', '0', '0', '0', '0', '0') -- | - | +-- ); + + ------------------------------------------------------------------- + -- ?= functions, Similar to "std_match", but returns "std_ulogic". + ------------------------------------------------------------------- + function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + variable lx, rx : STD_ULOGIC; + begin +-- return match_logic_table (l, r); + lx := to_x01(l); + rx := to_x01(r); + if lx = 'X' or rx = 'X' then + return 'X'; + elsif lx = rx then + return '1'; + else + return '0'; + end if; + end function \?=\; + function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + begin +-- return no_match_logic_table (l, r); + return not \?=\ (l, r); + end function \?/=\; + -- "?=" operator is similar to "std_match", but returns a std_ulogic.. + -- Id: M.2B + function \?=\ (L, R: UNSIGNED) return STD_ULOGIC is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : UNSIGNED(L_LEFT downto 0) is L; + alias XR : UNSIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); + variable LX : UNSIGNED(SIZE-1 downto 0); + variable RX : UNSIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin + -- Logically identical to an "=" operator. + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '1'; + for i in LX'low to LX'high loop + result1 := \?=\(LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; + + -- Id: M.3B + function \?=\ (L, R: SIGNED) return std_ulogic is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : SIGNED(L_LEFT downto 0) is L; + alias XR : SIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); + variable LX : SIGNED(SIZE-1 downto 0); + variable RX : SIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '1'; + for i in LX'low to LX'high loop + result1 := \?=\ (LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; + + function \?/=\ (L, R : UNSIGNED) return std_ulogic is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : UNSIGNED(L_LEFT downto 0) is L; + alias XR : UNSIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); + variable LX : UNSIGNED(SIZE-1 downto 0); + variable RX : UNSIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?/="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '0'; + for i in LX'low to LX'high loop + result1 := \?/=\ (LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; + + function \?/=\ (L, R : SIGNED) return std_ulogic is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : SIGNED(L_LEFT downto 0) is L; + alias XR : SIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); + variable LX : SIGNED(SIZE-1 downto 0); + variable RX : SIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?/="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '0'; + for i in LX'low to LX'high loop + result1 := \?/=\ (LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; + + function Is_X ( s : UNSIGNED ) return BOOLEAN is + begin + return Is_X (STD_LOGIC_VECTOR (s)); + end function Is_X; + + function Is_X ( s : SIGNED ) return BOOLEAN is + begin + return Is_X (STD_LOGIC_VECTOR (s)); + end function Is_X; + function \?>\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + -- %%% function "?>" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?>"\; + function \?>\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + function \?>=\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + -- %%% function "?>=" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?>="; + function \?>=\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + function \?<\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + -- %%% function "?<" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?<"; + function \?<\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + function \?<=\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + -- %%% function "?<=" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?<="; + function \?<=\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + +-- %%% END replicated functions + -- Special version of "minimum" to do some boundary checking without errors + function mins (l, r : INTEGER) + return INTEGER is + begin -- function mins + if (L = INTEGER'low or R = INTEGER'low) then + return 0; -- error condition, silent + end if; + return minimum (L, R); + end function mins; + + -- Special version of "minimum" to do some boundary checking with errors + function mine (l, r : INTEGER) + return INTEGER is + begin -- function mine + if (L = INTEGER'low or R = INTEGER'low) then + report "fixed_pkg:" + & " Unbounded number passed, was a literal used?" + severity error; + return 0; + end if; + return minimum (L, R); + end function mine; + + -- The following functions are used only internally. Every function + -- calls "cleanvec" either directly or indirectly. + -- purpose: Fixes "downto" problem and resolves meta states + function cleanvec ( + arg : UNRESOLVED_sfixed) -- input + return UNRESOLVED_sfixed is + constant left_index : INTEGER := maximum(arg'left, arg'right); + constant right_index : INTEGER := mins(arg'left, arg'right); + variable result : UNRESOLVED_sfixed (arg'range); + begin -- function cleanvec + assert not (arg'ascending and (arg'low /= INTEGER'low)) + report "fixed_pkg:" + & " Vector passed using a ""to"" range, expected is ""downto""" + severity error; + return arg; + end function cleanvec; + + -- purpose: Fixes "downto" problem and resolves meta states + function cleanvec ( + arg : UNRESOLVED_ufixed) -- input + return UNRESOLVED_ufixed is + constant left_index : INTEGER := maximum(arg'left, arg'right); + constant right_index : INTEGER := mins(arg'left, arg'right); + variable result : UNRESOLVED_ufixed (arg'range); + begin -- function cleanvec + assert not (arg'ascending and (arg'low /= INTEGER'low)) + report "fixed_pkg:" + & " Vector passed using a ""to"" range, expected is ""downto""" + severity error; + return arg; + end function cleanvec; + + -- Type convert a "unsigned" into a "ufixed", used internally + function to_fixed ( + arg : UNSIGNED; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (left_index downto right_index); + begin -- function to_fixed + result := UNRESOLVED_ufixed(arg); + return result; + end function to_fixed; + + -- Type convert a "signed" into an "sfixed", used internally + function to_fixed ( + arg : SIGNED; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (left_index downto right_index); + begin -- function to_fixed + result := UNRESOLVED_sfixed(arg); + return result; + end function to_fixed; + + -- Type convert a "ufixed" into an "unsigned", used internally + function to_uns ( + arg : UNRESOLVED_ufixed) -- fp vector + return UNSIGNED is + subtype t is UNSIGNED(arg'high - arg'low downto 0); + variable slv : t; + begin -- function to_uns + slv := t(arg); + return slv; + end function to_uns; + + -- Type convert an "sfixed" into a "signed", used internally + function to_s ( + arg : UNRESOLVED_sfixed) -- fp vector + return SIGNED is + subtype t is SIGNED(arg'high - arg'low downto 0); + variable slv : t; + begin -- function to_s + slv := t(arg); + return slv; + end function to_s; + + -- adds 1 to the LSB of the number + procedure round_up (arg : in UNRESOLVED_ufixed; + result : out UNRESOLVED_ufixed; + overflowx : out BOOLEAN) is + variable arguns, resuns : UNSIGNED (arg'high-arg'low+1 downto 0) + := (others => '0'); + begin -- round_up + arguns (arguns'high-1 downto 0) := to_uns (arg); + resuns := arguns + 1; + result := to_fixed(resuns(arg'high-arg'low + downto 0), arg'high, arg'low); + overflowx := (resuns(resuns'high) = '1'); + end procedure round_up; + + -- adds 1 to the LSB of the number + procedure round_up (arg : in UNRESOLVED_sfixed; + result : out UNRESOLVED_sfixed; + overflowx : out BOOLEAN) is + variable args, ress : SIGNED (arg'high-arg'low+1 downto 0); + begin -- round_up + args (args'high-1 downto 0) := to_s (arg); + args(args'high) := arg(arg'high); -- sign extend + ress := args + 1; + result := to_fixed(ress (ress'high-1 + downto 0), arg'high, arg'low); + overflowx := ((arg(arg'high) /= ress(ress'high-1)) + and (or_reduce (STD_ULOGIC_VECTOR(ress)) /= '0')); + end procedure round_up; + + -- Rounding - Performs a "round_nearest" (IEEE 754) which rounds up + -- when the remainder is > 0.5. If the remainder IS 0.5 then if the + -- bottom bit is a "1" it is rounded, otherwise it remains the same. + function round_fixed (arg : UNRESOLVED_ufixed; + remainder : UNRESOLVED_ufixed; + overflow_style : fixed_overflow_style_type := fixed_overflow_style) + return UNRESOLVED_ufixed is + variable rounds : BOOLEAN; + variable round_overflow : BOOLEAN; + variable result : UNRESOLVED_ufixed (arg'range); + begin + rounds := false; + if (remainder'length > 1) then + if (remainder (remainder'high) = '1') then + rounds := (arg(arg'low) = '1') + or (or_reduce (to_sulv(remainder(remainder'high-1 downto + remainder'low))) = '1'); + end if; + else + rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); + end if; + if rounds then + round_up(arg => arg, + result => result, + overflowx => round_overflow); + else + result := arg; + end if; + if (overflow_style = fixed_saturate) and round_overflow then + result := saturate (result'high, result'low); + end if; + return result; + end function round_fixed; + + -- Rounding case statement + function round_fixed (arg : UNRESOLVED_sfixed; + remainder : UNRESOLVED_sfixed; + overflow_style : fixed_overflow_style_type := fixed_overflow_style) + return UNRESOLVED_sfixed is + variable rounds : BOOLEAN; + variable round_overflow : BOOLEAN; + variable result : UNRESOLVED_sfixed (arg'range); + begin + rounds := false; + if (remainder'length > 1) then + if (remainder (remainder'high) = '1') then + rounds := (arg(arg'low) = '1') + or (or_reduce (to_sulv(remainder(remainder'high-1 downto + remainder'low))) = '1'); + end if; + else + rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); + end if; + if rounds then + round_up(arg => arg, + result => result, + overflowx => round_overflow); + else + result := arg; + end if; + if round_overflow then + if (overflow_style = fixed_saturate) then + if arg(arg'high) = '0' then + result := saturate (result'high, result'low); + else + result := not saturate (result'high, result'low); + end if; + -- Sign bit not fixed when wrapping + end if; + end if; + return result; + end function round_fixed; + + -- converts an sfixed into a ufixed. The output is the same length as the + -- input, because abs("1000") = "1000" = 8. + function to_ufixed ( + arg : UNRESOLVED_sfixed) + return UNRESOLVED_ufixed + is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable xarg : UNRESOLVED_sfixed(left_index+1 downto right_index); + variable result : UNRESOLVED_ufixed(left_index downto right_index); + begin + if arg'length < 1 then + return NAUF; + end if; + xarg := abs(arg); + result := UNRESOLVED_ufixed (xarg (left_index downto right_index)); + return result; + end function to_ufixed; + +----------------------------------------------------------------------------- +-- Visible functions +----------------------------------------------------------------------------- + + -- Conversion functions. These are needed for synthesis where typically + -- the only input and output type is a std_logic_vector. + function to_sulv ( + arg : UNRESOLVED_ufixed) -- fixed point vector + return STD_ULOGIC_VECTOR is + variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0); + begin + if arg'length < 1 then + return NSLV; + end if; + result := STD_ULOGIC_VECTOR (arg); + return result; + end function to_sulv; + + function to_sulv ( + arg : UNRESOLVED_sfixed) -- fixed point vector + return STD_ULOGIC_VECTOR is + variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0); + begin + if arg'length < 1 then + return NSLV; + end if; + result := STD_ULOGIC_VECTOR (arg); + return result; + end function to_sulv; + + function to_slv ( + arg : UNRESOLVED_ufixed) -- fixed point vector + return STD_LOGIC_VECTOR is + begin + return std_logic_vector(to_sulv(arg)); + end function to_slv; + + function to_slv ( + arg : UNRESOLVED_sfixed) -- fixed point vector + return STD_LOGIC_VECTOR is + begin + return std_logic_vector(to_sulv(arg)); + end function to_slv; + + function to_ufixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return unresolved_ufixed is + variable result : UNRESOLVED_ufixed (left_index downto right_index); + begin + if (arg'length < 1 or right_index > left_index) then + return NAUF; + end if; + if (arg'length /= result'length) then + report "fixed_pkg:" & "TO_UFIXED(SLV) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NAUF; + else + result := to_fixed (arg => UNSIGNED(arg), + left_index => left_index, + right_index => right_index); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return unresolved_sfixed is + variable result : UNRESOLVED_sfixed (left_index downto right_index); + begin + if (arg'length < 1 or right_index > left_index) then + return NASF; + end if; + if (arg'length /= result'length) then + report "fixed_pkg:" & "TO_SFIXED(SLV) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NASF; + else + result := to_fixed (arg => SIGNED(arg), + left_index => left_index, + right_index => right_index); + return result; + end if; + end function to_sfixed; + + -- Two's complement number, Grows the vector by 1 bit. + -- because "abs (1000.000) = 01000.000" or abs(-16) = 16. + function "abs" ( + arg : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable ressns : SIGNED (arg'length downto 0); + variable result : UNRESOLVED_sfixed (left_index+1 downto right_index); + begin + if (arg'length < 1 or result'length < 1) then + return NASF; + end if; + ressns (arg'length-1 downto 0) := to_s (cleanvec (arg)); + ressns (arg'length) := ressns (arg'length-1); -- expand sign bit + result := to_fixed (abs(ressns), left_index+1, right_index); + return result; + end function "abs"; + + -- also grows the vector by 1 bit. + function "-" ( + arg : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + constant left_index : INTEGER := arg'high+1; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable ressns : SIGNED (arg'length downto 0); + variable result : UNRESOLVED_sfixed (left_index downto right_index); + begin + if (arg'length < 1 or result'length < 1) then + return NASF; + end if; + ressns (arg'length-1 downto 0) := to_s (cleanvec(arg)); + ressns (arg'length) := ressns (arg'length-1); -- expand sign bit + result := to_fixed (-ressns, left_index, right_index); + return result; + end function "-"; + + -- Addition + function "+" ( + l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) + ufixed(c downto d) = + return UNRESOLVED_ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mine(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable result : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + begin + if (l'length < 1 or r'length < 1 or result'length < 1) then + return NAUF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv + rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "+"; + + function "+" ( + l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) + sfixed(c downto d) = + return UNRESOLVED_sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mine(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable result : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index downto 0); + variable result_slv : SIGNED (left_index-right_index downto 0); + begin + if (l'length < 1 or r'length < 1 or result'length < 1) then + return NASF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv + rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "+"; + + -- Subtraction + function "-" ( + l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) - ufixed(c downto d) = + return UNRESOLVED_ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mine(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable result : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + begin + if (l'length < 1 or r'length < 1 or result'length < 1) then + return NAUF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv - rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "-"; + + function "-" ( + l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) - sfixed(c downto d) = + return UNRESOLVED_sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mine(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable result : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index downto 0); + variable result_slv : SIGNED (left_index-right_index downto 0); + begin + if (l'length < 1 or r'length < 1 or result'length < 1) then + return NASF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv - rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "-"; + + function "*" ( + l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) * ufixed(c downto d) = + return UNRESOLVED_ufixed is -- ufixed(a+c+1 downto b+d) + variable lslv : UNSIGNED (l'length-1 downto 0); + variable rslv : UNSIGNED (r'length-1 downto 0); + variable result_slv : UNSIGNED (r'length+l'length-1 downto 0); + variable result : UNRESOLVED_ufixed (l'high + r'high+1 downto + mine(l'low, l'low) + mine(r'low, r'low)); + begin + if (l'length < 1 or r'length < 1 or + result'length /= result_slv'length) then + return NAUF; + end if; + lslv := to_uns (cleanvec(l)); + rslv := to_uns (cleanvec(r)); + result_slv := lslv * rslv; + result := to_fixed (result_slv, result'high, result'low); + return result; + end function "*"; + + function "*" ( + l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) * sfixed(c downto d) = + return UNRESOLVED_sfixed is -- sfixed(a+c+1 downto b+d) + variable lslv : SIGNED (l'length-1 downto 0); + variable rslv : SIGNED (r'length-1 downto 0); + variable result_slv : SIGNED (r'length+l'length-1 downto 0); + variable result : UNRESOLVED_sfixed (l'high + r'high+1 downto + mine(l'low, l'low) + mine(r'low, r'low)); + begin + if (l'length < 1 or r'length < 1 or + result'length /= result_slv'length) then + return NASF; + end if; + lslv := to_s (cleanvec(l)); + rslv := to_s (cleanvec(r)); + result_slv := lslv * rslv; + result := to_fixed (result_slv, result'high, result'low); + return result; + end function "*"; + +-- function "/" ( +-- l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) / ufixed(c downto d) = +-- return UNRESOLVED_ufixed is -- ufixed(a-d downto b-c-1) +-- begin +-- return divide (l, r); +-- end function "/"; + +-- function "/" ( +-- l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) / sfixed(c downto d) = +-- return UNRESOLVED_sfixed is -- sfixed(a-d+1 downto b-c) +-- begin +-- return divide (l, r); +-- end function "/"; + + -- This version of divide gives the user more control + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) +-- function divide ( +-- l, r : UNRESOLVED_ufixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed is +-- variable result : UNRESOLVED_ufixed (l'high - mine(r'low, r'low) downto +-- mine (l'low, l'low) - r'high -1); +-- variable dresult : UNRESOLVED_ufixed (result'high downto result'low -guard_bits); +-- variable lresize : UNRESOLVED_ufixed (l'high downto l'high - dresult'length+1); +-- variable lslv : UNSIGNED (lresize'length-1 downto 0); +-- variable rslv : UNSIGNED (r'length-1 downto 0); +-- variable result_slv : UNSIGNED (lresize'length-1 downto 0); +-- begin +-- if (l'length < 1 or r'length < 1 or +-- mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then +-- return NAUF; +-- end if; +-- lresize := resize (arg => l, +-- left_index => lresize'high, +-- right_index => lresize'low, +-- overflow_style => fixed_wrap, -- vector only grows +-- round_style => fixed_truncate); +-- lslv := to_uns (cleanvec (lresize)); +-- rslv := to_uns (cleanvec (r)); +-- if (rslv = 0) then +-- report "fixed_pkg:" +-- & "DIVIDE(ufixed) Division by zero" severity error; +-- result := saturate (result'high, result'low); -- saturate +-- else +-- result_slv := lslv / rslv; +-- dresult := to_fixed (result_slv, dresult'high, dresult'low); +-- result := resize (arg => dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => fixed_wrap, -- overflow impossible +-- round_style => round_style); +-- end if; +-- return result; +-- end function divide; + + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) +-- function divide ( +-- l, r : UNRESOLVED_sfixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed is +-- variable result : UNRESOLVED_sfixed (l'high - mine(r'low, r'low) + 1 downto +-- mine (l'low, l'low) - r'high); +-- variable dresult : UNRESOLVED_sfixed (result'high downto result'low-guard_bits); +-- variable lresize : UNRESOLVED_sfixed (l'high+1 downto l'high+1 -dresult'length+1); +-- variable lslv : SIGNED (lresize'length-1 downto 0); +-- variable rslv : SIGNED (r'length-1 downto 0); +-- variable result_slv : SIGNED (lresize'length-1 downto 0); +-- begin +-- if (l'length < 1 or r'length < 1 or +-- mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then +-- return NASF; +-- end if; +-- lresize := resize (arg => l, +-- left_index => lresize'high, +-- right_index => lresize'low, +-- overflow_style => fixed_wrap, -- vector only grows +-- round_style => fixed_truncate); +-- lslv := to_s (cleanvec (lresize)); +-- rslv := to_s (cleanvec (r)); +-- if (rslv = 0) then +-- report "fixed_pkg:" +-- & "DIVIDE(sfixed) Division by zero" severity error; +-- result := saturate (result'high, result'low); +-- else +-- result_slv := lslv / rslv; +-- dresult := to_fixed (result_slv, dresult'high, dresult'low); +-- result := resize (arg => dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => fixed_wrap, -- overflow impossible +-- round_style => round_style); +-- end if; +-- return result; +-- end function divide; + + -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) +-- function reciprocal ( +-- arg : UNRESOLVED_ufixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed is +-- constant one : UNRESOLVED_ufixed (0 downto 0) := "1"; +-- begin +-- return divide (l => one, +-- r => arg, +-- round_style => round_style, +-- guard_bits => guard_bits); +-- end function reciprocal; + + -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) +-- function reciprocal ( +-- arg : UNRESOLVED_sfixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed is +-- constant one : UNRESOLVED_sfixed (1 downto 0) := "01"; -- extra bit. +-- variable resultx : UNRESOLVED_sfixed (-mine(arg'low, arg'low)+2 downto -arg'high); +-- begin +-- if (arg'length < 1 or resultx'length < 1) then +-- return NASF; +-- else +-- resultx := divide (l => one, +-- r => arg, +-- round_style => round_style, +-- guard_bits => guard_bits); +-- return resultx (resultx'high-1 downto resultx'low); -- remove extra bit +-- end if; +-- end function reciprocal; + + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) +-- function "rem" ( +-- l, r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return remainder (l, r); +-- end function "rem"; + +-- -- remainder +-- -- sfixed (a downto b) rem sfixed (c downto d) +-- -- = sfixed (min(a,c) downto min(b,d)) +-- function "rem" ( +-- l, r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return remainder (l, r); +-- end function "rem"; + + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) +-- function remainder ( +-- l, r : UNRESOLVED_ufixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed is +-- variable result : UNRESOLVED_ufixed (minimum(l'high, r'high) downto +-- mine(l'low, r'low)); +-- variable lresize : UNRESOLVED_ufixed (maximum(l'high, r'low) downto +-- mins(r'low, r'low)-guard_bits); +-- variable rresize : UNRESOLVED_ufixed (r'high downto r'low-guard_bits); +-- variable dresult : UNRESOLVED_ufixed (rresize'range); +-- variable lslv : UNSIGNED (lresize'length-1 downto 0); +-- variable rslv : UNSIGNED (rresize'length-1 downto 0); +-- variable result_slv : UNSIGNED (rslv'range); +-- begin +-- if (l'length < 1 or r'length < 1 or +-- mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then +-- return NAUF; +-- end if; +-- lresize := resize (arg => l, +-- left_index => lresize'high, +-- right_index => lresize'low, +-- overflow_style => fixed_wrap, -- vector only grows +-- round_style => fixed_truncate); +-- lslv := to_uns (lresize); +-- rresize := resize (arg => r, +-- left_index => rresize'high, +-- right_index => rresize'low, +-- overflow_style => fixed_wrap, -- vector only grows +-- round_style => fixed_truncate); +-- rslv := to_uns (rresize); +-- if (rslv = 0) then +-- report "fixed_pkg:" +-- & "remainder(ufixed) Division by zero" severity error; +-- result := saturate (result'high, result'low); -- saturate +-- else +-- if (r'low <= l'high) then +-- result_slv := lslv rem rslv; +-- dresult := to_fixed (result_slv, dresult'high, dresult'low); +-- result := resize (arg => dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => fixed_wrap, -- can't overflow +-- round_style => round_style); +-- end if; +-- if l'low < r'low then +-- result(mins(r'low-1, l'high) downto l'low) := +-- cleanvec(l(mins(r'low-1, l'high) downto l'low)); +-- end if; +-- end if; +-- return result; +-- end function remainder; + +-- -- remainder +-- -- sfixed (a downto b) rem sfixed (c downto d) +-- -- = sfixed (min(a,c) downto min(b,d)) +-- function remainder ( +-- l, r : UNRESOLVED_sfixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed is +-- variable l_abs : UNRESOLVED_ufixed (l'range); +-- variable r_abs : UNRESOLVED_ufixed (r'range); +-- variable result : UNRESOLVED_sfixed (minimum(r'high, l'high) downto +-- mine(r'low, l'low)); +-- variable neg_result : UNRESOLVED_sfixed (minimum(r'high, l'high)+1 downto +-- mins(r'low, l'low)); +-- begin +-- if (l'length < 1 or r'length < 1 or +-- mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then +-- return NASF; +-- end if; +-- l_abs := to_ufixed (l); +-- r_abs := to_ufixed (r); +-- result := UNRESOLVED_sfixed (remainder ( +-- l => l_abs, +-- r => r_abs, +-- round_style => round_style)); +-- neg_result := -result; +-- if l(l'high) = '1' then +-- result := neg_result(result'range); +-- end if; +-- return result; +-- end function remainder; + +-- -- modulo +-- -- ufixed (a downto b) mod ufixed (c downto d) +-- -- = ufixed (min(a,c) downto min(b, d)) +-- function "mod" ( +-- l, r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return modulo (l, r); +-- end function "mod"; + +-- -- sfixed (a downto b) mod sfixed (c downto d) +-- -- = sfixed (c downto min(b, d)) +-- function "mod" ( +-- l, r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return modulo(l, r); +-- end function "mod"; + +-- -- modulo +-- -- ufixed (a downto b) mod ufixed (c downto d) +-- -- = ufixed (min(a,c) downto min(b, d)) +-- function modulo ( +-- l, r : UNRESOLVED_ufixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed is +-- begin +-- return remainder(l => l, +-- r => r, +-- round_style => round_style, +-- guard_bits => guard_bits); +-- end function modulo; + +-- -- sfixed (a downto b) mod sfixed (c downto d) +-- -- = sfixed (c downto min(b, d)) +-- function modulo ( +-- l, r : UNRESOLVED_sfixed; -- fixed point input +-- constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed is +-- variable l_abs : UNRESOLVED_ufixed (l'range); +-- variable r_abs : UNRESOLVED_ufixed (r'range); +-- variable result : UNRESOLVED_sfixed (r'high downto +-- mine(r'low, l'low)); +-- variable dresult : UNRESOLVED_sfixed (minimum(r'high, l'high)+1 downto +-- mins(r'low, l'low)); +-- variable dresult_not_zero : BOOLEAN; +-- begin +-- if (l'length < 1 or r'length < 1 or +-- mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then +-- return NASF; +-- end if; +-- l_abs := to_ufixed (l); +-- r_abs := to_ufixed (r); +-- dresult := "0" & UNRESOLVED_sfixed(remainder (l => l_abs, +-- r => r_abs, +-- round_style => round_style)); +-- if (to_s(dresult) = 0) then +-- dresult_not_zero := false; +-- else +-- dresult_not_zero := true; +-- end if; +-- if to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '0' +-- and dresult_not_zero then +-- result := resize (arg => r - dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => overflow_style, +-- round_style => round_style); +-- elsif to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '1' then +-- result := resize (arg => -dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => overflow_style, +-- round_style => round_style); +-- elsif to_x01(l(l'high)) = '0' and to_x01(r(r'high)) = '1' +-- and dresult_not_zero then +-- result := resize (arg => dresult + r, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => overflow_style, +-- round_style => round_style); +-- else +-- result := resize (arg => dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => overflow_style, +-- round_style => round_style); +-- end if; +-- return result; +-- end function modulo; + + -- Procedure for those who need an "accumulator" function + procedure add_carry ( + L, R : in UNRESOLVED_ufixed; + c_in : in STD_ULOGIC; + result : out UNRESOLVED_ufixed; + c_out : out STD_ULOGIC) is + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + variable cx : UNSIGNED (0 downto 0); -- Carry in + begin + if (l'length < 1 or r'length < 1) then + result := NAUF; + c_out := '0'; + else + cx (0) := c_in; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv + rslv + cx; + c_out := result_slv(left_index); + result := to_fixed(result_slv (left_index-right_index-1 downto 0), + left_index-1, right_index); + end if; + end procedure add_carry; + + procedure add_carry ( + L, R : in UNRESOLVED_sfixed; + c_in : in STD_ULOGIC; + result : out UNRESOLVED_sfixed; + c_out : out STD_ULOGIC) is + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index + downto 0); + variable result_slv : SIGNED (left_index-right_index + downto 0); + variable cx : SIGNED (1 downto 0); -- Carry in + begin + if (l'length < 1 or r'length < 1) then + result := NASF; + c_out := '0'; + else + cx (1) := '0'; + cx (0) := c_in; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv + rslv + cx; + c_out := result_slv(left_index); + result := to_fixed(result_slv (left_index-right_index-1 downto 0), + left_index-1, right_index); + end if; + end procedure add_carry; + + -- Scales the result by a power of 2. Width of input = width of output with + -- the decimal point moved. + function scalb (y : UNRESOLVED_ufixed; N : INTEGER) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (y'high+N downto y'low+N); + begin + if y'length < 1 then + return NAUF; + else + result := y; + return result; + end if; + end function scalb; + + function scalb (y : UNRESOLVED_ufixed; N : SIGNED) + return UNRESOLVED_ufixed is + begin + return scalb (y => y, + N => to_integer(N)); + end function scalb; + + function scalb (y : UNRESOLVED_sfixed; N : INTEGER) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (y'high+N downto y'low+N); + begin + if y'length < 1 then + return NASF; + else + result := y; + return result; + end if; + end function scalb; + + function scalb (y : UNRESOLVED_sfixed; N : SIGNED) + return UNRESOLVED_sfixed is + begin + return scalb (y => y, + N => to_integer(N)); + end function scalb; + + function Is_Negative (arg : UNRESOLVED_sfixed) return BOOLEAN is + begin + if to_X01(arg(arg'high)) = '1' then + return true; + else + return false; + end if; + end function Is_Negative; + + function find_rightmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) + return INTEGER is + begin + for_loop : for i in arg'reverse_range loop + if \?=\ (arg(i), y) = '1' then + return i; + end if; + end loop; + return arg'high+1; -- return out of bounds 'high + end function find_rightmost; + + function find_leftmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) + return INTEGER is + begin + for_loop : for i in arg'range loop + if \?=\ (arg(i), y) = '1' then + return i; + end if; + end loop; + return arg'low-1; -- return out of bounds 'low + end function find_leftmost; + + function find_rightmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) + return INTEGER is + begin + for_loop : for i in arg'reverse_range loop + if \?=\ (arg(i), y) = '1' then + return i; + end if; + end loop; + return arg'high+1; -- return out of bounds 'high + end function find_rightmost; + + function find_leftmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) + return INTEGER is + begin + for_loop : for i in arg'range loop + if \?=\ (arg(i), y) = '1' then + return i; + end if; + end loop; + return arg'low-1; -- return out of bounds 'low + end function find_leftmost; + + function "sll" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sll"; + + function "srl" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "srl"; + + function "rol" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv rol COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "rol"; + + function "ror" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv ror COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "ror"; + + function "sla" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + -- Arithmetic shift on an unsigned is a logical shift + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sla"; + + function "sra" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + -- Arithmetic shift on an unsigned is a logical shift + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sra"; + + function "sll" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sll"; + + function "srl" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "srl"; + + function "rol" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv rol COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "rol"; + + function "ror" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv ror COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "ror"; + + function "sla" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + if COUNT > 0 then + -- Arithmetic shift left on a 2's complement number is a logic shift + argslv := argslv sll COUNT; + else + argslv := argslv sra -COUNT; + end if; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sla"; + + function "sra" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + if COUNT > 0 then + argslv := argslv sra COUNT; + else + -- Arithmetic shift left on a 2's complement number is a logic shift + argslv := argslv sll -COUNT; + end if; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sra"; + + -- Because some people want the older functions. + function SHIFT_LEFT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) + return UNRESOLVED_ufixed is + begin + if (ARG'length < 1) then + return NAUF; + end if; + return ARG sla COUNT; + end function SHIFT_LEFT; + + function SHIFT_RIGHT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) + return UNRESOLVED_ufixed is + begin + if (ARG'length < 1) then + return NAUF; + end if; + return ARG sra COUNT; + end function SHIFT_RIGHT; + + function SHIFT_LEFT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) + return UNRESOLVED_sfixed is + begin + if (ARG'length < 1) then + return NASF; + end if; + return ARG sla COUNT; + end function SHIFT_LEFT; + + function SHIFT_RIGHT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) + return UNRESOLVED_sfixed is + begin + if (ARG'length < 1) then + return NASF; + end if; + return ARG sra COUNT; + end function SHIFT_RIGHT; + + ---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + function "not" (L : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + RESULT := not to_sulv(L); + return to_ufixed(RESULT, L'high, L'low); + end function "not"; + + function "and" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) and to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """and"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "and"; + + function "or" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) or to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """or"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "or"; + + function "nand" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) nand to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """nand"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "nand"; + + function "nor" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) nor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """nor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "nor"; + + function "xor" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) xor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """xor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "xor"; + + function "xnor" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) xnor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """xnor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "xnor"; + + function "not" (L : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + RESULT := not to_sulv(L); + return to_sfixed(RESULT, L'high, L'low); + end function "not"; + + function "and" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) and to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """and"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "and"; + + function "or" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) or to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """or"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "or"; + + function "nand" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) nand to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """nand"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "nand"; + + function "nor" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) nor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """nor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "nor"; + + function "xor" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) xor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """xor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "xor"; + + function "xnor" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) xnor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """xnor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + 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 : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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 : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xnor R; + end loop; + return result; + end function "xnor"; + + -- Reduction operator_reduces + function and_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return and_reduce (to_sulv(l)); + end function and_reduce; + + function nand_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return nand_reduce (to_sulv(l)); + end function nand_reduce; + + function or_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return or_reduce (to_sulv(l)); + end function or_reduce; + + function nor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return nor_reduce (to_sulv(l)); + end function nor_reduce; + + function xor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return xor_reduce (to_sulv(l)); + end function xor_reduce; + + function xnor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return xnor_reduce (to_sulv(l)); + end function xnor_reduce; + + function and_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return and_reduce (to_sulv(l)); + end function and_reduce; + + function nand_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return nand_reduce (to_sulv(l)); + end function nand_reduce; + + function or_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return or_reduce (to_sulv(l)); + end function or_reduce; + + function nor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return nor_reduce (to_sulv(l)); + end function nor_reduce; + + function xor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return xor_reduce (to_sulv(l)); + end function xor_reduce; + + function xnor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return xnor_reduce (to_sulv(l)); + end function xnor_reduce; + -- End reduction operator_reduces + + function \?=\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?="": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?=\; + + function \?/=\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?/="": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?/=\; + + function \?>\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?>"": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?>\; + + function \?>=\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?>="": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?>=\; + + function \?<\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?<"": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?<\; + + function \?<=\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?<="": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?<=\; + + function \?=\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?="": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?=\; + + function \?/=\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?/="": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?/=\; + + function \?>\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?>"": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?>\; + + function \?>=\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?>="": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?>=\; + + function \?<\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?<"": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?<\; + + function \?<=\ (L, R : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """?<="": null detected, returning X" + severity warning; + return 'X'; + else + 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 if; + end function \?<=\; + + -- Match function, similar to "std_match" from numeric_std + function std_match (L, R : UNRESOLVED_ufixed) return BOOLEAN is + begin + if (L'high = R'high and L'low = R'low) then + return std_match(to_sulv(L), to_sulv(R)); + else + assert NO_WARNING + report "fixed_pkg:" + & "STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" + severity warning; + return false; + end if; + end function std_match; + + function std_match (L, R : UNRESOLVED_sfixed) return BOOLEAN is + begin + if (L'high = R'high and L'low = R'low) then + return std_match(to_sulv(L), to_sulv(R)); + else + assert NO_WARNING + report "fixed_pkg:" + & "STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" + severity warning; + return false; + end if; + end function std_match; + + -- compare functions + function "=" ( + l, r : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """/="": null argument detected, returning TRUE" + severity warning; + return true; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """/="": null argument detected, returning TRUE" + severity warning; + return true; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """>"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """>"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """<"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """<"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """>="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """>="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """<="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_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 : UNRESOLVED_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_pkg:" + & """<="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_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 : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + 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); + if lresize > rresize then return lresize; + else return rresize; + end if; + end function maximum; + + function maximum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + 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); + if lresize > rresize then return lresize; + else return rresize; + end if; + end function maximum; + + function minimum (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + 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); + if lresize > rresize then return rresize; + else return lresize; + end if; + end function minimum; + + function minimum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + 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); + if lresize > rresize then return rresize; + else return lresize; + end if; + end function minimum; + + function to_ufixed ( + arg : NATURAL; -- integer + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant fw : INTEGER := mins (right_index, right_index); -- catch literals + variable result : UNRESOLVED_ufixed (left_index downto fw); + variable sresult : UNRESOLVED_ufixed (left_index downto 0) := + (others => '0'); -- integer portion + variable argx : NATURAL; -- internal version of arg + begin + if (result'length < 1) then + return NAUF; + end if; + if arg /= 0 then + argx := arg; + for I in 0 to sresult'left loop + if (argx mod 2) = 0 then + sresult(I) := '0'; + else + sresult(I) := '1'; + end if; + argx := argx/2; + end loop; + if argx /= 0 then + assert NO_WARNING + report "fixed_pkg:" + & "TO_UFIXED(NATURAL): vector truncated" + severity warning; + if overflow_style = fixed_saturate then + return saturate (left_index, right_index); + end if; + end if; + result := resize (arg => sresult, + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + else + result := (others => '0'); + end if; + return result; + end function to_ufixed; + + function to_sfixed ( + arg : INTEGER; -- integer + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant fw : INTEGER := mins (right_index, right_index); -- catch literals + variable result : UNRESOLVED_sfixed (left_index downto fw); + variable sresult : UNRESOLVED_sfixed (left_index downto 0) := + (others => '0'); -- integer portion + variable argx : INTEGER; -- internal version of arg + variable sign : STD_ULOGIC; -- sign of input + begin + if (result'length < 1) then -- null range + return NASF; + end if; + if arg /= 0 then + if (arg < 0) then + sign := '1'; + argx := -(arg + 1); + else + sign := '0'; + argx := arg; + end if; + for I in 0 to sresult'left loop + if (argx mod 2) = 0 then + sresult(I) := sign; + else + sresult(I) := not sign; + end if; + argx := argx/2; + end loop; + if argx /= 0 or left_index < 0 or sign /= sresult(sresult'left) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_SFIXED(INTEGER): vector truncated" + severity warning; + if overflow_style = fixed_saturate then -- 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; + end if; + result := resize (arg => sresult, + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + else + result := (others => '0'); + end if; + return result; + end function to_sfixed; + + function to_ufixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return UNRESOLVED_ufixed is + constant fw : INTEGER := mins (right_index, right_index); -- catch literals + variable result : UNRESOLVED_ufixed (left_index downto fw) := + (others => '0'); + variable Xresult : UNRESOLVED_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_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_pkg:" + & "TO_UFIXED(REAL): vector truncated" + severity warning; + 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; -- left index (high index) + constant right_index : INTEGER; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return UNRESOLVED_sfixed is + constant fw : INTEGER := mins (right_index, right_index); -- catch literals + variable result : UNRESOLVED_sfixed (left_index downto fw) := + (others => '0'); + variable Xresult : UNRESOLVED_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_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 = 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_sfixed; + + function to_ufixed ( + arg : UNSIGNED; -- unsigned + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; + variable result : UNRESOLVED_ufixed (left_index downto right_index); + begin + if arg'length < 1 or (left_index < right_index) then + return NAUF; + end if; + result := resize (arg => UNRESOLVED_ufixed (XARG), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_ufixed; + + -- converted version + function to_ufixed ( + arg : UNSIGNED) -- unsigned + return UNRESOLVED_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 UNRESOLVED_ufixed(xarg); + end function to_ufixed; + + function to_sfixed ( + arg : SIGNED; -- signed + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; + variable result : UNRESOLVED_sfixed (left_index downto right_index); + begin + if arg'length < 1 or (left_index < right_index) then + return NASF; + end if; + result := resize (arg => UNRESOLVED_sfixed (XARG), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_sfixed; + + -- converted version + function to_sfixed ( + arg : SIGNED) -- signed + return UNRESOLVED_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 UNRESOLVED_sfixed(xarg); + end function to_sfixed; + + function to_sfixed (arg : UNRESOLVED_ufixed) return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (arg'high+1 downto arg'low); + begin + if arg'length < 1 then + return NASF; + end if; + result (arg'high downto arg'low) := UNRESOLVED_sfixed(cleanvec(arg)); + result (arg'high+1) := '0'; + return result; + end function to_sfixed; + + -- Because of the fairly complicated sizing rules in the fixed point + -- packages these functions are provided to compute the result ranges + -- Example: + -- signal uf1 : ufixed (3 downto -3); + -- signal uf2 : ufixed (4 downto -2); + -- signal uf1multuf2 : ufixed (ufixed_high (3, -3, '*', 4, -2) downto + -- ufixed_low (3, -3, '*', 4, -2)); + -- uf1multuf2 <= uf1 * uf2; + -- Valid characters: '+', '-', '*', '/', 'r' or 'R' (rem), 'm' or 'M' (mod), + -- '1' (reciprocal), 'A', '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 : UNRESOLVED_ufixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_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 : UNRESOLVED_ufixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_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 : UNRESOLVED_sfixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_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 : UNRESOLVED_sfixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_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 UNRESOLVED_ufixed is + constant sat : UNRESOLVED_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 UNRESOLVED_sfixed is + variable sat : UNRESOLVED_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 : UNRESOLVED_ufixed) -- only the size of this is used + return UNRESOLVED_ufixed is + begin + return saturate (size_res'high, size_res'low); + end function saturate; + + function saturate ( + size_res : UNRESOLVED_sfixed) -- only the size of this is used + return UNRESOLVED_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_ULOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (width-fraction-1 downto -fraction); + begin + if (arg'length /= result'length) then + report "fixed_pkg:" + & "TO_UFIX (STD_ULOGIC_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_ULOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (width-fraction-1 downto -fraction); + begin + if (arg'length /= result'length) then + report "fixed_pkg:" + & "TO_SFIX (STD_ULOGIC_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 : UNRESOLVED_ufixed; -- ufixed point input + constant size : NATURAL; -- length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNSIGNED 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 : UNRESOLVED_ufixed; -- ufixed point input + size_res : UNSIGNED; -- length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNSIGNED 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 : UNRESOLVED_sfixed; -- sfixed point input + constant size : NATURAL; -- length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return SIGNED 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 : UNRESOLVED_sfixed; -- sfixed point input + size_res : SIGNED; -- used for length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return SIGNED 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 : UNRESOLVED_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 : UNRESOLVED_ufixed (left_index downto right_index); + begin + if (arg'length < 1) then + return 0.0; + end if; + arg_int := to_x01(cleanvec(arg)); + if (Is_X(arg_int)) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_REAL (ufixed): 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 : UNRESOLVED_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 : UNRESOLVED_sfixed (left_index downto right_index); + -- unsigned version of argument + variable arg_uns : UNRESOLVED_ufixed (left_index downto right_index); + -- absolute of argument + begin + if (arg'length < 1) then + return 0.0; + end if; + arg_int := to_x01(cleanvec(arg)); + if (Is_X(arg_int)) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_REAL (sfixed): metavalue detected, returning 0.0" + severity warning; + return 0.0; + end if; + arg_uns := to_ufixed (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 : UNRESOLVED_ufixed; -- fixed point input + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return NATURAL is + constant left_index : INTEGER := arg'high; + variable arg_uns : UNSIGNED (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_pkg:" + & "TO_INTEGER (ufixed): 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 : UNRESOLVED_sfixed; -- fixed point input + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return INTEGER is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := arg'low; + variable arg_s : SIGNED (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_pkg:" + & "TO_INTEGER (sfixed): 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 : UNRESOLVED_ufixed; -- ufixed point input + constant XMAP : STD_ULOGIC := '0') -- Map x to + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (s'range); -- result + begin + if (s'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_01(ufixed): null detected, returning NULL" + severity warning; + return NAUF; + end if; + return to_fixed (to_01(to_uns(s), XMAP), s'high, s'low); + end function to_01; + + function to_01 ( + s : UNRESOLVED_sfixed; -- sfixed point input + constant XMAP : STD_ULOGIC := '0') -- Map x to + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (s'range); + begin + if (s'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_01(sfixed): null detected, returning NULL" + severity warning; + return NASF; + end if; + return to_fixed (to_01(to_s(s), XMAP), s'high, s'low); + end function to_01; + + function Is_X ( + arg : UNRESOLVED_ufixed) + return BOOLEAN is + variable argslv : STD_ULOGIC_VECTOR (arg'length-1 downto 0); -- slv + begin + argslv := to_sulv(arg); + return Is_X (argslv); + end function Is_X; + + function Is_X ( + arg : UNRESOLVED_sfixed) + return BOOLEAN is + variable argslv : STD_ULOGIC_VECTOR (arg'length-1 downto 0); -- slv + begin + argslv := to_sulv(arg); + return Is_X (argslv); + end function Is_X; + + function To_X01 ( + arg : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return to_ufixed (To_X01(to_sulv(arg)), arg'high, arg'low); + end function To_X01; + + function to_X01 ( + arg : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return to_sfixed (To_X01(to_sulv(arg)), arg'high, arg'low); + end function To_X01; + + function To_X01Z ( + arg : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return to_ufixed (To_X01Z(to_sulv(arg)), arg'high, arg'low); + end function To_X01Z; + + function to_X01Z ( + arg : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return to_sfixed (To_X01Z(to_sulv(arg)), arg'high, arg'low); + end function To_X01Z; + + function To_UX01 ( + arg : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return to_ufixed (To_UX01(to_sulv(arg)), arg'high, arg'low); + end function To_UX01; + + function to_UX01 ( + arg : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return to_sfixed (To_UX01(to_sulv(arg)), arg'high, arg'low); + end function To_UX01; + + function resize ( + arg : UNRESOLVED_ufixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant arghigh : INTEGER := maximum (arg'high, arg'low); + constant arglow : INTEGER := mine (arg'high, arg'low); + variable invec : UNRESOLVED_ufixed (arghigh downto arglow); + variable result : UNRESOLVED_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_reduce(to_sulv(invec)) = '1') then + result := saturate (result'high, result'low); -- saturate + end if; + elsif (arghigh > left_index) then + -- wrap or saturate? + if (overflow_style = fixed_saturate and + or_reduce (to_sulv(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 : UNRESOLVED_sfixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant arghigh : INTEGER := maximum (arg'high, arg'low); + constant arglow : INTEGER := mine (arg'high, arg'low); + variable invec : UNRESOLVED_sfixed (arghigh downto arglow); + variable result : UNRESOLVED_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 = fixed_saturate) then + reduced := or_reduce (to_sulv(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_reduce (to_sulv(invec(arghigh-1 downto + left_index))); + if overflow_style = fixed_saturate 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_reduce (to_sulv(invec(arghigh-1 downto + left_index))); + if overflow_style = fixed_saturate 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_ULOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_ufixed) -- for size only + return UNRESOLVED_ufixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_ufixed (size_res'left downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NAUF; + 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_ULOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_sfixed) -- for size only + return UNRESOLVED_sfixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_sfixed (size_res'left downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NASF; + 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 : NATURAL; -- integer + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_ufixed (size_res'left downto fw); + begin + if (result'length < 1) then + return NAUF; + 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 : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_sfixed (size_res'left downto fw); + begin + if (result'length < 1) then + return NASF; + 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 : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return UNRESOLVED_ufixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_ufixed (size_res'left downto fw); + begin + if (result'length < 1) then + return NAUF; + 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 : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return UNRESOLVED_sfixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_sfixed (size_res'left downto fw); + begin + if (result'length < 1) then + return NASF; + 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 : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_ufixed (size_res'left downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NAUF; + 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 : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_sfixed (size_res'left downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NASF; + 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 : UNRESOLVED_ufixed; -- input + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_ufixed (size_res'high downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NAUF; + 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 : UNRESOLVED_sfixed; -- input + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_sfixed (size_res'high downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NASF; + 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 math functions for real + function "+" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : REAL) + return UNRESOLVED_ufixed is + begin + return (l + to_ufixed (r, l'high, l'low)); + end function "+"; + + function "+" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, r'low) + r); + end function "+"; + + function "+" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : REAL) + return UNRESOLVED_sfixed is + begin + return (l + to_sfixed (r, l'high, l'low)); + end function "+"; + + function "+" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, r'low) + r); + end function "+"; + + function "-" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : REAL) + return UNRESOLVED_ufixed is + begin + return (l - to_ufixed (r, l'high, l'low)); + end function "-"; + + function "-" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, r'low) - r); + end function "-"; + + function "-" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : REAL) + return UNRESOLVED_sfixed is + begin + return (l - to_sfixed (r, l'high, l'low)); + end function "-"; + + function "-" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, r'low) - r); + end function "-"; + + function "*" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : REAL) + return UNRESOLVED_ufixed is + begin + return (l * to_ufixed (r, l'high, l'low)); + end function "*"; + + function "*" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, r'low) * r); + end function "*"; + + function "*" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : REAL) + return UNRESOLVED_sfixed is + begin + return (l * to_sfixed (r, l'high, l'low)); + end function "*"; + + function "*" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, r'low) * r); + end function "*"; + +-- function "/" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l / to_ufixed (r, l'high, l'low)); +-- end function "/"; + +-- function "/" ( +-- l : REAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, r'low) / r); +-- end function "/"; + +-- function "/" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l / to_sfixed (r, l'high, l'low)); +-- end function "/"; + +-- function "/" ( +-- l : REAL; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, r'low) / r); +-- end function "/"; + +-- function "rem" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l rem to_ufixed (r, l'high, l'low)); +-- end function "rem"; + +-- function "rem" ( +-- l : REAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, r'low) rem r); +-- end function "rem"; + +-- function "rem" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l rem to_sfixed (r, l'high, l'low)); +-- end function "rem"; + +-- function "rem" ( +-- l : REAL; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, r'low) rem r); +-- end function "rem"; + +-- function "mod" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l mod to_ufixed (r, l'high, l'low)); +-- end function "mod"; + +-- function "mod" ( +-- l : REAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, r'low) mod r); +-- end function "mod"; + +-- function "mod" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l mod to_sfixed (r, l'high, l'low)); +-- end function "mod"; + +-- function "mod" ( +-- l : REAL; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, r'low) mod r); +-- end function "mod"; + + -- Overloaded math functions for integers + function "+" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : NATURAL) + return UNRESOLVED_ufixed is + begin + return (l + to_ufixed (r, l'high, 0)); + end function "+"; + + function "+" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, 0) + r); + end function "+"; + + function "+" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : INTEGER) + return UNRESOLVED_sfixed is + begin + return (l + to_sfixed (r, l'high, 0)); + end function "+"; + + function "+" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, 0) + r); + end function "+"; + + -- Overloaded functions + function "-" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : NATURAL) + return UNRESOLVED_ufixed is + begin + return (l - to_ufixed (r, l'high, 0)); + end function "-"; + + function "-" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, 0) - r); + end function "-"; + + function "-" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : INTEGER) + return UNRESOLVED_sfixed is + begin + return (l - to_sfixed (r, l'high, 0)); + end function "-"; + + function "-" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, 0) - r); + end function "-"; + + -- Overloaded functions + function "*" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : NATURAL) + return UNRESOLVED_ufixed is + begin + return (l * to_ufixed (r, l'high, 0)); + end function "*"; + + function "*" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, 0) * r); + end function "*"; + + function "*" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : INTEGER) + return UNRESOLVED_sfixed is + begin + return (l * to_sfixed (r, l'high, 0)); + end function "*"; + + function "*" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, 0) * r); + end function "*"; + + -- Overloaded functions +-- function "/" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : NATURAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l / to_ufixed (r, l'high, 0)); +-- end function "/"; + +-- function "/" ( +-- l : NATURAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, 0) / r); +-- end function "/"; + +-- function "/" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : INTEGER) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l / to_sfixed (r, l'high, 0)); +-- end function "/"; + +-- function "/" ( +-- l : INTEGER; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, 0) / r); +-- end function "/"; + +-- function "rem" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : NATURAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l rem to_ufixed (r, l'high, 0)); +-- end function "rem"; + +-- function "rem" ( +-- l : NATURAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, 0) rem r); +-- end function "rem"; + +-- function "rem" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : INTEGER) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l rem to_sfixed (r, l'high, 0)); +-- end function "rem"; + +-- function "rem" ( +-- l : INTEGER; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, 0) rem r); +-- end function "rem"; + +-- function "mod" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : NATURAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l mod to_ufixed (r, l'high, 0)); +-- end function "mod"; + +-- function "mod" ( +-- l : NATURAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, 0) mod r); +-- end function "mod"; + +-- function "mod" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : INTEGER) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l mod to_sfixed (r, l'high, 0)); +-- end function "mod"; + +-- function "mod" ( +-- l : INTEGER; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, 0) mod r); +-- end function "mod"; + + -- overloaded ufixed compare functions with integer + function "=" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l = to_ufixed (r, l'high, l'low)); + end function "="; + + function "/=" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l /= to_ufixed (r, l'high, l'low)); + end function "/="; + + function ">=" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l >= to_ufixed (r, l'high, l'low)); + end function ">="; + + function "<=" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l <= to_ufixed (r, l'high, l'low)); + end function "<="; + + function ">" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l > to_ufixed (r, l'high, l'low)); + end function ">"; + + function "<" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l < to_ufixed (r, l'high, l'low)); + end function "<"; + + function \?=\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?=\ (l, to_ufixed (r, l'high, l'low)); + end function \?=\; + + function \?/=\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?/=\ (l, to_ufixed (r, l'high, l'low)); + end function \?/=\; + + function \?>=\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?>=\ (l, to_ufixed (r, l'high, l'low)); + end function \?>=\; + + function \?<=\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?<=\ (l, to_ufixed (r, l'high, l'low)); + end function \?<=\; + + function \?>\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?>\ (l, to_ufixed (r, l'high, l'low)); + end function \?>\; + + function \?<\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?<\ (l, to_ufixed (r, l'high, l'low)); + end function \?<\; + + function maximum ( + l : UNRESOLVED_ufixed; -- fixed point input + r : NATURAL) + return UNRESOLVED_ufixed is + begin + return maximum (l, to_ufixed (r, l'high, l'low)); + end function maximum; + + function minimum ( + l : UNRESOLVED_ufixed; -- fixed point input + r : NATURAL) + return UNRESOLVED_ufixed is + begin + return minimum (l, to_ufixed (r, l'high, l'low)); + end function minimum; + + -- NATURAL to ufixed + function "=" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) = r); + end function "="; + + function "/=" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) /= r); + end function "/="; + + function ">=" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) >= r); + end function ">="; + + function "<=" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) <= r); + end function "<="; + + function ">" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) > r); + end function ">"; + + function "<" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) < r); + end function "<"; + + function \?=\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?=\ (to_ufixed (l, r'high, r'low), r); + end function \?=\; + + function \?/=\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?/=\ (to_ufixed (l, r'high, r'low), r); + end function \?/=\; + + function \?>=\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>=\ (to_ufixed (l, r'high, r'low), r); + end function \?>=\; + + function \?<=\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<=\ (to_ufixed (l, r'high, r'low), r); + end function \?<=\; + + function \?>\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>\ (to_ufixed (l, r'high, r'low), r); + end function \?>\; + + function \?<\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<\ (to_ufixed (l, r'high, r'low), r); + end function \?<\; + + function maximum ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return maximum (to_ufixed (l, r'high, r'low), r); + end function maximum; + + function minimum ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return minimum (to_ufixed (l, r'high, r'low), r); + end function minimum; + + -- overloaded ufixed compare functions with real + function "=" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l = to_ufixed (r, l'high, l'low)); + end function "="; + + function "/=" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l /= to_ufixed (r, l'high, l'low)); + end function "/="; + + function ">=" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l >= to_ufixed (r, l'high, l'low)); + end function ">="; + + function "<=" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l <= to_ufixed (r, l'high, l'low)); + end function "<="; + + function ">" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l > to_ufixed (r, l'high, l'low)); + end function ">"; + + function "<" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l < to_ufixed (r, l'high, l'low)); + end function "<"; + + function \?=\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?=\ (l, to_ufixed (r, l'high, l'low)); + end function \?=\; + + function \?/=\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?/=\ (l, to_ufixed (r, l'high, l'low)); + end function \?/=\; + + function \?>=\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?>=\ (l, to_ufixed (r, l'high, l'low)); + end function \?>=\; + + function \?<=\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?<=\ (l, to_ufixed (r, l'high, l'low)); + end function \?<=\; + + function \?>\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?>\ (l, to_ufixed (r, l'high, l'low)); + end function \?>\; + + function \?<\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?<\ (l, to_ufixed (r, l'high, l'low)); + end function \?<\; + + function maximum ( + l : UNRESOLVED_ufixed; + r : REAL) + return UNRESOLVED_ufixed is + begin + return maximum (l, to_ufixed (r, l'high, l'low)); + end function maximum; + + function minimum ( + l : UNRESOLVED_ufixed; + r : REAL) + return UNRESOLVED_ufixed is + begin + return minimum (l, to_ufixed (r, l'high, l'low)); + end function minimum; + + -- real and ufixed + function "=" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) = r); + end function "="; + + function "/=" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) /= r); + end function "/="; + + function ">=" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) >= r); + end function ">="; + + function "<=" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) <= r); + end function "<="; + + function ">" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) > r); + end function ">"; + + function "<" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) < r); + end function "<"; + + function \?=\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?=\ (to_ufixed (l, r'high, r'low), r); + end function \?=\; + + function \?/=\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?/=\ (to_ufixed (l, r'high, r'low), r); + end function \?/=\; + + function \?>=\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>=\ (to_ufixed (l, r'high, r'low), r); + end function \?>=\; + + function \?<=\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<=\ (to_ufixed (l, r'high, r'low), r); + end function \?<=\; + + function \?>\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>\ (to_ufixed (l, r'high, r'low), r); + end function \?>\; + + function \?<\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<\ (to_ufixed (l, r'high, r'low), r); + end function \?<\; + + function maximum ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return maximum (to_ufixed (l, r'high, r'low), r); + end function maximum; + + function minimum ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return minimum (to_ufixed (l, r'high, r'low), r); + end function minimum; + + -- overloaded sfixed compare functions with integer + function "=" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l = to_sfixed (r, l'high, l'low)); + end function "="; + + function "/=" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l /= to_sfixed (r, l'high, l'low)); + end function "/="; + + function ">=" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l >= to_sfixed (r, l'high, l'low)); + end function ">="; + + function "<=" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l <= to_sfixed (r, l'high, l'low)); + end function "<="; + + function ">" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l > to_sfixed (r, l'high, l'low)); + end function ">"; + + function "<" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l < to_sfixed (r, l'high, l'low)); + end function "<"; + + function \?=\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?=\ (l, to_sfixed (r, l'high, l'low)); + end function \?=\; + + function \?/=\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?/=\ (l, to_sfixed (r, l'high, l'low)); + end function \?/=\; + + function \?>=\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?>=\ (l, to_sfixed (r, l'high, l'low)); + end function \?>=\; + + function \?<=\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?<=\ (l, to_sfixed (r, l'high, l'low)); + end function \?<=\; + + function \?>\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?>\ (l, to_sfixed (r, l'high, l'low)); + end function \?>\; + + function \?<\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?<\ (l, to_sfixed (r, l'high, l'low)); + end function \?<\; + + function maximum ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return UNRESOLVED_sfixed is + begin + return maximum (l, to_sfixed (r, l'high, l'low)); + end function maximum; + + function minimum ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return UNRESOLVED_sfixed is + begin + return minimum (l, to_sfixed (r, l'high, l'low)); + end function minimum; + + -- integer and sfixed + function "=" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) = r); + end function "="; + + function "/=" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) /= r); + end function "/="; + + function ">=" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) >= r); + end function ">="; + + function "<=" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) <= r); + end function "<="; + + function ">" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) > r); + end function ">"; + + function "<" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) < r); + end function "<"; + + function \?=\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?=\ (to_sfixed (l, r'high, r'low), r); + end function \?=\; + + function \?/=\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?/=\ (to_sfixed (l, r'high, r'low), r); + end function \?/=\; + + function \?>=\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>=\ (to_sfixed (l, r'high, r'low), r); + end function \?>=\; + + function \?<=\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<=\ (to_sfixed (l, r'high, r'low), r); + end function \?<=\; + + function \?>\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>\ (to_sfixed (l, r'high, r'low), r); + end function \?>\; + + function \?<\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<\ (to_sfixed (l, r'high, r'low), r); + end function \?<\; + + function maximum ( + l : INTEGER; + r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return maximum (to_sfixed (l, r'high, r'low), r); + end function maximum; + + function minimum ( + l : INTEGER; + r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return minimum (to_sfixed (l, r'high, r'low), r); + end function minimum; + + -- overloaded sfixed compare functions with real + function "=" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l = to_sfixed (r, l'high, l'low)); + end function "="; + + function "/=" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l /= to_sfixed (r, l'high, l'low)); + end function "/="; + + function ">=" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l >= to_sfixed (r, l'high, l'low)); + end function ">="; + + function "<=" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l <= to_sfixed (r, l'high, l'low)); + end function "<="; + + function ">" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l > to_sfixed (r, l'high, l'low)); + end function ">"; + + function "<" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l < to_sfixed (r, l'high, l'low)); + end function "<"; + + function \?=\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?=\ (l, to_sfixed (r, l'high, l'low)); + end function \?=\; + + function \?/=\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?/=\ (l, to_sfixed (r, l'high, l'low)); + end function \?/=\; + + function \?>=\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?>=\ (l, to_sfixed (r, l'high, l'low)); + end function \?>=\; + + function \?<=\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?<=\ (l, to_sfixed (r, l'high, l'low)); + end function \?<=\; + + function \?>\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?>\ (l, to_sfixed (r, l'high, l'low)); + end function \?>\; + + function \?<\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?<\ (l, to_sfixed (r, l'high, l'low)); + end function \?<\; + + function maximum ( + l : UNRESOLVED_sfixed; + r : REAL) + return UNRESOLVED_sfixed is + begin + return maximum (l, to_sfixed (r, l'high, l'low)); + end function maximum; + + function minimum ( + l : UNRESOLVED_sfixed; + r : REAL) + return UNRESOLVED_sfixed is + begin + return minimum (l, to_sfixed (r, l'high, l'low)); + end function minimum; + + -- REAL and sfixed + function "=" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) = r); + end function "="; + + function "/=" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) /= r); + end function "/="; + + function ">=" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) >= r); + end function ">="; + + function "<=" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) <= r); + end function "<="; + + function ">" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) > r); + end function ">"; + + function "<" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) < r); + end function "<"; + + function \?=\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?=\ (to_sfixed (l, r'high, r'low), r); + end function \?=\; + + function \?/=\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?/=\ (to_sfixed (l, r'high, r'low), r); + end function \?/=\; + + function \?>=\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>=\ (to_sfixed (l, r'high, r'low), r); + end function \?>=\; + + function \?<=\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<=\ (to_sfixed (l, r'high, r'low), r); + end function \?<=\; + + function \?>\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>\ (to_sfixed (l, r'high, r'low), r); + end function \?>\; + + function \?<\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<\ (to_sfixed (l, r'high, r'low), r); + end function \?<\; + + function maximum ( + l : REAL; + r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return maximum (to_sfixed (l, r'high, r'low), r); + end function maximum; + + function minimum ( + l : REAL; + r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return minimum (to_sfixed (l, r'high, r'low), r); + end function minimum; +-- rtl_synthesis off +-- pragma synthesis_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 => ' '); + + -- %%% Replicated Textio functions + procedure Char2TriBits (C : CHARACTER; + RESULT : out STD_ULOGIC_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_pkg:" + & "OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + result := "UUU"; + good := false; + end case; + end procedure Char2TriBits; + -- Hex Read and Write procedures for STD_ULOGIC_VECTOR. + -- Modified from the original to be more forgiving. + + procedure Char2QuadBits (C : CHARACTER; + RESULT : out STD_ULOGIC_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_pkg:" + & "HREAD Error: Read a '" & c & + "', expected a Hex character (0-F)." + severity error; + result := "UUUU"; + good := false; + end case; + end procedure Char2QuadBits; + + -- purpose: Skips white space + procedure skip_whitespace ( + L : inout LINE) is + variable readOk : BOOLEAN; + variable c : CHARACTER; + begin + while L /= null and L.all'length /= 0 loop + if (L.all(1) = ' ' or L.all(1) = NBSP or L.all(1) = HT) then + read (l, c, readOk); + else + exit; + end if; + end loop; + end procedure skip_whitespace; + + function to_ostring (value : STD_ULOGIC_VECTOR) return STRING is + constant ne : INTEGER := (value'length+2)/3; + variable pad : STD_ULOGIC_VECTOR(0 to (ne*3 - value'length) - 1); + variable ivalue : STD_ULOGIC_VECTOR(0 to ne*3 - 1); + variable result : STRING(1 to ne); + variable tri : STD_ULOGIC_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 result; + end if; + end function to_ostring; + ------------------------------------------------------------------- + function to_hstring (value : STD_ULOGIC_VECTOR) return STRING is + constant ne : INTEGER := (value'length+3)/4; + variable pad : STD_ULOGIC_VECTOR(0 to (ne*4 - value'length) - 1); + variable ivalue : STD_ULOGIC_VECTOR(0 to ne*4 - 1); + variable result : STRING(1 to ne); + variable quad : STD_ULOGIC_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 result; + end if; + end function to_hstring; + + +-- %%% END replicated textio functions + + -- purpose: writes fixed point into a line + procedure write ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) 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 UNRESOLVED_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 UNRESOLVED_ufixed) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable readOk : BOOLEAN; + variable i : INTEGER; -- index variable + variable mv : ufixed (VALUE'range); + variable lastu : BOOLEAN := false; -- last character was an "_" + variable founddot : BOOLEAN := false; -- found a "." + begin -- READ + VALUE := (VALUE'range => 'U'); + Skip_whitespace (L); + if VALUE'length > 0 then -- non Null input string + read (l, c, readOk); + i := value'high; + while i >= VALUE'low loop + if readOk = false then -- Bail out if there was a bad read + report "fixed_pkg:" & "READ(ufixed) " + & "End of string encountered" + severity error; + return; + elsif c = '_' then + if i = value'high then + report "fixed_pkg:" & "READ(ufixed) " + & "String begins with an ""_""" severity error; + return; + elsif lastu then + report "fixed_pkg:" & "READ(ufixed) " + & "Two underscores detected in input string ""__""" + severity error; + return; + else + lastu := true; + end if; + elsif c = '.' then -- binary point + if founddot then + report "fixed_pkg:" & "READ(ufixed) " + & "Two binary points found in input string" severity error; + return; + elsif i /= -1 then -- Seperator in the wrong spot + report "fixed_pkg:" & "READ(ufixed) " + & "Decimal point does not match number format " + severity error; + return; + end if; + founddot := true; + lastu := false; + elsif c = ' ' or c = NBSP or c = HT then -- reading done. + report "fixed_pkg:" & "READ(ufixed) " + & "Short read, Space encounted in input string" + severity error; + return; + elsif char_to_MVL9plus(c) = error then + report "fixed_pkg:" & "READ(ufixed) " + & "Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + return; + else + mv(i) := char_to_MVL9(c); + i := i - 1; + if i < mv'low then + VALUE := mv; + return; + end if; + lastu := false; + end if; + read(L, c, readOk); + end loop; + end if; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable readOk : BOOLEAN; + variable mv : ufixed (VALUE'range); + variable i : INTEGER; -- index variable + variable lastu : BOOLEAN := false; -- last character was an "_" + variable founddot : BOOLEAN := false; -- found a "." + begin -- READ + VALUE := (VALUE'range => 'U'); + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, readOk); + i := value'high; + GOOD := false; + while i >= VALUE'low loop + if not readOk then -- Bail out if there was a bad read + return; + elsif c = '_' then + if i = value'high then -- Begins with an "_" + return; + elsif lastu then -- "__" detected + return; + else + lastu := true; + end if; + elsif c = '.' then -- binary point + if founddot then + return; + elsif i /= -1 then -- Seperator in the wrong spot + return; + end if; + founddot := true; + lastu := false; + elsif (char_to_MVL9plus(c) = error) then -- Illegal character/short read + return; + else + mv(i) := char_to_MVL9(c); + i := i - 1; + if i < mv'low then -- reading done + GOOD := true; + VALUE := mv; + return; + end if; + lastu := false; + end if; + read(L, c, readOk); + end loop; + else + GOOD := true; -- read into a null array + end if; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_sfixed) is + variable c : CHARACTER; + variable readOk : BOOLEAN; + variable i : INTEGER; -- index variable + variable mv : sfixed (VALUE'range); + variable lastu : BOOLEAN := false; -- last character was an "_" + variable founddot : BOOLEAN := false; -- found a "." + begin -- READ + VALUE := (VALUE'range => 'U'); + Skip_whitespace (L); + if VALUE'length > 0 then -- non Null input string + read (l, c, readOk); + i := value'high; + while i >= VALUE'low loop + if readOk = false then -- Bail out if there was a bad read + report "fixed_pkg:" & "READ(sfixed) " + & "End of string encountered" + severity error; + return; + elsif c = '_' then + if i = value'high then + report "fixed_pkg:" & "READ(sfixed) " + & "String begins with an ""_""" severity error; + return; + elsif lastu then + report "fixed_pkg:" & "READ(sfixed) " + & "Two underscores detected in input string ""__""" + severity error; + return; + else + lastu := true; + end if; + elsif c = '.' then -- binary point + if founddot then + report "fixed_pkg:" & "READ(sfixed) " + & "Two binary points found in input string" severity error; + return; + elsif i /= -1 then -- Seperator in the wrong spot + report "fixed_pkg:" & "READ(sfixed) " + & "Decimal point does not match number format " + severity error; + return; + end if; + founddot := true; + lastu := false; + elsif c = ' ' or c = NBSP or c = HT then -- reading done. + report "fixed_pkg:" & "READ(sfixed) " + & "Short read, Space encounted in input string" + severity error; + return; + elsif char_to_MVL9plus(c) = error then + report "fixed_pkg:" & "READ(sfixed) " + & "Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + return; + else + mv(i) := char_to_MVL9(c); + i := i - 1; + if i < mv'low then + VALUE := mv; + return; + end if; + lastu := false; + end if; + read(L, c, readOk); + end loop; + end if; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN) is + variable value_ufixed : UNRESOLVED_ufixed (VALUE'range); + begin -- READ + READ (L => L, VALUE => value_ufixed, GOOD => GOOD); + VALUE := UNRESOLVED_sfixed (value_ufixed); + end procedure READ; + + -- octal read and write + procedure owrite ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) 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 UNRESOLVED_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; + + -- purpose: Routines common to the OREAD routines + procedure OREAD_common ( + L : inout LINE; + slv : out STD_ULOGIC_VECTOR; + igood : out BOOLEAN; + idex : out INTEGER; + constant bpoint : in INTEGER; -- binary point + constant message : in BOOLEAN; + constant smath : in BOOLEAN) is + + -- purpose: error message routine + procedure errmes ( + constant mess : in STRING) is -- error message + begin + if message then + if smath then + report "fixed_pkg:" + & "OREAD(sfixed) " + & mess + severity error; + else + report "fixed_pkg:" + & "OREAD(ufixed) " + & mess + severity error; + end if; + end if; + end procedure errmes; + variable xgood : BOOLEAN; + variable nybble : STD_ULOGIC_VECTOR (2 downto 0); -- 3 bits + variable c : CHARACTER; + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + variable founddot : BOOLEAN := false; -- found a dot. + begin + Skip_whitespace (L); + if slv'length > 0 then + i := slv'high; + read (l, c, xgood); + while i > 0 loop + if xgood = false then + errmes ("Error: end of string encountered"); + exit; + elsif c = '_' then + if i = slv'length then + errmes ("Error: String begins with an ""_"""); + xgood := false; + exit; + elsif lastu then + errmes ("Error: Two underscores detected in input string ""__"""); + xgood := false; + exit; + else + lastu := true; + end if; + elsif (c = '.') then + if (i + 1 /= bpoint) then + errmes ("encountered ""."" at wrong index"); + xgood := false; + exit; + elsif i = slv'length then + errmes ("encounted a ""."" at the beginning of the line"); + xgood := false; + exit; + elsif founddot then + errmes ("Two ""."" encounted in input string"); + xgood := false; + exit; + end if; + founddot := true; + lastu := false; + else + Char2triBits(c, nybble, xgood, message); + if not xgood then + exit; + end if; + slv (i downto i-2) := nybble; + i := i - 3; + lastu := false; + end if; + if i > 0 then + read (L, c, xgood); + end if; + end loop; + idex := i; + igood := xgood; + else + igood := true; -- read into a null array + idex := -1; + end if; + end procedure OREAD_common; + + -- 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 UNRESOLVED_ufixed) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-2)/3)*3; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + OREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => true, + smath => false); + if igood then -- We did not get another error + if not ((i = -1) and -- We read everything, and high bits 0 + (or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then + report "fixed_pkg:" + & "OREAD(ufixed): Vector truncated." + severity error; + else + if (or_reduce (slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "fixed_pkg:" + & "OREAD(ufixed): Vector truncated" + severity warning; + end if; + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end if; + end if; + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-2)/3)*3; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + OREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => false, + smath => false); + if (igood and -- We did not get another error + (i = -1) and -- We read everything, and high bits 0 + (or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + good := true; + else + good := false; + end if; + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-2)/3)*3; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + OREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => true, + smath => true); + if igood then -- We did not get another error + if not ((i = -1) and -- We read everything + ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then + report "fixed_pkg:" + & "OREAD(sfixed): Vector truncated." + severity error; + else + if (or_reduce (slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "fixed_pkg:" + & "OREAD(sfixed): Vector truncated" + severity warning; + end if; + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end if; + end if; + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-2)/3)*3; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + OREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => false, + smath => true); + if (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_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + good := true; + else + good := false; + end if; + end procedure OREAD; + + -- hex read and write + procedure hwrite ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) 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 UNRESOLVED_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; + + -- purpose: Routines common to the OREAD routines + procedure HREAD_common ( + L : inout LINE; + slv : out STD_ULOGIC_VECTOR; + igood : out BOOLEAN; + idex : out INTEGER; + constant bpoint : in INTEGER; -- binary point + constant message : in BOOLEAN; + constant smath : in BOOLEAN) is + + -- purpose: error message routine + procedure errmes ( + constant mess : in STRING) is -- error message + begin + if message then + if smath then + report "fixed_pkg:" + & "HREAD(sfixed) " + & mess + severity error; + else + report "fixed_pkg:" + & "HREAD(ufixed) " + & mess + severity error; + end if; + end if; + end procedure errmes; + variable xgood : BOOLEAN; + variable nybble : STD_ULOGIC_VECTOR (3 downto 0); -- 4 bits + variable c : CHARACTER; + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + variable founddot : BOOLEAN := false; -- found a dot. + begin + Skip_whitespace (L); + if slv'length > 0 then + i := slv'high; + read (l, c, xgood); + while i > 0 loop + if xgood = false then + errmes ("Error: end of string encountered"); + exit; + elsif c = '_' then + if i = slv'length then + errmes ("Error: String begins with an ""_"""); + xgood := false; + exit; + elsif lastu then + errmes ("Error: Two underscores detected in input string ""__"""); + xgood := false; + exit; + else + lastu := true; + end if; + elsif (c = '.') then + if (i + 1 /= bpoint) then + errmes ("encountered ""."" at wrong index"); + xgood := false; + exit; + elsif i = slv'length then + errmes ("encounted a ""."" at the beginning of the line"); + xgood := false; + exit; + elsif founddot then + errmes ("Two ""."" encounted in input string"); + xgood := false; + exit; + end if; + founddot := true; + lastu := false; + else + Char2QuadBits(c, nybble, xgood, message); + if not xgood then + exit; + end if; + slv (i downto i-3) := nybble; + i := i - 4; + lastu := false; + end if; + if i > 0 then + read (L, c, xgood); + end if; + end loop; + idex := i; + igood := xgood; + else + idex := -1; + igood := true; -- read null string + end if; + end procedure HREAD_common; + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-3)/4)*4; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + HREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => false, + smath => false); + if igood then + if not ((i = -1) and -- We read everything, and high bits 0 + (or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then + report "fixed_pkg:" + & "HREAD(ufixed): Vector truncated." + severity error; + else + if (or_reduce (slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "fixed_pkg:" + & "HREAD(ufixed): Vector truncated" + severity warning; + end if; + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end if; + end if; + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-3)/4)*4; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + HREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => false, + smath => false); + if (igood and -- We did not get another error + (i = -1) and -- We read everything, and high bits 0 + (or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + good := true; + else + good := false; + end if; + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-3)/4)*4; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + HREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => true, + smath => true); + if igood then -- We did not get another error + if not ((i = -1) -- We read everything + and ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then + report "fixed_pkg:" + & "HREAD(sfixed): Vector truncated." + severity error; + else + if (or_reduce (slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "fixed_pkg:" + & "HREAD(sfixed): Vector truncated" + severity warning; + end if; + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end if; + end if; + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-3)/4)*4; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + HREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => false, + smath => true); + if (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_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + good := true; + else + good := false; + end if; + end procedure HREAD; + + function to_string (value : UNRESOLVED_ufixed) return STRING is + variable s : STRING(1 to value'length +1) := (others => ' '); + variable subval : UNRESOLVED_ufixed (value'high downto -1); + variable sindx : INTEGER; + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + if value(value'high) = 'Z' then + return to_string (resize (sfixed(value), 0, value'low)); + else + return to_string (resize (value, 0, value'low)); + end if; + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_string(subval); + else + return to_string (resize (value, value'high, -1)); + end if; + 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 s; + end if; + end if; + end function to_string; + + function to_string (value : UNRESOLVED_sfixed) return STRING is + variable s : STRING(1 to value'length + 1) := (others => ' '); + variable subval : UNRESOLVED_sfixed (value'high downto -1); + 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)); + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_string(subval); + else + return to_string (resize (value, value'high, -1)); + end if; + 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 s; + end if; + end if; + end function to_string; + + function to_ostring (value : UNRESOLVED_ufixed) return STRING is + constant lne : INTEGER := (-VALUE'low+2)/3; + variable subval : UNRESOLVED_ufixed (value'high downto -3); + variable lpad : STD_ULOGIC_VECTOR (0 to (lne*3 + VALUE'low) -1); + variable slv : STD_ULOGIC_VECTOR (value'length-1 downto 0); + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + if value(value'high) = 'Z' then + return to_ostring (resize (sfixed(value), 2, value'low)); + else + return to_ostring (resize (value, 2, value'low)); + end if; + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_ostring(subval); + else + return to_ostring (resize (value, value'high, -3)); + end if; + else + slv := to_sulv (value); + if Is_X (value (value'low)) then + lpad := (others => value (value'low)); + else + lpad := (others => '0'); + end if; + return to_ostring(slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_ostring(slv(slv'high-VALUE'high-1 downto 0) & lpad); + end if; + end if; + end function to_ostring; + + function to_hstring (value : UNRESOLVED_ufixed) return STRING is + constant lne : INTEGER := (-VALUE'low+3)/4; + variable subval : UNRESOLVED_ufixed (value'high downto -4); + variable lpad : STD_ULOGIC_VECTOR (0 to (lne*4 + VALUE'low) -1); + variable slv : STD_ULOGIC_VECTOR (value'length-1 downto 0); + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + if value(value'high) = 'Z' then + return to_hstring (resize (sfixed(value), 3, value'low)); + else + return to_hstring (resize (value, 3, value'low)); + end if; + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_hstring(subval); + else + return to_hstring (resize (value, value'high, -4)); + end if; + else + slv := to_sulv (value); + if Is_X (value (value'low)) then + lpad := (others => value(value'low)); + else + lpad := (others => '0'); + end if; + return to_hstring(slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_hstring(slv(slv'high-VALUE'high-1 downto 0)&lpad); + end if; + end if; + end function to_hstring; + + function to_ostring (value : UNRESOLVED_sfixed) return STRING is + constant ne : INTEGER := ((value'high+1)+2)/3; + variable pad : STD_ULOGIC_VECTOR(0 to (ne*3 - (value'high+1)) - 1); + constant lne : INTEGER := (-VALUE'low+2)/3; + variable subval : UNRESOLVED_sfixed (value'high downto -3); + variable lpad : STD_ULOGIC_VECTOR (0 to (lne*3 + VALUE'low) -1); + variable slv : STD_ULOGIC_VECTOR (VALUE'high - VALUE'low downto 0); + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_ostring (resize (value, 2, value'low)); + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_ostring(subval); + else + return to_ostring (resize (value, value'high, -3)); + end if; + else + pad := (others => value(value'high)); + slv := to_sulv (value); + if Is_X (value (value'low)) then + lpad := (others => value(value'low)); + else + lpad := (others => '0'); + end if; + return to_ostring(pad & slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_ostring(slv(slv'high-VALUE'high-1 downto 0) & lpad); + end if; + end if; + end function to_ostring; + + function to_hstring (value : UNRESOLVED_sfixed) return STRING is + constant ne : INTEGER := ((value'high+1)+3)/4; + variable pad : STD_ULOGIC_VECTOR(0 to (ne*4 - (value'high+1)) - 1); + constant lne : INTEGER := (-VALUE'low+3)/4; + variable subval : UNRESOLVED_sfixed (value'high downto -4); + variable lpad : STD_ULOGIC_VECTOR (0 to (lne*4 + VALUE'low) -1); + variable slv : STD_ULOGIC_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)); + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_hstring(subval); + else + return to_hstring (resize (value, value'high, -4)); + end if; + else + slv := to_sulv (value); + pad := (others => value(value'high)); + if Is_X (value (value'low)) then + lpad := (others => value(value'low)); + else + lpad := (others => '0'); + end if; + return to_hstring(pad & slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_hstring(slv(slv'high-VALUE'high-1 downto 0) & lpad); + 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 UNRESOLVED_ufixed is + variable result : UNRESOLVED_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_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 UNRESOLVED_ufixed is + variable result : UNRESOLVED_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_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 UNRESOLVED_ufixed is + variable result : UNRESOLVED_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_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 UNRESOLVED_sfixed is + variable result : UNRESOLVED_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_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 UNRESOLVED_sfixed is + variable result : UNRESOLVED_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_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 UNRESOLVED_sfixed is + variable result : UNRESOLVED_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_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 : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return from_string (bstring, size_res'high, size_res'low); + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return from_ostring (ostring, size_res'high, size_res'low); + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return from_hstring(hstring, size_res'high, size_res'low); + end function from_hstring; + + function from_string ( + bstring : STRING; -- binary string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return from_string (bstring, size_res'high, size_res'low); + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return from_ostring (ostring, size_res'high, size_res'low); + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return from_hstring (hstring, size_res'high, size_res'low); + end function from_hstring; + + -- purpose: Calculate the string boundaries + procedure calculate_string_boundry ( + arg : in STRING; -- input string + left_index : out INTEGER; -- left + right_index : out INTEGER) is -- right + -- examples "10001.111" would return +4, -3 + -- "07X.44" would return +2, -2 (then the octal routine would multiply) + -- "A_B_._C" would return +1, -1 (then the hex routine would multiply) + alias xarg : STRING (arg'length downto 1) is arg; -- make it downto range + variable l, r : INTEGER; -- internal indexes + variable founddot : BOOLEAN := false; + begin + if arg'length > 0 then + l := xarg'high - 1; + r := 0; + for i in xarg'range loop + if xarg(i) = '_' then + if r = 0 then + l := l - 1; + else + r := r + 1; + end if; + elsif xarg(i) = ' ' or xarg(i) = NBSP or xarg(i) = HT then + report "fixed_pkg:" + & "Found a space in the input STRING " & xarg + severity error; + elsif xarg(i) = '.' then + if founddot then + report "fixed_pkg:" + & "Found two binary points in input string " & xarg + severity error; + else + l := l - i; + r := -i + 1; + founddot := true; + end if; + end if; + end loop; + left_index := l; + right_index := r; + else + left_index := 0; + right_index := 0; + end if; + end procedure calculate_string_boundry; + + -- Direct conversion functions. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100"); -- 6.5 + -- In this case the "." is not optional, and the size of + -- the output must match exactly. + function from_string ( + bstring : STRING) -- binary string + return UNRESOLVED_ufixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (bstring, left_index, right_index); + return from_string (bstring, left_index, right_index); + end function from_string; + + -- Direct octal and hex conversion functions. In this case + -- the string lengths must match. Example: + -- signal sf1 := sfixed (5 downto -3); + -- sf1 <= from_ostring ("71.4") -- -6.5 + function from_ostring ( + ostring : STRING) -- Octal string + return UNRESOLVED_ufixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (ostring, left_index, right_index); + return from_ostring (ostring, ((left_index+1)*3)-1, right_index*3); + end function from_ostring; + + function from_hstring ( + hstring : STRING) -- hex string + return UNRESOLVED_ufixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (hstring, left_index, right_index); + return from_hstring (hstring, ((left_index+1)*4)-1, right_index*4); + end function from_hstring; + + function from_string ( + bstring : STRING) -- binary string + return UNRESOLVED_sfixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (bstring, left_index, right_index); + return from_string (bstring, left_index, right_index); + end function from_string; + + function from_ostring ( + ostring : STRING) -- Octal string + return UNRESOLVED_sfixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (ostring, left_index, right_index); + return from_ostring (ostring, ((left_index+1)*3)-1, right_index*3); + end function from_ostring; + + function from_hstring ( + hstring : STRING) -- hex string + return UNRESOLVED_sfixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (hstring, left_index, right_index); + return from_hstring (hstring, ((left_index+1)*4)-1, right_index*4); + end function from_hstring; +-- pragma synthesis_on +-- rtl_synthesis on + -- IN VHDL-2006 std_logic_vector is a subtype of std_ulogic_vector, so these + -- extra functions are needed for compatability. + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed is + begin + return to_ufixed ( + arg => std_ulogic_vector (arg), + left_index => left_index, + right_index => right_index); + end function to_ufixed; + + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_ufixed) -- for size only + return UNRESOLVED_ufixed is + begin + return to_ufixed ( + arg => std_ulogic_vector (arg), + size_res => size_res); + end function to_ufixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed is + begin + return to_sfixed ( + arg => std_ulogic_vector (arg), + left_index => left_index, + right_index => right_index); + end function to_sfixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_sfixed) -- for size only + return UNRESOLVED_sfixed is + begin + return to_sfixed ( + arg => std_ulogic_vector (arg), + size_res => size_res); + end function to_sfixed; + + -- unsigned fixed point + function to_UFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_ufixed is + begin + return to_UFix ( + arg => std_ulogic_vector (arg), + width => width, + fraction => fraction); + 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 UNRESOLVED_sfixed is + begin + return to_SFix ( + arg => std_ulogic_vector (arg), + width => width, + fraction => fraction); + end function to_SFix; + +end package body fixed_pkg; diff --git a/ieee_proposed/rtl/float_pkg_c.vhd b/ieee_proposed/rtl/float_pkg_c.vhd new file mode 100644 index 0000000..8abbff6 --- /dev/null +++ b/ieee_proposed/rtl/float_pkg_c.vhd @@ -0,0 +1,7190 @@ +-- -------------------------------------------------------------------- +-- "float_pkg" package contains functions for floating point math. +-- Please see the documentation for the floating 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_float_types.all; +-- use ieee_proposed.fixed_pkg.all; +-- use ieee_proposed.float_pkg.all; +-- +-- This verison is designed to work with the VHDL-93 compilers. Please +-- note the "%%%" comments. These are where we diverge from the +-- VHDL-200X LRM. +-- +-- -------------------------------------------------------------------- +-- Version : $Revision: 2.0 $ +-- Date : $Date: 2009/01/27 20:45:30 $ +-- -------------------------------------------------------------------- + +use STD.TEXTIO.all; +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.all; +library ieee_proposed; +use ieee_proposed.fixed_float_types.all; +use ieee_proposed.fixed_pkg.all; + +package float_pkg is +-- generic ( + -- Defaults for sizing routines, when you do a "to_float" this will be + -- the default size. Example float32 would be 8 and 23 (8 downto -23) + constant float_exponent_width : NATURAL := 8; + constant float_fraction_width : NATURAL := 23; + -- Rounding algorithm, "round_nearest" is default, other valid values + -- are "round_zero" (truncation), "round_inf" (round up), and + -- "round_neginf" (round down) + constant float_round_style : round_type := round_nearest; + -- Denormal numbers (very small numbers near zero) true or false + constant float_denormalize : BOOLEAN := true; + -- Turns on NAN processing (invalid numbers and overflow) true of false + constant float_check_error : BOOLEAN := true; + -- Guard bits are added to the bottom of every operation for rounding. + -- any natural number (including 0) are valid. + constant float_guard_bits : NATURAL := 3; + -- If TRUE, then turn off warnings on "X" propagation + constant no_warning : BOOLEAN := (false + ); + + -- Author David Bishop (dbishop@vhdl.org) + + -- Note that the size of the vector is not defined here, but in + -- the package which calls this one. + type UNRESOLVED_float is array (INTEGER range <>) of STD_ULOGIC; -- main type + subtype U_float is UNRESOLVED_float; + + subtype float is UNRESOLVED_float; + ----------------------------------------------------------------------------- + -- Use the float type to define your own floating point numbers. + -- There must be a negative index or the packages will error out. + -- Minimum supported is "subtype float7 is float (3 downto -3);" + -- "subtype float16 is float (6 downto -9);" is probably the smallest + -- practical one to use. + ----------------------------------------------------------------------------- + + -- IEEE 754 single precision + subtype UNRESOLVED_float32 is UNRESOLVED_float (8 downto -23); +-- alias U_float32 is UNRESOLVED_float32; + subtype float32 is float (8 downto -23); + ----------------------------------------------------------------------------- + -- IEEE-754 single precision floating point. This is a "float" + -- in C, and a FLOAT in Fortran. The exponent is 8 bits wide, and + -- the fraction is 23 bits wide. This format can hold roughly 7 decimal + -- digits. Infinity is 2**127 = 1.7E38 in this number system. + -- The bit representation is as follows: + -- 1 09876543 21098765432109876543210 + -- 8 76543210 12345678901234567890123 + -- 0 00000000 00000000000000000000000 + -- 8 7 0 -1 -23 + -- +/- exp. fraction + ----------------------------------------------------------------------------- + + -- IEEE 754 double precision + subtype UNRESOLVED_float64 is UNRESOLVED_float (11 downto -52); +-- alias U_float64 is UNRESOLVED_float64; + subtype float64 is float (11 downto -52); + ----------------------------------------------------------------------------- + -- IEEE-754 double precision floating point. This is a "double float" + -- in C, and a FLOAT*8 in Fortran. The exponent is 11 bits wide, and + -- the fraction is 52 bits wide. This format can hold roughly 15 decimal + -- digits. Infinity is 2**2047 in this number system. + -- The bit representation is as follows: + -- 3 21098765432 1098765432109876543210987654321098765432109876543210 + -- 1 09876543210 1234567890123456789012345678901234567890123456789012 + -- S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + -- 11 10 0 -1 -52 + -- +/- exponent fraction + ----------------------------------------------------------------------------- + + -- IEEE 854 & C extended precision + subtype UNRESOLVED_float128 is UNRESOLVED_float (15 downto -112); +-- alias U_float128 is UNRESOLVED_float128; + subtype float128 is float (15 downto -112); + ----------------------------------------------------------------------------- + -- The 128 bit floating point number is "long double" in C (on + -- some systems this is a 70 bit floating point number) and FLOAT*32 + -- in Fortran. The exponent is 15 bits wide and the fraction is 112 + -- bits wide. This number can handle approximately 33 decimal digits. + -- Infinity is 2**32,767 in this number system. + ----------------------------------------------------------------------------- + + -- purpose: Checks for a valid floating point number + type valid_fpstate is (nan, -- Signaling NaN (C FP_NAN) + quiet_nan, -- Quiet NaN (C FP_NAN) + neg_inf, -- Negative infinity (C FP_INFINITE) + neg_normal, -- negative normalized nonzero + neg_denormal, -- negative denormalized (FP_SUBNORMAL) + neg_zero, -- -0 (C FP_ZERO) + pos_zero, -- +0 (C FP_ZERO) + pos_denormal, -- Positive denormalized (FP_SUBNORMAL) + pos_normal, -- positive normalized nonzero + pos_inf, -- positive infinity + isx); -- at least one input is unknown + + -- This deferred constant will tell you if the package body is synthesizable + -- or implemented as real numbers. + constant fphdlsynth_or_real : BOOLEAN; -- deferred constant + + -- Returns the class which X falls into + function Classfp ( + x : UNRESOLVED_float; -- floating point input + check_error : BOOLEAN := float_check_error) -- check for errors + return valid_fpstate; + + -- Arithmetic functions, these operators do not require parameters. + function "abs" (arg : UNRESOLVED_float) return UNRESOLVED_float; + function "-" (arg : UNRESOLVED_float) return UNRESOLVED_float; + + -- These allows the base math functions to use the default values + -- of their parameters. Thus they do full IEEE floating point. + + function "+" (l, r : UNRESOLVED_float) return UNRESOLVED_float; + function "-" (l, r : UNRESOLVED_float) return UNRESOLVED_float; + function "*" (l, r : UNRESOLVED_float) return UNRESOLVED_float; + function "/" (l, r : UNRESOLVED_float) return UNRESOLVED_float; +-- function "rem" (l, r : UNRESOLVED_float) return UNRESOLVED_float; +-- function "mod" (l, r : UNRESOLVED_float) return UNRESOLVED_float; + + -- Basic parameter list + -- round_style - Selects the rounding algorithm to use + -- guard - extra bits added to the end if the operation to add precision + -- check_error - When "false" turns off NAN and overflow checks + -- denormalize - When "false" turns off denormal number processing + + function add ( + l, r : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + function subtract ( + l, r : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + function multiply ( + l, r : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + function divide ( + l, r : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + +-- function remainder ( +-- l, r : UNRESOLVED_float; -- floating point input +-- constant round_style : round_type := float_round_style; -- rounding option +-- constant guard : NATURAL := float_guard_bits; -- number of guard bits +-- constant check_error : BOOLEAN := float_check_error; -- check for errors +-- constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP +-- return UNRESOLVED_float; + +-- function modulo ( +-- l, r : UNRESOLVED_float; -- floating point input +-- constant round_style : round_type := float_round_style; -- rounding option +-- constant guard : NATURAL := float_guard_bits; -- number of guard bits +-- constant check_error : BOOLEAN := float_check_error; -- check for errors +-- constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP +-- return UNRESOLVED_float; + + -- reciprocal + function reciprocal ( + arg : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + function dividebyp2 ( + l, r : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + -- Multiply accumulate result = l*r + c + function mac ( + l, r, c : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + -- Square root (all 754 based implementations need this) +-- function sqrt ( +-- arg : UNRESOLVED_float; -- floating point input +-- constant round_style : round_type := float_round_style; +-- constant guard : NATURAL := float_guard_bits; +-- constant check_error : BOOLEAN := float_check_error; +-- constant denormalize : BOOLEAN := float_denormalize) +-- return UNRESOLVED_float; + + function Is_Negative (arg : UNRESOLVED_float) return BOOLEAN; + + ----------------------------------------------------------------------------- + -- compare functions + -- =, /=, >=, <=, <, >, maximum, minimum + + function eq ( -- equal = + l, r : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + + function ne ( -- not equal /= + l, r : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + + function lt ( -- less than < + l, r : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + + function gt ( -- greater than > + l, r : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + + function le ( -- less than or equal to <= + l, r : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + + function ge ( -- greater than or equal to >= + l, r : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + + -- Need to overload the default versions of these + function "=" (l, r : UNRESOLVED_float) return BOOLEAN; + function "/=" (l, r : UNRESOLVED_float) return BOOLEAN; + function ">=" (l, r : UNRESOLVED_float) return BOOLEAN; + function "<=" (l, r : UNRESOLVED_float) return BOOLEAN; + function ">" (l, r : UNRESOLVED_float) return BOOLEAN; + function "<" (l, r : UNRESOLVED_float) return BOOLEAN; + + function \?=\ (l, r : UNRESOLVED_float) return STD_ULOGIC; + function \?/=\ (l, r : UNRESOLVED_float) return STD_ULOGIC; + function \?>\ (l, r : UNRESOLVED_float) return STD_ULOGIC; + function \?>=\ (l, r : UNRESOLVED_float) return STD_ULOGIC; + function \?<\ (l, r : UNRESOLVED_float) return STD_ULOGIC; + function \?<=\ (l, r : UNRESOLVED_float) return STD_ULOGIC; + + function std_match (l, r : UNRESOLVED_float) return BOOLEAN; + function find_rightmost (arg : UNRESOLVED_float; y : STD_ULOGIC) + return INTEGER; + function find_leftmost (arg : UNRESOLVED_float; y : STD_ULOGIC) + return INTEGER; + function maximum (l, r : UNRESOLVED_float) return UNRESOLVED_float; + function minimum (l, r : UNRESOLVED_float) return UNRESOLVED_float; + + -- conversion functions + -- Converts one floating point number into another. + + function resize ( + arg : UNRESOLVED_float; -- Floating point input + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + function resize ( + arg : UNRESOLVED_float; -- Floating point input + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + function to_float32 ( + arg : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float32; + + function to_float64 ( + arg : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float64; + + function to_float128 ( + arg : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float128; + + -- Converts an fp into an SLV (needed for synthesis) + function to_slv (arg : UNRESOLVED_float) return STD_LOGIC_VECTOR; +-- alias to_StdLogicVector is to_slv [UNRESOLVED_float return STD_LOGIC_VECTOR]; +-- alias to_Std_Logic_Vector is to_slv [UNRESOLVED_float return STD_LOGIC_VECTOR]; + + -- Converts an fp into an std_ulogic_vector (sulv) + function to_sulv (arg : UNRESOLVED_float) return STD_ULOGIC_VECTOR; +-- alias to_StdULogicVector is to_sulv [UNRESOLVED_float return STD_ULOGIC_VECTOR]; +-- alias to_Std_ULogic_Vector is to_sulv [UNRESOLVED_float return STD_ULOGIC_VECTOR]; + + -- std_ulogic_vector to float + function to_float ( + arg : STD_ULOGIC_VECTOR; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction + return UNRESOLVED_float; + + -- Integer to float + function to_float ( + arg : INTEGER; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return UNRESOLVED_float; + + -- real to float + function to_float ( + arg : REAL; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + -- unsigned to float + function to_float ( + arg : UNSIGNED; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return UNRESOLVED_float; + + -- signed to float + function to_float ( + arg : SIGNED; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return UNRESOLVED_float; + + -- unsigned fixed point to float + function to_float ( + arg : UNRESOLVED_ufixed; -- unsigned fixed point input + constant exponent_width : NATURAL := float_exponent_width; -- width of exponent + constant fraction_width : NATURAL := float_fraction_width; -- width of fraction + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions + return UNRESOLVED_float; + + -- signed fixed point to float + function to_float ( + arg : UNRESOLVED_sfixed; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- rounding option + return UNRESOLVED_float; + + -- size_res functions + -- Integer to float + function to_float ( + arg : INTEGER; + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style) -- rounding option + return UNRESOLVED_float; + + -- real to float + function to_float ( + arg : REAL; + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + -- unsigned to float + function to_float ( + arg : UNSIGNED; + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style) -- rounding option + return UNRESOLVED_float; + + -- signed to float + function to_float ( + arg : SIGNED; + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style) -- rounding option + return UNRESOLVED_float; + + -- sulv to float + function to_float ( + arg : STD_ULOGIC_VECTOR; + size_res : UNRESOLVED_float) + return UNRESOLVED_float; + + -- unsigned fixed point to float + function to_float ( + arg : UNRESOLVED_ufixed; -- unsigned fixed point input + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions + return UNRESOLVED_float; + + -- signed fixed point to float + function to_float ( + arg : UNRESOLVED_sfixed; + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- rounding option + return UNRESOLVED_float; + + -- float to unsigned + function to_unsigned ( + arg : UNRESOLVED_float; -- floating point input + constant size : NATURAL; -- length of output + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error) -- check for errors + return UNSIGNED; + + -- float to signed + function to_signed ( + arg : UNRESOLVED_float; -- floating point input + constant size : NATURAL; -- length of output + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error) -- check for errors + return SIGNED; + + -- purpose: Converts a float to unsigned fixed point + function to_ufixed ( + arg : UNRESOLVED_float; -- fp input + constant left_index : INTEGER; -- integer part + constant right_index : INTEGER; -- fraction part + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate + constant round_style : fixed_round_style_type := fixed_round_style; -- rounding + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return UNRESOLVED_ufixed; + + -- float to signed fixed point + function to_sfixed ( + arg : UNRESOLVED_float; -- fp input + constant left_index : INTEGER; -- integer part + constant right_index : INTEGER; -- fraction part + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate + constant round_style : fixed_round_style_type := fixed_round_style; -- rounding + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return UNRESOLVED_sfixed; + + -- size_res versions + -- float to unsigned + function to_unsigned ( + arg : UNRESOLVED_float; -- floating point input + size_res : UNSIGNED; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error) -- check for errors + return UNSIGNED; + + -- float to signed + function to_signed ( + arg : UNRESOLVED_float; -- floating point input + size_res : SIGNED; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error) -- check for errors + return SIGNED; + + -- purpose: Converts a float to unsigned fixed point + function to_ufixed ( + arg : UNRESOLVED_float; -- fp input + size_res : UNRESOLVED_ufixed; + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate + constant round_style : fixed_round_style_type := fixed_round_style; -- rounding + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return UNRESOLVED_ufixed; + + -- float to signed fixed point + function to_sfixed ( + arg : UNRESOLVED_float; -- fp input + size_res : UNRESOLVED_sfixed; + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate + constant round_style : fixed_round_style_type := fixed_round_style; -- rounding + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return UNRESOLVED_sfixed; + + -- float to real + function to_real ( + arg : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return REAL; + + -- float to integer + function to_integer ( + arg : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error) -- check for errors + return INTEGER; + + -- For Verilog compatability + function realtobits (arg : REAL) return STD_ULOGIC_VECTOR; + function bitstoreal (arg : STD_ULOGIC_VECTOR) return REAL; + + -- Maps metalogical values + function to_01 ( + arg : UNRESOLVED_float; -- floating point input + XMAP : STD_LOGIC := '0') + return UNRESOLVED_float; + + function Is_X (arg : UNRESOLVED_float) return BOOLEAN; + function to_X01 (arg : UNRESOLVED_float) return UNRESOLVED_float; + function to_X01Z (arg : UNRESOLVED_float) return UNRESOLVED_float; + function to_UX01 (arg : UNRESOLVED_float) return UNRESOLVED_float; + + -- These two procedures were copied out of the body because they proved + -- very useful for vendor specific algorithm development + -- Break_number converts a floating point number into it's parts + -- Exponent is biased by -1 + + procedure break_number ( + arg : in UNRESOLVED_float; + denormalize : in BOOLEAN := float_denormalize; + check_error : in BOOLEAN := float_check_error; + fract : out UNSIGNED; + expon : out SIGNED; -- NOTE: Add 1 to get the real exponent! + sign : out STD_ULOGIC); + + procedure break_number ( + arg : in UNRESOLVED_float; + denormalize : in BOOLEAN := float_denormalize; + check_error : in BOOLEAN := float_check_error; + fract : out ufixed; -- a number between 1.0 and 2.0 + expon : out SIGNED; -- NOTE: Add 1 to get the real exponent! + sign : out STD_ULOGIC); + + -- Normalize takes a fraction and and exponent and converts them into + -- a floating point number. Does the shifting and the rounding. + -- Exponent is assumed to be biased by -1 + + function normalize ( + fract : UNSIGNED; -- fraction, unnormalized + expon : SIGNED; -- exponent - 1, normalized + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent + constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return UNRESOLVED_float; + + -- Exponent is assumed to be biased by -1 + function normalize ( + fract : ufixed; -- unsigned fixed point + expon : SIGNED; -- exponent - 1, normalized + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent + constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return UNRESOLVED_float; + + function normalize ( + fract : UNSIGNED; -- unsigned + expon : SIGNED; -- exponent - 1, normalized + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + size_res : UNRESOLVED_float; -- used for sizing only + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return UNRESOLVED_float; + + -- Exponent is assumed to be biased by -1 + function normalize ( + fract : ufixed; -- unsigned fixed point + expon : SIGNED; -- exponent - 1, normalized + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + size_res : UNRESOLVED_float; -- used for sizing only + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return UNRESOLVED_float; + + -- overloaded versions + function "+" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; + function "+" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; + function "+" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; + function "+" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; + function "-" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; + function "-" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; + function "-" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; + function "-" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; + function "*" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; + function "*" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; + function "*" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; + function "*" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; + function "/" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; + function "/" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; + function "/" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; + function "/" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; +-- function "rem" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; +-- function "rem" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; +-- function "rem" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; +-- function "rem" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; +-- function "mod" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; +-- function "mod" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; +-- function "mod" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; +-- function "mod" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; + + -- overloaded compare functions + function "=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; + function "/=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; + function ">=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; + function "<=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; + function ">" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; + function "<" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; + function "=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; + function "/=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; + function ">=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; + function "<=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; + function ">" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; + function "<" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; + function "=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; + function "/=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; + function ">=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; + function "<=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; + function ">" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; + function "<" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; + function "=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; + function "/=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; + function ">=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; + function "<=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; + function ">" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; + function "<" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; + function \?=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; + function \?/=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; + function \?>\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; + function \?>=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; + function \?<\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; + function \?<=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; + function \?=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; + function \?/=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; + function \?>\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; + function \?>=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; + function \?<\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; + function \?<=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; + function \?=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; + function \?/=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; + function \?>\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; + function \?>=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; + function \?<\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; + function \?<=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; + function \?=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; + function \?/=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; + function \?>\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; + function \?>=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; + function \?<\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; + function \?<=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; + -- minimum and maximum overloads + function maximum (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; + function minimum (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; + function maximum (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; + function minimum (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; + function maximum (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; + function minimum (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; + function maximum (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; + function minimum (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; +---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + + function "not" (l : UNRESOLVED_float) return UNRESOLVED_float; + function "and" (l, r : UNRESOLVED_float) return UNRESOLVED_float; + function "or" (l, r : UNRESOLVED_float) return UNRESOLVED_float; + function "nand" (l, r : UNRESOLVED_float) return UNRESOLVED_float; + function "nor" (l, r : UNRESOLVED_float) return UNRESOLVED_float; + function "xor" (l, r : UNRESOLVED_float) return UNRESOLVED_float; + function "xnor" (l, r : UNRESOLVED_float) return UNRESOLVED_float; + -- Vector and std_ulogic functions, same as functions in numeric_std + function "and" (l : STD_ULOGIC; r : UNRESOLVED_float) + return UNRESOLVED_float; + function "and" (l : UNRESOLVED_float; r : STD_ULOGIC) + return UNRESOLVED_float; + function "or" (l : STD_ULOGIC; r : UNRESOLVED_float) + return UNRESOLVED_float; + function "or" (l : UNRESOLVED_float; r : STD_ULOGIC) + return UNRESOLVED_float; + function "nand" (l : STD_ULOGIC; r : UNRESOLVED_float) + return UNRESOLVED_float; + function "nand" (l : UNRESOLVED_float; r : STD_ULOGIC) + return UNRESOLVED_float; + function "nor" (l : STD_ULOGIC; r : UNRESOLVED_float) + return UNRESOLVED_float; + function "nor" (l : UNRESOLVED_float; r : STD_ULOGIC) + return UNRESOLVED_float; + function "xor" (l : STD_ULOGIC; r : UNRESOLVED_float) + return UNRESOLVED_float; + function "xor" (l : UNRESOLVED_float; r : STD_ULOGIC) + return UNRESOLVED_float; + function "xnor" (l : STD_ULOGIC; r : UNRESOLVED_float) + return UNRESOLVED_float; + function "xnor" (l : UNRESOLVED_float; r : STD_ULOGIC) + return UNRESOLVED_float; + -- Reduction operators, same as numeric_std functions + function and_reduce (l : UNRESOLVED_float) return STD_ULOGIC; + function nand_reduce (l : UNRESOLVED_float) return STD_ULOGIC; + function or_reduce (l : UNRESOLVED_float) return STD_ULOGIC; + function nor_reduce (l : UNRESOLVED_float) return STD_ULOGIC; + function xor_reduce (l : UNRESOLVED_float) return STD_ULOGIC; + function xnor_reduce (l : UNRESOLVED_float) return STD_ULOGIC; + + -- Note: "sla", "sra", "sll", "slr", "rol" and "ror" not implemented. + + ----------------------------------------------------------------------------- + -- Recommended Functions from the IEEE 754 Appendix + ----------------------------------------------------------------------------- + + -- returns x with the sign of y. + function Copysign (x, y : UNRESOLVED_float) return UNRESOLVED_float; + + -- Returns y * 2**n for integral values of N without computing 2**n + function Scalb ( + y : UNRESOLVED_float; -- floating point input + N : INTEGER; -- exponent to add + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + -- Returns y * 2**n for integral values of N without computing 2**n + function Scalb ( + y : UNRESOLVED_float; -- floating point input + N : SIGNED; -- exponent to add + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float; + + -- returns the unbiased exponent of x + function Logb (x : UNRESOLVED_float) return INTEGER; + function Logb (x : UNRESOLVED_float) return SIGNED; + + -- returns the next representable neighbor of x in the direction toward y +-- function Nextafter ( +-- x, y : UNRESOLVED_float; -- floating point input +-- constant check_error : BOOLEAN := float_check_error; -- check for errors +-- constant denormalize : BOOLEAN := float_denormalize) +-- return UNRESOLVED_float; + + -- Returns TRUE if X is unordered with Y. + function Unordered (x, y : UNRESOLVED_float) return BOOLEAN; + function Finite (x : UNRESOLVED_float) return BOOLEAN; + function Isnan (x : UNRESOLVED_float) return BOOLEAN; + + -- Function to return constants. + function zerofp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float; + function nanfp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float; + function qnanfp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float; + function pos_inffp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float; + function neg_inffp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float; + function neg_zerofp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float; + -- size_res versions + function zerofp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float; + function nanfp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float; + function qnanfp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float; + function pos_inffp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float; + function neg_inffp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float; + function neg_zerofp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float; + + -- =========================================================================== + -- string and textio Functions + -- =========================================================================== +-- rtl_synthesis off +-- pragma synthesis_off + -- writes S:EEEE:FFFFFFFF + procedure WRITE ( + L : inout LINE; -- access type (pointer) + VALUE : in UNRESOLVED_float; -- value to write + JUSTIFIED : in SIDE := right; -- which side to justify text + FIELD : in WIDTH := 0); -- width of field + + -- Reads SEEEEFFFFFFFF, "." and ":" are ignored + procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float); + procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float; + GOOD : out BOOLEAN); + + alias BREAD is READ [LINE, UNRESOLVED_float, BOOLEAN]; + alias BREAD is READ [LINE, UNRESOLVED_float]; + alias BWRITE is WRITE [LINE, UNRESOLVED_float, SIDE, WIDTH]; + alias BINARY_READ is READ [LINE, UNRESOLVED_FLOAT, BOOLEAN]; + alias BINARY_READ is READ [LINE, UNRESOLVED_FLOAT]; + alias BINARY_WRITE is WRITE [LINE, UNRESOLVED_float, SIDE, WIDTH]; + + procedure OWRITE ( + L : inout LINE; -- access type (pointer) + VALUE : in UNRESOLVED_float; -- value to write + JUSTIFIED : in SIDE := right; -- which side to justify text + FIELD : in WIDTH := 0); -- width of field + + -- Octal read with padding, no separators used + procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float); + procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float; + GOOD : out BOOLEAN); + alias OCTAL_READ is OREAD [LINE, UNRESOLVED_FLOAT, BOOLEAN]; + alias OCTAL_READ is OREAD [LINE, UNRESOLVED_FLOAT]; + alias OCTAL_WRITE is OWRITE [LINE, UNRESOLVED_FLOAT, SIDE, WIDTH]; + + -- Hex write with padding, no separators + procedure HWRITE ( + L : inout LINE; -- access type (pointer) + VALUE : in UNRESOLVED_float; -- value to write + JUSTIFIED : in SIDE := right; -- which side to justify text + FIELD : in WIDTH := 0); -- width of field + + -- Hex read with padding, no separators used + procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float); + procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float; + GOOD : out BOOLEAN); + alias HEX_READ is HREAD [LINE, UNRESOLVED_FLOAT, BOOLEAN]; + alias HEX_READ is HREAD [LINE, UNRESOLVED_FLOAT]; + alias HEX_WRITE is HWRITE [LINE, UNRESOLVED_FLOAT, SIDE, WIDTH]; + + -- returns "S:EEEE:FFFFFFFF" + function to_string (value : UNRESOLVED_float) return STRING; + alias TO_BSTRING is TO_STRING [UNRESOLVED_FLOAT return STRING]; + alias TO_BINARY_STRING is TO_STRING [UNRESOLVED_FLOAT return STRING]; + + -- Returns a HEX string, with padding + function to_hstring (value : UNRESOLVED_float) return STRING; + alias TO_HEX_STRING is TO_HSTRING [UNRESOLVED_FLOAT return STRING]; + + -- Returns and octal string, with padding + function to_ostring (value : UNRESOLVED_float) return STRING; + alias TO_OCTAL_STRING is TO_OSTRING [UNRESOLVED_FLOAT return STRING]; + + function from_string ( + bstring : STRING; -- binary string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return UNRESOLVED_float; + alias from_bstring is from_string [STRING, NATURAL, NATURAL + return UNRESOLVED_float]; + alias from_binary_string is from_string [STRING, NATURAL, NATURAL + return UNRESOLVED_float]; + function from_ostring ( + ostring : STRING; -- Octal string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return UNRESOLVED_float; + alias from_octal_string is from_ostring [STRING, NATURAL, NATURAL + return UNRESOLVED_float]; + + function from_hstring ( + hstring : STRING; -- hex string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return UNRESOLVED_float; + alias from_hex_string is from_hstring [STRING, NATURAL, NATURAL + return UNRESOLVED_float]; + + function from_string ( + bstring : STRING; -- binary string + size_res : UNRESOLVED_float) -- used for sizing only + return UNRESOLVED_float; + alias from_bstring is from_string [STRING, UNRESOLVED_float + return UNRESOLVED_float]; + alias from_binary_string is from_string [STRING, UNRESOLVED_float + return UNRESOLVED_float]; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : UNRESOLVED_float) -- used for sizing only + return UNRESOLVED_float; + alias from_octal_string is from_ostring [STRING, UNRESOLVED_float + return UNRESOLVED_float]; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : UNRESOLVED_float) -- used for sizing only + return UNRESOLVED_float; + alias from_hex_string is from_hstring [STRING, UNRESOLVED_float + return UNRESOLVED_float]; +-- rtl_synthesis on +-- pragma synthesis_on + -- IN VHDL-2006 std_logic_vector is a subtype of std_ulogic_vector, so these + -- extra functions are needed for compatability. + function to_float ( + arg : STD_LOGIC_VECTOR; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction + return UNRESOLVED_float; + + function to_float ( + arg : STD_LOGIC_VECTOR; + size_res : UNRESOLVED_float) + return UNRESOLVED_float; + + -- For Verilog compatability + function realtobits (arg : REAL) return STD_LOGIC_VECTOR; + function bitstoreal (arg : STD_LOGIC_VECTOR) return REAL; + +end package float_pkg; +------------------------------------------------------------------------------- +-- Proposed package body for the VHDL-200x-FT float_pkg package +-- This version is optimized for Synthesis, and not for simulation. +-- Note that there are functional differences between the synthesis and +-- simulation packages bodies. The Synthesis version is preferred. +-- This package body supplies a recommended implementation of these functions +-- Version : $Revision: 2.0 $ +-- Date : $Date: 2009/01/27 20:45:30 $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------- + +package body float_pkg is + + -- Author David Bishop (dbishop@vhdl.org) + ----------------------------------------------------------------------------- + -- type declarations + ----------------------------------------------------------------------------- + + -- This deferred constant will tell you if the package body is synthesizable + -- or implemented as real numbers, set to "true" if synthesizable. + constant fphdlsynth_or_real : BOOLEAN := true; -- deferred constant + + -- types of boundary conditions + type boundary_type is (normal, infinity, zero, denormal); + + -- null range array constant + constant NAFP : UNRESOLVED_float (0 downto 1) := (others => '0'); + constant NSLV : STD_ULOGIC_VECTOR (0 downto 1) := (others => '0'); + + -- %%% Replicated functions + -- These functions are replicated so that we don't need to reference the new + -- 2006 package std.standard, std_logic_1164 and numeric_std. + function maximum ( + l, r : INTEGER) -- inputs + return INTEGER is + begin -- function max + if l > r then return l; + else return r; + end if; + end function maximum; + + function minimum ( + l, r : INTEGER) -- inputs + return INTEGER is + begin -- function min + if l > r then return r; + else return l; + end if; + end function minimum; + + function or_reduce (arg : STD_ULOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '0'; + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) or BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := or_reduce (BUS_int (BUS_int'left downto Half)); + Lower := or_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper or Lower; + end if; + end if; + return Result; + end function or_reduce; + + function or_reduce (arg : UNSIGNED) + return STD_ULOGIC is + begin + return or_reduce (STD_ULOGIC_VECTOR (arg)); + end function or_reduce; + + function or_reduce (arg : SIGNED) + return STD_ULOGIC is + begin + return or_reduce (STD_ULOGIC_VECTOR (arg)); + end function or_reduce; + + function or_reduce (arg : STD_LOGIC_VECTOR) + return STD_ULOGIC is + begin + return or_reduce (STD_ULOGIC_VECTOR (arg)); + end function or_reduce; + + -- purpose: AND all of the bits in a vector together + -- This is a copy of the proposed "and_reduce" from 1076.3 + function and_reduce (arg : STD_ULOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '1'; + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) and BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := and_reduce (BUS_int (BUS_int'left downto Half)); + Lower := and_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper and Lower; + end if; + end if; + return Result; + end function and_reduce; + + function and_reduce (arg : UNSIGNED) + return STD_ULOGIC is + begin + return and_reduce (STD_ULOGIC_VECTOR (arg)); + end function and_reduce; + + function and_reduce (arg : SIGNED) + return STD_ULOGIC is + begin + return and_reduce (STD_ULOGIC_VECTOR (arg)); + end function and_reduce; + + function xor_reduce (arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range + begin + if (arg'length >= 1) then + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := xor_reduce (BUS_int (BUS_int'left downto Half)); + Lower := xor_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper xor Lower; + end if; + end if; + return Result; + end function xor_reduce; + + function nand_reduce(arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return not and_reduce (arg); + end function nand_reduce; + + function nor_reduce(arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return not or_reduce (arg); + end function nor_reduce; + + function xnor_reduce(arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return not xor_reduce (arg); + end function xnor_reduce; + + function find_leftmost (ARG : UNSIGNED; Y : STD_ULOGIC) + return INTEGER is + begin + for INDEX in ARG'range loop + if ARG(INDEX) = Y then + return INDEX; + end if; + end loop; + return -1; + end function find_leftmost; + + -- Match table, copied form new std_logic_1164 +-- type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; +-- constant match_logic_table : stdlogic_table := ( +-- ----------------------------------------------------- +-- -- U X 0 1 Z W L H - | | +-- ----------------------------------------------------- +-- ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1'), -- | U | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | X | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | 0 | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | 1 | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | Z | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | W | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | L | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | H | +-- ('1', '1', '1', '1', '1', '1', '1', '1', '1') -- | - | +-- ); + +-- constant no_match_logic_table : stdlogic_table := ( +-- ----------------------------------------------------- +-- -- U X 0 1 Z W L H - | | +-- ----------------------------------------------------- +-- ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '0'), -- | U | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | X | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | 0 | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | 1 | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | Z | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | W | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | L | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | H | +-- ('0', '0', '0', '0', '0', '0', '0', '0', '0') -- | - | +-- ); + + ------------------------------------------------------------------- + -- ?= functions, Similar to "std_match", but returns "std_ulogic". + ------------------------------------------------------------------- + -- %%% FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic IS + function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + variable lx, rx : STD_ULOGIC; + begin +-- return match_logic_table (l, r); + lx := to_x01(l); + rx := to_x01(r); + if lx = 'X' or rx = 'X' then + return 'X'; + elsif lx = rx then + return '1'; + else + return '0'; + end if; + end function \?=\; + function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + begin +-- return no_match_logic_table (l, r); + return not \?=\ (l, r); + end function \?/=\; + +-- -- %%% FUNCTION "?=" ( l, r : std_logic_vector ) RETURN std_ulogic IS +-- function \?=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC is +-- alias lv : STD_LOGIC_VECTOR(1 to l'length) is l; +-- alias rv : STD_LOGIC_VECTOR(1 to r'length) is r; +-- variable result, result1 : STD_ULOGIC; -- result +-- begin +-- -- Logically identical to an "=" operator. +-- if ((l'length < 1) or (r'length < 1)) then +-- report "STD_LOGIC_1164.""?="": null detected, returning X" +-- severity warning; +-- return 'X'; +-- end if; +-- if lv'length /= rv'length then +-- report "STD_LOGIC_1164.""?="": L'LENGTH /= R'LENGTH, returning X" +-- severity warning; +-- return 'X'; +-- else +-- result := '1'; +-- for i in lv'low to lv'high loop +-- result1 := match_logic_table(lv(i), rv(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 : std_ulogic_vector ) RETURN std_ulogic IS + function \?=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_ULOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_ULOGIC_VECTOR(1 to r'length) is r; + variable result, result1 : STD_ULOGIC; + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?="": null detected, returning X" + severity warning; + return 'X'; + end if; + if lv'length /= rv'length then + report "STD_LOGIC_1164.""?="": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + else + result := '1'; + for i in lv'low to lv'high loop + result1 := \?=\ (lv(i), rv(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; + + function Is_X (s : UNSIGNED) return BOOLEAN is + begin + return Is_X (STD_LOGIC_VECTOR (s)); + end function Is_X; + + function Is_X (s : SIGNED) return BOOLEAN is + begin + return Is_X (STD_LOGIC_VECTOR (s)); + end function Is_X; +-- %%% END replicated functions + + -- Special version of "minimum" to do some boundary checking + function mine (L, R : INTEGER) + return INTEGER is + begin -- function minimum + if (L = INTEGER'low or R = INTEGER'low) then + report "float_pkg:" + & " Unbounded number passed, was a literal used?" + severity error; + return 0; + end if; + return minimum (L, R); + end function mine; + + -- Generates the base number for the exponent normalization offset. + function gen_expon_base ( + constant exponent_width : NATURAL) + return SIGNED is + variable result : SIGNED (exponent_width-1 downto 0); + begin + result := (others => '1'); + result (exponent_width-1) := '0'; + return result; + end function gen_expon_base; + + -- Integer version of the "log2" command (contributed by Peter Ashenden) + function log2 (A : NATURAL) return NATURAL is + variable quotient : NATURAL; + variable result : NATURAL := 0; + begin + quotient := A / 2; + while quotient > 0 loop + quotient := quotient / 2; + result := result + 1; + end loop; + return result; + end function log2; + + -- Function similar to the ILOGB function in MATH_REAL + function log2 (A : REAL) return INTEGER is + variable Y : REAL; + variable N : INTEGER := 0; + begin + if (A = 1.0 or A = 0.0) then + return 0; + end if; + Y := A; + if(A > 1.0) then + while Y >= 2.0 loop + Y := Y / 2.0; + N := N + 1; + end loop; + return N; + end if; + -- O < Y < 1 + while Y < 1.0 loop + Y := Y * 2.0; + N := N - 1; + end loop; + return N; + end function log2; + + -- purpose: Test the boundary conditions of a Real number + procedure test_boundary ( + arg : in REAL; -- Input, converted to real + constant fraction_width : in NATURAL; -- length of FP output fraction + constant exponent_width : in NATURAL; -- length of FP exponent + constant denormalize : in BOOLEAN := true; -- Use IEEE extended FP + variable btype : out boundary_type; + variable log2i : out INTEGER + ) is + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + constant exp_min : SIGNED (12 downto 0) := + -(resize(expon_base, 13)) + 1; -- Minimum normal exponent + constant exp_ext_min : SIGNED (12 downto 0) := + exp_min - fraction_width; -- Minimum for denormal exponent + variable log2arg : INTEGER; -- log2 of argument + begin -- function test_boundary + -- Check to see if the exponent is big enough + -- Note that the argument is always an absolute value at this point. + log2arg := log2(arg); + if arg = 0.0 then + btype := zero; + elsif exponent_width > 11 then -- Exponent for Real is 11 (64 bit) + btype := normal; + else + if log2arg < to_integer(exp_min) then + if denormalize then + if log2arg < to_integer(exp_ext_min) then + btype := zero; + else + btype := denormal; + end if; + else + if log2arg < to_integer(exp_min)-1 then + btype := zero; + else + btype := normal; -- Can still represent this number + end if; + end if; + elsif exponent_width < 11 then + if log2arg > to_integer(expon_base)+1 then + btype := infinity; + else + btype := normal; + end if; + else + btype := normal; + end if; + end if; + log2i := log2arg; + end procedure test_boundary; + + -- purpose: Rounds depending on the state of the "round_style" + -- Logic taken from + -- "What Every Computer Scientist Should Know About Floating Point Arithmetic" + -- by David Goldberg (1991) + function check_round ( + fract_in : STD_ULOGIC; -- input fraction + sign : STD_ULOGIC; -- sign bit + remainder : UNSIGNED; -- remainder to round from + sticky : STD_ULOGIC := '0'; -- Sticky bit + constant round_style : round_type) -- rounding type + return BOOLEAN is + variable result : BOOLEAN; + variable or_reduced : STD_ULOGIC; + begin -- function check_round + result := false; + if (remainder'length > 0) then -- if remainder in a null array + or_reduced := or_reduce (remainder & sticky); + rounding_case : case round_style is + when round_nearest => -- Round Nearest, default mode + if remainder(remainder'high) = '1' then -- round + if (remainder'length > 1) then + if ((or_reduce (remainder(remainder'high-1 + downto remainder'low)) = '1' + or sticky = '1') + or fract_in = '1') then + -- Make the bottom bit zero if possible if we are at 1/2 + result := true; + end if; + else + result := (fract_in = '1' or sticky = '1'); + end if; + end if; + when round_inf => -- round up if positive, else truncate. + if or_reduced = '1' and sign = '0' then + result := true; + end if; + when round_neginf => -- round down if negative, else truncate. + if or_reduced = '1' and sign = '1' then + result := true; + end if; + when round_zero => -- round toward 0 Truncate + null; + end case rounding_case; + end if; + return result; + end function check_round; + + -- purpose: Rounds depending on the state of the "round_style" + -- unsigned version + procedure fp_round ( + fract_in : in UNSIGNED; -- input fraction + expon_in : in SIGNED; -- input exponent + fract_out : out UNSIGNED; -- output fraction + expon_out : out SIGNED) is -- output exponent + begin -- procedure fp_round + if and_reduce (fract_in) = '1' then -- Fraction is all "1" + expon_out := expon_in + 1; + fract_out := to_unsigned(0, fract_out'high+1); + else + expon_out := expon_in; + fract_out := fract_in + 1; + end if; + end procedure fp_round; + + -- This version of break_number doesn't call "classfp" + procedure break_number ( -- internal version + arg : in UNRESOLVED_float; + fptyp : in valid_fpstate; + denormalize : in BOOLEAN := true; + fract : out UNSIGNED; + expon : out SIGNED) is + constant fraction_width : NATURAL := -arg'low; -- length of FP output fraction + constant exponent_width : NATURAL := arg'high; -- length of FP output exponent + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable exp : SIGNED (expon'range); + begin + fract (fraction_width-1 downto 0) := + UNSIGNED (to_slv(arg(-1 downto -fraction_width))); + breakcase : case fptyp is + when pos_zero | neg_zero => + fract (fraction_width) := '0'; + exp := -expon_base; + when pos_denormal | neg_denormal => + if denormalize then + exp := -expon_base; + fract (fraction_width) := '0'; + else + exp := -expon_base - 1; + fract (fraction_width) := '1'; + end if; + when pos_normal | neg_normal | pos_inf | neg_inf => + fract (fraction_width) := '1'; + exp := SIGNED(arg(exponent_width-1 downto 0)); + exp (exponent_width-1) := not exp(exponent_width-1); + when others => + assert NO_WARNING + report "float_pkg:" + & "BREAK_NUMBER: " & + "Meta state detected in fp_break_number process" + severity warning; + -- complete the case, if a NAN goes in, a NAN comes out. + exp := (others => '1'); + fract (fraction_width) := '1'; + end case breakcase; + expon := exp; + end procedure break_number; + + -- purpose: floating point to UNSIGNED + -- Used by to_integer, to_unsigned, and to_signed functions + procedure float_to_unsigned ( + arg : in UNRESOLVED_float; -- floating point input + variable sign : out STD_ULOGIC; -- sign of output + variable frac : out UNSIGNED; -- unsigned biased output + constant denormalize : in BOOLEAN; -- turn on denormalization + constant bias : in NATURAL; -- bias for fixed point + constant round_style : in round_type) is -- rounding method + constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : INTEGER := arg'high; -- length of FP output exponent + variable fract : UNSIGNED (frac'range); -- internal version of frac + variable isign : STD_ULOGIC; -- internal version of sign + variable exp : INTEGER; -- Exponent + variable expon : SIGNED (exponent_width-1 downto 0); -- Vectorized exp + -- Base to divide fraction by + variable frac_shift : UNSIGNED (frac'high+3 downto 0); -- Fraction shifted + variable shift : INTEGER; + variable remainder : UNSIGNED (2 downto 0); + variable round : STD_ULOGIC; -- round BIT + begin + isign := to_x01(arg(arg'high)); + -- exponent /= '0', normal floating point + expon := to_01(SIGNED(arg (exponent_width-1 downto 0)), 'X'); + expon(exponent_width-1) := not expon(exponent_width-1); + exp := to_integer (expon); + -- Figure out the fraction + fract := (others => '0'); -- fill with zero + fract (fract'high) := '1'; -- Add the "1.0". + shift := (fract'high-1) - exp; + if fraction_width > fract'high then -- Can only use size-2 bits + fract (fract'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto + -fract'high))); + else -- can use all bits + fract (fract'high-1 downto fract'high-fraction_width) := + UNSIGNED (to_slv (arg(-1 downto -fraction_width))); + end if; + frac_shift := fract & "000"; + if shift < 0 then -- Overflow + fract := (others => '1'); + else + frac_shift := shift_right (frac_shift, shift); + fract := frac_shift (frac_shift'high downto 3); + remainder := frac_shift (2 downto 0); + -- round (round_zero will bypass this and truncate) + case round_style is + when round_nearest => + round := remainder(2) and + (fract (0) or (or_reduce (remainder (1 downto 0)))); + when round_inf => + round := remainder(2) and not isign; + when round_neginf => + round := remainder(2) and isign; + when others => + round := '0'; + end case; + if round = '1' then + fract := fract + 1; + end if; + end if; + frac := fract; + sign := isign; + end procedure float_to_unsigned; + + -- purpose: returns a part of a vector, this function is here because + -- or (fractr (to_integer(shiftx) downto 0)); + -- can't be synthesized in some synthesis tools. + function smallfract ( + arg : UNSIGNED; + shift : NATURAL) + return STD_ULOGIC is + variable orx : STD_ULOGIC; + begin + orx := arg(shift); + for i in arg'range loop + if i < shift then + orx := arg(i) or orx; + end if; + end loop; + return orx; + end function smallfract; + --------------------------------------------------------------------------- + -- Visible functions + --------------------------------------------------------------------------- + + -- purpose: converts the negative index to a positive one + -- negative indices are illegal in 1164 and 1076.3 + function to_sulv ( + arg : UNRESOLVED_float) -- fp vector + return STD_ULOGIC_VECTOR is + variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0); + begin -- function to_std_ulogic_vector + if arg'length < 1 then + return NSLV; + end if; + result := STD_ULOGIC_VECTOR (arg); + return result; + end function to_sulv; + + -- Converts an fp into an SLV + function to_slv (arg : UNRESOLVED_float) return STD_LOGIC_VECTOR is + begin + return std_logic_vector (to_sulv (arg)); + end function to_slv; + + -- purpose: normalizes a floating point number + -- This version assumes an "unsigned" input with + function normalize ( + fract : UNSIGNED; -- fraction, unnormalized + expon : SIGNED; -- exponent, normalized by -1 + sign : STD_ULOGIC; -- sign BIT + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent + constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return UNRESOLVED_float is + variable sfract : UNSIGNED (fract'high downto 0); -- shifted fraction + variable rfract : UNSIGNED (fraction_width-1 downto 0); -- fraction + variable exp : SIGNED (exponent_width+1 downto 0); -- exponent + variable rexp : SIGNED (exponent_width+1 downto 0); -- result exponent + variable rexpon : UNSIGNED (exponent_width-1 downto 0); -- exponent + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); -- result + variable shiftr : INTEGER; -- shift amount + variable stickyx : STD_ULOGIC; -- version of sticky + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable round, zerores, infres : BOOLEAN; + begin -- function normalize + zerores := false; + infres := false; + round := false; + shiftr := find_leftmost (to_01(fract), '1') -- Find the first "1" + - fraction_width - nguard; -- subtract the length we want + exp := resize (expon, exp'length) + shiftr; + if (or_reduce (fract) = '0') then -- Zero + zerores := true; + elsif ((exp <= -resize(expon_base, exp'length)-1) and denormalize) + or ((exp < -resize(expon_base, exp'length)-1) and not denormalize) then + if (exp >= -resize(expon_base, exp'length)-fraction_width-1) + and denormalize then + exp := -resize(expon_base, exp'length)-1; + shiftr := -to_integer (expon + expon_base); -- new shift + else -- return zero + zerores := true; + end if; + elsif (exp > expon_base-1) then -- infinity + infres := true; + end if; + if zerores then + result := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif infres then + result := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + sfract := fract srl shiftr; -- shift + if shiftr > 0 then +-- stickyx := sticky or (or_reduce(fract (shiftr-1 downto 0))); + stickyx := sticky or smallfract (fract, shiftr-1); + else + stickyx := sticky; + end if; + if nguard > 0 then + round := check_round ( + fract_in => sfract (nguard), + sign => sign, + remainder => sfract(nguard-1 downto 0), + sticky => stickyx, + round_style => round_style); + end if; + if round then + fp_round(fract_in => sfract (fraction_width-1+nguard downto nguard), + expon_in => exp(rexp'range), + fract_out => rfract, + expon_out => rexp); + else + rfract := sfract (fraction_width-1+nguard downto nguard); + rexp := exp(rexp'range); + end if; + -- result + rexpon := UNSIGNED (rexp(exponent_width-1 downto 0)); + rexpon (exponent_width-1) := not rexpon(exponent_width-1); + result (rexpon'range) := UNRESOLVED_float(rexpon); + result (-1 downto -fraction_width) := UNRESOLVED_float(rfract); + end if; + result (exponent_width) := sign; -- sign BIT + return result; + end function normalize; + + -- purpose: normalizes a floating point number + -- This version assumes a "ufixed" input + function normalize ( + fract : ufixed; -- unsigned fixed point + expon : SIGNED; -- exponent, normalized by -1 + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent + constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + variable arguns : UNSIGNED (fract'high + fraction_width + nguard + downto 0) := (others => '0'); + begin -- function normalize + arguns (arguns'high downto maximum (arguns'high-fract'length+1, 0)) := + UNSIGNED (to_slv (fract)); + result := normalize (fract => arguns, + expon => expon, + sign => sign, + sticky => sticky, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => nguard); + return result; + end function normalize; + + -- purpose: normalizes a floating point number + -- This version assumes a "ufixed" input with a "size_res" input + function normalize ( + fract : ufixed; -- unsigned fixed point + expon : SIGNED; -- exponent, normalized by -1 + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + size_res : UNRESOLVED_float; -- used for sizing only + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return UNRESOLVED_float is + constant fraction_width : NATURAL := -size_res'low; + constant exponent_width : NATURAL := size_res'high; + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + variable arguns : UNSIGNED (fract'high + fraction_width + nguard + downto 0) := (others => '0'); + begin -- function normalize + arguns (arguns'high downto maximum (arguns'high-fract'length+1, 0)) := + UNSIGNED (to_slv (fract)); + result := normalize (fract => arguns, + expon => expon, + sign => sign, + sticky => sticky, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => nguard); + return result; + end function normalize; + + -- Regular "normalize" function with a "size_res" input. + function normalize ( + fract : UNSIGNED; -- unsigned + expon : SIGNED; -- exponent - 1, normalized + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + size_res : UNRESOLVED_float; -- used for sizing only + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return UNRESOLVED_float is + begin + return normalize (fract => fract, + expon => expon, + sign => sign, + sticky => sticky, + fraction_width => -size_res'low, + exponent_width => size_res'high, + round_style => round_style, + denormalize => denormalize, + nguard => nguard); + end function normalize; + + -- Returns the class which X falls into + function Classfp ( + x : UNRESOLVED_float; -- floating point input + check_error : BOOLEAN := float_check_error) -- check for errors + return valid_fpstate is + constant fraction_width : INTEGER := -mine(x'low, x'low); -- length of FP output fraction + constant exponent_width : INTEGER := x'high; -- length of FP output exponent + variable arg : UNRESOLVED_float (exponent_width downto -fraction_width); + begin -- classfp + if (arg'length < 1 or fraction_width < 3 or exponent_width < 3 + or x'left < x'right) then + report "float_pkg:" + & "CLASSFP: " & + "Floating point number detected with a bad range" + severity error; + return isx; + end if; + -- Check for "X". + arg := to_01 (x, 'X'); + if (arg(0) = 'X') then + return isx; -- If there is an X in the number + -- Special cases, check for illegal number + elsif check_error and + (and_reduce (STD_ULOGIC_VECTOR (arg (exponent_width-1 downto 0))) + = '1') then -- Exponent is all "1". + if or_reduce (to_slv (arg (-1 downto -fraction_width))) + /= '0' then -- Fraction must be all "0" or this is not a number. + if (arg(-1) = '1') then -- From "W. Khan - IEEE standard + return nan; -- 754 binary FP Signaling nan (Not a number) + else + return quiet_nan; + end if; + -- Check for infinity + elsif arg(exponent_width) = '0' then + return pos_inf; -- Positive infinity + else + return neg_inf; -- Negative infinity + end if; + -- check for "0" + elsif or_reduce (STD_LOGIC_VECTOR (arg (exponent_width-1 downto 0))) + = '0' then -- Exponent is all "0" + if or_reduce (to_slv (arg (-1 downto -fraction_width))) + = '0' then -- Fraction is all "0" + if arg(exponent_width) = '0' then + return pos_zero; -- Zero + else + return neg_zero; + end if; + else + if arg(exponent_width) = '0' then + return pos_denormal; -- Denormal number (ieee extended fp) + else + return neg_denormal; + end if; + end if; + else + if arg(exponent_width) = '0' then + return pos_normal; -- Normal FP number + else + return neg_normal; + end if; + end if; + end function Classfp; + + procedure break_number ( + arg : in UNRESOLVED_float; + denormalize : in BOOLEAN := float_denormalize; + check_error : in BOOLEAN := float_check_error; + fract : out UNSIGNED; + expon : out SIGNED; + sign : out STD_ULOGIC) is + constant fraction_width : NATURAL := -mine(arg'low, arg'low); -- length of FP output fraction + variable fptyp : valid_fpstate; + begin + fptyp := Classfp (arg, check_error); + sign := to_x01(arg(arg'high)); + break_number ( + arg => arg, + fptyp => fptyp, + denormalize => denormalize, + fract => fract, + expon => expon); + end procedure break_number; + + procedure break_number ( + arg : in UNRESOLVED_float; + denormalize : in BOOLEAN := float_denormalize; + check_error : in BOOLEAN := float_check_error; + fract : out ufixed; -- 1 downto -fraction_width + expon : out SIGNED; -- exponent_width-1 downto 0 + sign : out STD_ULOGIC) is + constant fraction_width : NATURAL := -mine(arg'low, arg'low); -- length of FP output fraction + variable fptyp : valid_fpstate; + variable ufract : UNSIGNED (fraction_width downto 0); -- unsigned fraction + begin + fptyp := Classfp (arg, check_error); + sign := to_x01(arg(arg'high)); + break_number ( + arg => arg, + fptyp => fptyp, + denormalize => denormalize, + fract => ufract, + expon => expon); + fract (0 downto -fraction_width) := ufixed (ufract); + end procedure break_number; + + -- Arithmetic functions + function "abs" ( + arg : UNRESOLVED_float) -- floating point input + return UNRESOLVED_float is + variable result : UNRESOLVED_float (arg'range); -- result + begin + if (arg'length > 0) then + result := to_01 (arg, 'X'); + result (arg'high) := '0'; -- set the sign bit to positive + return result; + else + return NAFP; + end if; + end function "abs"; + + -- IEEE 754 "negative" function + function "-" ( + arg : UNRESOLVED_float) -- floating point input + return UNRESOLVED_float is + variable result : UNRESOLVED_float (arg'range); -- result + begin + if (arg'length > 0) then + result := to_01 (arg, 'X'); + result (arg'high) := not result (arg'high); -- invert sign bit + return result; + else + return NAFP; + end if; + end function "-"; + + -- Addition, adds two floating point numbers + function add ( + l, r : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + constant addguard : NATURAL := guard; -- add one guard bit + variable lfptype, rfptype : valid_fpstate; + variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); + variable fractl, fractr : UNSIGNED (fraction_width+1+addguard downto 0); -- fractions + variable fractc, fracts : UNSIGNED (fractl'range); -- constant and shifted variables + variable urfract, ulfract : UNSIGNED (fraction_width downto 0); + variable ufract : UNSIGNED (fraction_width+1+addguard downto 0); + variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents + variable rexpon : SIGNED (exponent_width downto 0); -- result exponent + variable shiftx : SIGNED (exponent_width downto 0); -- shift fractions + variable sign : STD_ULOGIC; -- sign of the output + variable leftright : BOOLEAN; -- left or right used + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + variable sticky : STD_ULOGIC; -- Holds precision for rounding + begin -- addition + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + lfptype := isx; + else + lfptype := classfp (l, check_error); + rfptype := classfp (r, check_error); + end if; + if (lfptype = isx or rfptype = isx) then + fpresult := (others => 'X'); + elsif (lfptype = nan or lfptype = quiet_nan or + rfptype = nan or rfptype = quiet_nan) + -- Return quiet NAN, IEEE754-1985-7.1,1 + or (lfptype = pos_inf and rfptype = neg_inf) + or (lfptype = neg_inf and rfptype = pos_inf) then + -- Return quiet NAN, IEEE754-1985-7.1,2 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (lfptype = pos_inf or rfptype = pos_inf) then -- x + inf = inf + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (lfptype = neg_inf or rfptype = neg_inf) then -- x - inf = -inf + fpresult := neg_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (lfptype = neg_zero and rfptype = neg_zero) then -- -0 + -0 = -0 + fpresult := neg_zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + lresize := resize (arg => to_x01(l), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + lfptype := classfp (lresize, false); -- errors already checked + rresize := resize (arg => to_x01(r), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rfptype := classfp (rresize, false); -- errors already checked + break_number ( + arg => lresize, + fptyp => lfptype, + denormalize => denormalize, + fract => ulfract, + expon => exponl); + fractl := (others => '0'); + fractl (fraction_width+addguard downto addguard) := ulfract; + break_number ( + arg => rresize, + fptyp => rfptype, + denormalize => denormalize, + fract => urfract, + expon => exponr); + fractr := (others => '0'); + fractr (fraction_width+addguard downto addguard) := urfract; + shiftx := (exponl(exponent_width-1) & exponl) - exponr; + if shiftx < -fractl'high then + rexpon := exponr(exponent_width-1) & exponr; + fractc := fractr; + fracts := (others => '0'); -- add zero + leftright := false; + sticky := or_reduce (fractl); + elsif shiftx < 0 then + shiftx := - shiftx; + fracts := shift_right (fractl, to_integer(shiftx)); + fractc := fractr; + rexpon := exponr(exponent_width-1) & exponr; + leftright := false; +-- sticky := or_reduce (fractl (to_integer(shiftx) downto 0)); + sticky := smallfract (fractl, to_integer(shiftx)); + elsif shiftx = 0 then + rexpon := exponl(exponent_width-1) & exponl; + sticky := '0'; + if fractr > fractl then + fractc := fractr; + fracts := fractl; + leftright := false; + else + fractc := fractl; + fracts := fractr; + leftright := true; + end if; + elsif shiftx > fractr'high then + rexpon := exponl(exponent_width-1) & exponl; + fracts := (others => '0'); -- add zero + fractc := fractl; + leftright := true; + sticky := or_reduce (fractr); + elsif shiftx > 0 then + fracts := shift_right (fractr, to_integer(shiftx)); + fractc := fractl; + rexpon := exponl(exponent_width-1) & exponl; + leftright := true; +-- sticky := or_reduce (fractr (to_integer(shiftx) downto 0)); + sticky := smallfract (fractr, to_integer(shiftx)); + end if; + -- add + fracts (0) := fracts (0) or sticky; -- Or the sticky bit into the LSB + if l(l'high) = r(r'high) then + ufract := fractc + fracts; + sign := l(l'high); + else -- signs are different + ufract := fractc - fracts; -- always positive result + if leftright then -- Figure out which sign to use + sign := l(l'high); + else + sign := r(r'high); + end if; + end if; + if or_reduce (ufract) = '0' then + sign := '0'; -- IEEE 854, 6.3, paragraph 2. + end if; + -- normalize + fpresult := normalize (fract => ufract, + expon => rexpon, + sign => sign, + sticky => sticky, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => addguard); + end if; + return fpresult; + end function add; + + -- Subtraction, Calls "add". + function subtract ( + l, r : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + variable negr : UNRESOLVED_float (r'range); -- negative version of r + begin + negr := -r; + return add (l => l, + r => negr, + round_style => round_style, + guard => guard, + check_error => check_error, + denormalize => denormalize); + end function subtract; + + -- Floating point multiply + function multiply ( + l, r : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + constant multguard : NATURAL := guard; -- guard bits + variable lfptype, rfptype : valid_fpstate; + variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); + variable fractl, fractr : UNSIGNED (fraction_width downto 0); -- fractions + variable rfract : UNSIGNED ((2*(fraction_width))+1 downto 0); -- result fraction + variable sfract : UNSIGNED (fraction_width+1+multguard downto 0); -- result fraction + variable shifty : INTEGER; -- denormal shift + variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents + variable rexpon : SIGNED (exponent_width+1 downto 0); -- result exponent + variable fp_sign : STD_ULOGIC; -- sign of result + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + variable sticky : STD_ULOGIC; -- Holds precision for rounding + begin -- multiply + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + lfptype := isx; + else + lfptype := classfp (l, check_error); + rfptype := classfp (r, check_error); + end if; + if (lfptype = isx or rfptype = isx) then + fpresult := (others => 'X'); + elsif ((lfptype = nan or lfptype = quiet_nan or + rfptype = nan or rfptype = quiet_nan)) then + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (((lfptype = pos_inf or lfptype = neg_inf) and + (rfptype = pos_zero or rfptype = neg_zero)) or + ((rfptype = pos_inf or rfptype = neg_inf) and + (lfptype = pos_zero or lfptype = neg_zero))) then -- 0 * inf + -- Return quiet NAN, IEEE754-1985-7.1,3 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (lfptype = pos_inf or rfptype = pos_inf + or lfptype = neg_inf or rfptype = neg_inf) then -- x * inf = inf + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + -- figure out the sign + fp_sign := l(l'high) xor r(r'high); -- figure out the sign + fpresult (exponent_width) := fp_sign; + else + fp_sign := l(l'high) xor r(r'high); -- figure out the sign + lresize := resize (arg => to_x01(l), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + lfptype := classfp (lresize, false); -- errors already checked + rresize := resize (arg => to_x01(r), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rfptype := classfp (rresize, false); -- errors already checked + break_number ( + arg => lresize, + fptyp => lfptype, + denormalize => denormalize, + fract => fractl, + expon => exponl); + break_number ( + arg => rresize, + fptyp => rfptype, + denormalize => denormalize, + fract => fractr, + expon => exponr); + if (rfptype = pos_denormal or rfptype = neg_denormal) then + shifty := fraction_width - find_leftmost(fractr, '1'); + fractr := shift_left (fractr, shifty); + elsif (lfptype = pos_denormal or lfptype = neg_denormal) then + shifty := fraction_width - find_leftmost(fractl, '1'); + fractl := shift_left (fractl, shifty); + else + shifty := 0; + -- Note that a denormal number * a denormal number is always zero. + end if; + -- multiply + -- add the exponents + rexpon := resize (exponl, rexpon'length) + exponr - shifty + 1; + rfract := fractl * fractr; -- Multiply the fraction + sfract := rfract (rfract'high downto + rfract'high - (fraction_width+1+multguard)); + sticky := or_reduce (rfract (rfract'high-(fraction_width+1+multguard) + downto 0)); + -- normalize + fpresult := normalize (fract => sfract, + expon => rexpon, + sign => fp_sign, + sticky => sticky, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => multguard); + end if; + return fpresult; + end function multiply; + + function short_divide ( + lx, rx : UNSIGNED) + return UNSIGNED is + -- This is a special divider for the floating point routines. + -- For a true unsigned divider, "stages" needs to = lx'high + constant stages : INTEGER := lx'high - rx'high; -- number of stages + variable partial : UNSIGNED (lx'range); + variable q : UNSIGNED (stages downto 0); + variable partial_argl : SIGNED (rx'high + 2 downto 0); + variable partial_arg : SIGNED (rx'high + 2 downto 0); + begin + partial := lx; + for i in stages downto 0 loop + partial_argl := resize ("0" & SIGNED (partial(lx'high downto i)), + partial_argl'length); + partial_arg := partial_argl - SIGNED ("0" & rx); + if (partial_arg (partial_arg'high) = '1') then -- negative + q(i) := '0'; + else + q(i) := '1'; + partial (lx'high+i-stages downto lx'high+i-stages-rx'high) := + UNSIGNED (partial_arg(rx'range)); + end if; + end loop; + -- to make the output look like that of the unsigned IEEE divide. + return resize (q, lx'length); + end function short_divide; + + -- 1/X function. Needed for algorithm development. + function reciprocal ( + arg : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + constant fraction_width : NATURAL := -mine(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : NATURAL := arg'high; -- length of FP output exponent + constant divguard : NATURAL := guard; -- guard bits + function onedivy ( + arg : UNSIGNED) + return UNSIGNED is + variable q : UNSIGNED((2*arg'high)+1 downto 0); + variable one : UNSIGNED (q'range); + begin + one := (others => '0'); + one(one'high) := '1'; + q := short_divide (one, arg); -- Unsigned divide + return resize (q, arg'length+1); + end function onedivy; + variable fptype : valid_fpstate; + variable expon : SIGNED (exponent_width-1 downto 0); -- exponents + variable denorm_offset : NATURAL range 0 to 2; + variable fract : UNSIGNED (fraction_width downto 0); + variable fractg : UNSIGNED (fraction_width+divguard downto 0); + variable sfract : UNSIGNED (fraction_width+1+divguard downto 0); -- result fraction + variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); + begin -- reciprocal + fptype := classfp(arg, check_error); + classcase : case fptype is + when isx => + fpresult := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf | neg_inf => -- 1/inf, return 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + when neg_zero | pos_zero => -- 1/0 + report "float_pkg:" + & "RECIPROCAL: Floating Point divide by zero" + severity error; + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + when others => + if (fptype = pos_denormal or fptype = neg_denormal) + and ((arg (-1) or arg(-2)) /= '1') then + -- 1/denormal = infinity, with the exception of 2**-expon_base + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + fpresult (exponent_width) := to_x01 (arg (exponent_width)); + else + break_number ( + arg => arg, + fptyp => fptype, + denormalize => denormalize, + fract => fract, + expon => expon); + fractg := (others => '0'); + if (fptype = pos_denormal or fptype = neg_denormal) then + -- The reciprocal of a denormal number is typically zero, + -- except for two special cases which are trapped here. + if (to_x01(arg (-1)) = '1') then + fractg (fractg'high downto divguard+1) := + fract (fract'high-1 downto 0); -- Shift to not denormal + denorm_offset := 1; -- add 1 to exponent compensate + else -- arg(-2) = '1' + fractg (fractg'high downto divguard+2) := + fract (fract'high-2 downto 0); -- Shift to not denormal + denorm_offset := 2; -- add 2 to exponent compensate + end if; + else + fractg (fractg'high downto divguard) := fract; + denorm_offset := 0; + end if; + expon := - expon - 3 + denorm_offset; + sfract := onedivy (fractg); + -- normalize + fpresult := normalize (fract => sfract, + expon => expon, + sign => arg(exponent_width), + sticky => '1', + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => divguard); + end if; + end case classcase; + return fpresult; + end function reciprocal; + + -- floating point division + function divide ( + l, r : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + constant divguard : NATURAL := guard; -- division guard bits + variable lfptype, rfptype : valid_fpstate; + variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); + variable ulfract, urfract : UNSIGNED (fraction_width downto 0); + variable fractl : UNSIGNED ((2*(fraction_width+divguard)+1) downto 0); -- left + variable fractr : UNSIGNED (fraction_width+divguard downto 0); -- right + variable rfract : UNSIGNED (fractl'range); -- result fraction + variable sfract : UNSIGNED (fraction_width+1+divguard downto 0); -- result fraction + variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents + variable rexpon : SIGNED (exponent_width+1 downto 0); -- result exponent + variable fp_sign, sticky : STD_ULOGIC; -- sign of result + variable shifty, shiftx : INTEGER; -- denormal number shift + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + begin -- divide + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + lfptype := isx; + else + lfptype := classfp (l, check_error); + rfptype := classfp (r, check_error); + end if; + classcase : case rfptype is + when isx => + fpresult := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf | neg_inf => + if lfptype = pos_inf or lfptype = neg_inf -- inf / inf + or lfptype = quiet_nan or lfptype = nan then + -- Return quiet NAN, IEEE754-1985-7.1,4 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + else -- x / inf = 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + fp_sign := l(l'high) xor r(r'high); -- sign + fpresult (fpresult'high) := fp_sign; -- sign + end if; + when pos_zero | neg_zero => + if lfptype = pos_zero or lfptype = neg_zero -- 0 / 0 + or lfptype = quiet_nan or lfptype = nan then + -- Return quiet NAN, IEEE754-1985-7.1,4 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + report "float_pkg:" + & "DIVIDE: Floating Point divide by zero" + severity error; + -- Infinity, define in 754-1985-7.2 + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + fp_sign := l(l'high) xor r(r'high); -- sign + fpresult (fpresult'high) := fp_sign; -- sign + end if; + when others => + classcase2 : case lfptype is + when isx => + fpresult := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf | neg_inf => -- inf / x = inf + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + fp_sign := l(l'high) xor r(r'high); -- sign + fpresult(exponent_width) := fp_sign; + when pos_zero | neg_zero => -- 0 / X = 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + fp_sign := l(l'high) xor r(r'high); -- sign + fpresult(exponent_width) := fp_sign; + when others => + fp_sign := l(l'high) xor r(r'high); -- sign + lresize := resize (arg => to_x01(l), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + lfptype := classfp (lresize, false); -- errors already checked + rresize := resize (arg => to_x01(r), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rfptype := classfp (rresize, false); -- errors already checked + break_number ( + arg => lresize, + fptyp => lfptype, + denormalize => denormalize, + fract => ulfract, + expon => exponl); + -- right side + break_number ( + arg => rresize, + fptyp => rfptype, + denormalize => denormalize, + fract => urfract, + expon => exponr); + -- Compute the exponent + rexpon := resize (exponl, rexpon'length) - exponr - 2; + if (rfptype = pos_denormal or rfptype = neg_denormal) then + -- Do the shifting here not after. That way we have a smaller + -- shifter, and need a smaller divider, because the top + -- bit in the divisor will always be a "1". + shifty := fraction_width - find_leftmost(urfract, '1'); + urfract := shift_left (urfract, shifty); + rexpon := rexpon + shifty; + end if; + fractr := (others => '0'); + fractr (fraction_width+divguard downto divguard) := urfract; + if (lfptype = pos_denormal or lfptype = neg_denormal) then + shiftx := fraction_width - find_leftmost(ulfract, '1'); + ulfract := shift_left (ulfract, shiftx); + rexpon := rexpon - shiftx; + end if; + fractl := (others => '0'); + fractl (fractl'high downto fractl'high-fraction_width) := ulfract; + -- divide + rfract := short_divide (fractl, fractr); -- unsigned divide + sfract := rfract (sfract'range); -- lower bits + sticky := '1'; + -- normalize + fpresult := normalize (fract => sfract, + expon => rexpon, + sign => fp_sign, + sticky => sticky, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => divguard); + end case classcase2; + end case classcase; + return fpresult; + end function divide; + + -- division by a power of 2 + function dividebyp2 ( + l, r : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lfptype, rfptype : valid_fpstate; + variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); + variable ulfract, urfract : UNSIGNED (fraction_width downto 0); + variable exponl, exponr : SIGNED(exponent_width-1 downto 0); -- exponents + variable rexpon : SIGNED(exponent_width downto 0); -- result exponent + variable fp_sign : STD_ULOGIC; -- sign of result + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + begin -- divisionbyp2 + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + lfptype := isx; + else + lfptype := classfp (l, check_error); + rfptype := classfp (r, check_error); + end if; + classcase : case rfptype is + when isx => + fpresult := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf | neg_inf => + if lfptype = pos_inf or lfptype = neg_inf then -- inf / inf + -- Return quiet NAN, IEEE754-1985-7.1,4 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + else -- x / inf = 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + fp_sign := l(l'high) xor r(r'high); -- sign + fpresult (fpresult'high) := fp_sign; -- sign + end if; + when pos_zero | neg_zero => + if lfptype = pos_zero or lfptype = neg_zero then -- 0 / 0 + -- Return quiet NAN, IEEE754-1985-7.1,4 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + report "float_pkg:" + & "DIVIDEBYP2: Floating Point divide by zero" + severity error; + -- Infinity, define in 754-1985-7.2 + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + fp_sign := l(l'high) xor r(r'high); -- sign + fpresult (fpresult'high) := fp_sign; -- sign + end if; + when others => + classcase2 : case lfptype is + when isx => + fpresult := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf | neg_inf => -- inf / x = inf + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + fp_sign := l(l'high) xor r(r'high); -- sign + fpresult (exponent_width) := fp_sign; -- sign + when pos_zero | neg_zero => -- 0 / X = 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + fp_sign := l(l'high) xor r(r'high); -- sign + fpresult (exponent_width) := fp_sign; -- sign + when others => + fp_sign := l(l'high) xor r(r'high); -- sign + lresize := resize (arg => to_x01(l), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + lfptype := classfp (lresize, false); -- errors already checked + rresize := resize (arg => to_x01(r), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rfptype := classfp (rresize, false); -- errors already checked + break_number ( + arg => lresize, + fptyp => lfptype, + denormalize => denormalize, + fract => ulfract, + expon => exponl); + -- right side + break_number ( + arg => rresize, + fptyp => rfptype, + denormalize => denormalize, + fract => urfract, + expon => exponr); + assert (or_reduce (urfract (fraction_width-1 downto 0)) = '0') + report "float_pkg:" + & "DIVIDEBYP2: " + & "Dividebyp2 called with a non power of two divisor" + severity error; + rexpon := (exponl(exponl'high)&exponl) + - (exponr(exponr'high)&exponr) - 1; + -- normalize + fpresult := normalize (fract => ulfract, + expon => rexpon, + sign => fp_sign, + sticky => '1', + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => 0); + end case classcase2; + end case classcase; + return fpresult; + end function dividebyp2; + + -- Multiply accumulate result = l*r + c + function mac ( + l, r, c : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + constant fraction_width : NATURAL := + -mine (mine(l'low, r'low), c'low); -- length of FP output fraction + constant exponent_width : NATURAL := + maximum (maximum(l'high, r'high), c'high); -- length of FP output exponent + variable lfptype, rfptype, cfptype : valid_fpstate; + variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); + variable fractl, fractr : UNSIGNED (fraction_width downto 0); -- fractions + variable fractx : UNSIGNED (fraction_width+guard downto 0); + variable fractc, fracts : UNSIGNED (fraction_width+1+guard downto 0); + variable rfract : UNSIGNED ((2*(fraction_width))+1 downto 0); -- result fraction + variable sfract, ufract : UNSIGNED (fraction_width+1+guard downto 0); -- result fraction + variable exponl, exponr, exponc : SIGNED (exponent_width-1 downto 0); -- exponents + variable rexpon, rexpon2 : SIGNED (exponent_width+1 downto 0); -- result exponent + variable shifty : INTEGER; -- denormal shift + variable shiftx : SIGNED (rexpon'range); -- shift fractions + variable fp_sign : STD_ULOGIC; -- sign of result + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + variable cresize : UNRESOLVED_float (exponent_width downto -fraction_width - guard); + variable leftright : BOOLEAN; -- left or right used + variable sticky : STD_ULOGIC; -- Holds precision for rounding + begin -- multiply + if (fraction_width = 0 or l'length < 7 or r'length < 7 or c'length < 7) then + lfptype := isx; + else + lfptype := classfp (l, check_error); + rfptype := classfp (r, check_error); + cfptype := classfp (c, check_error); + end if; + if (lfptype = isx or rfptype = isx or cfptype = isx) then + fpresult := (others => 'X'); + elsif (lfptype = nan or lfptype = quiet_nan or + rfptype = nan or rfptype = quiet_nan or + cfptype = nan or cfptype = quiet_nan) then + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (((lfptype = pos_inf or lfptype = neg_inf) and + (rfptype = pos_zero or rfptype = neg_zero)) or + ((rfptype = pos_inf or rfptype = neg_inf) and + (lfptype = pos_zero or lfptype = neg_zero))) then -- 0 * inf + -- Return quiet NAN, IEEE754-1985-7.1,3 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (lfptype = pos_inf or rfptype = pos_inf + or lfptype = neg_inf or rfptype = neg_inf -- x * inf = inf + or cfptype = neg_inf or cfptype = pos_inf) then -- x + inf = inf + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + -- figure out the sign + fpresult (exponent_width) := l(l'high) xor r(r'high); + else + fp_sign := l(l'high) xor r(r'high); -- figure out the sign + lresize := resize (arg => to_x01(l), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + lfptype := classfp (lresize, false); -- errors already checked + rresize := resize (arg => to_x01(r), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rfptype := classfp (rresize, false); -- errors already checked + cresize := resize (arg => to_x01(c), + exponent_width => exponent_width, + fraction_width => -cresize'low, + denormalize_in => denormalize, + denormalize => denormalize); + cfptype := classfp (cresize, false); -- errors already checked + break_number ( + arg => lresize, + fptyp => lfptype, + denormalize => denormalize, + fract => fractl, + expon => exponl); + break_number ( + arg => rresize, + fptyp => rfptype, + denormalize => denormalize, + fract => fractr, + expon => exponr); + break_number ( + arg => cresize, + fptyp => cfptype, + denormalize => denormalize, + fract => fractx, + expon => exponc); + if (rfptype = pos_denormal or rfptype = neg_denormal) then + shifty := fraction_width - find_leftmost(fractr, '1'); + fractr := shift_left (fractr, shifty); + elsif (lfptype = pos_denormal or lfptype = neg_denormal) then + shifty := fraction_width - find_leftmost(fractl, '1'); + fractl := shift_left (fractl, shifty); + else + shifty := 0; + -- Note that a denormal number * a denormal number is always zero. + end if; + -- multiply + rfract := fractl * fractr; -- Multiply the fraction + -- add the exponents + rexpon := resize (exponl, rexpon'length) + exponr - shifty + 1; + shiftx := rexpon - exponc; + if shiftx < -fractl'high then + rexpon2 := resize (exponc, rexpon2'length); + fractc := "0" & fractx; + fracts := (others => '0'); + sticky := or_reduce (rfract); + elsif shiftx < 0 then + shiftx := - shiftx; + fracts := shift_right (rfract (rfract'high downto rfract'high + - fracts'length+1), + to_integer(shiftx)); + fractc := "0" & fractx; + rexpon2 := resize (exponc, rexpon2'length); + leftright := false; + sticky := or_reduce (rfract (to_integer(shiftx)+rfract'high + - fracts'length downto 0)); + elsif shiftx = 0 then + rexpon2 := resize (exponc, rexpon2'length); + sticky := or_reduce (rfract (rfract'high - fractc'length downto 0)); + if rfract (rfract'high downto rfract'high - fractc'length+1) > fractx + then + fractc := "0" & fractx; + fracts := rfract (rfract'high downto rfract'high + - fracts'length+1); + leftright := false; + else + fractc := rfract (rfract'high downto rfract'high + - fractc'length+1); + fracts := "0" & fractx; + leftright := true; + end if; + elsif shiftx > fractx'high then + rexpon2 := rexpon; + fracts := (others => '0'); + fractc := rfract (rfract'high downto rfract'high - fractc'length+1); + leftright := true; + sticky := or_reduce (fractx & rfract (rfract'high - fractc'length + downto 0)); + else -- fractx'high > shiftx > 0 + rexpon2 := rexpon; + fracts := "0" & shift_right (fractx, to_integer (shiftx)); + fractc := rfract (rfract'high downto rfract'high - fractc'length+1); + leftright := true; + sticky := or_reduce (fractx (to_integer (shiftx) downto 0) + & rfract (rfract'high - fractc'length downto 0)); + end if; + fracts (0) := fracts (0) or sticky; -- Or the sticky bit into the LSB + if fp_sign = to_X01(c(c'high)) then + ufract := fractc + fracts; + fp_sign := fp_sign; + else -- signs are different + ufract := fractc - fracts; -- always positive result + if leftright then -- Figure out which sign to use + fp_sign := fp_sign; + else + fp_sign := c(c'high); + end if; + end if; + -- normalize + fpresult := normalize (fract => ufract, + expon => rexpon2, + sign => fp_sign, + sticky => sticky, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => guard); + end if; + return fpresult; + end function mac; + + -- "rem" function +-- function remainder ( +-- l, r : UNRESOLVED_float; -- floating point input +-- constant round_style : round_type := float_round_style; -- rounding option +-- constant guard : NATURAL := float_guard_bits; -- number of guard bits +-- constant check_error : BOOLEAN := float_check_error; -- check for errors +-- constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP +-- return UNRESOLVED_float is +-- constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction +-- constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent +-- constant divguard : NATURAL := guard; -- division guard bits +-- variable lfptype, rfptype : valid_fpstate; +-- variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); +-- variable ulfract, urfract : UNSIGNED (fraction_width downto 0); +-- variable fractr, fractl : UNSIGNED (fraction_width+divguard downto 0); -- right +-- variable rfract : UNSIGNED (fractr'range); -- result fraction +-- variable sfract : UNSIGNED (fraction_width+divguard downto 0); -- result fraction +-- variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents +-- variable rexpon : SIGNED (exponent_width downto 0); -- result exponent +-- variable fp_sign : STD_ULOGIC; -- sign of result +-- variable shifty : INTEGER; -- denormal number shift +-- variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); +-- begin -- remainder +-- if (fraction_width = 0 or l'length < 7 or r'length < 7) then +-- lfptype := isx; +-- else +-- lfptype := classfp (l, check_error); +-- rfptype := classfp (r, check_error); +-- end if; +-- if (lfptype = isx or rfptype = isx) then +-- fpresult := (others => 'X'); +-- elsif (lfptype = nan or lfptype = quiet_nan) +-- or (rfptype = nan or rfptype = quiet_nan) +-- -- Return quiet NAN, IEEE754-1985-7.1,1 +-- or (lfptype = pos_inf or lfptype = neg_inf) -- inf rem x +-- -- Return quiet NAN, IEEE754-1985-7.1,5 +-- or (rfptype = pos_zero or rfptype = neg_zero) then -- x rem 0 +-- -- Return quiet NAN, IEEE754-1985-7.1,5 +-- fpresult := qnanfp (fraction_width => fraction_width, +-- exponent_width => exponent_width); +-- elsif (rfptype = pos_inf or rfptype = neg_inf) then -- x rem inf = 0 +-- fpresult := zerofp (fraction_width => fraction_width, +-- exponent_width => exponent_width); +-- elsif (abs(l) < abs(r)) then +-- fpresult := l; +-- else +-- fp_sign := to_X01(l(l'high)); -- sign +-- lresize := resize (arg => to_x01(l), +-- exponent_width => exponent_width, +-- fraction_width => fraction_width, +-- denormalize_in => denormalize, +-- denormalize => denormalize); +-- lfptype := classfp (lresize, false); -- errors already checked +-- rresize := resize (arg => to_x01(r), +-- exponent_width => exponent_width, +-- fraction_width => fraction_width, +-- denormalize_in => denormalize, +-- denormalize => denormalize); +-- rfptype := classfp (rresize, false); -- errors already checked +-- fractl := (others => '0'); +-- break_number ( +-- arg => lresize, +-- fptyp => lfptype, +-- denormalize => denormalize, +-- fract => ulfract, +-- expon => exponl); +-- fractl (fraction_width+divguard downto divguard) := ulfract; +-- -- right side +-- fractr := (others => '0'); +-- break_number ( +-- arg => rresize, +-- fptyp => rfptype, +-- denormalize => denormalize, +-- fract => urfract, +-- expon => exponr); +-- fractr (fraction_width+divguard downto divguard) := urfract; +-- rexpon := (exponr(exponr'high)&exponr); +-- shifty := to_integer(exponl - rexpon); +-- if (shifty > 0) then +-- fractr := shift_right (fractr, shifty); +-- rexpon := rexpon + shifty; +-- end if; +-- if (fractr /= 0) then +-- -- rem +-- rfract := fractl rem fractr; -- unsigned rem +-- sfract := rfract (sfract'range); -- lower bits +-- -- normalize +-- fpresult := normalize (fract => sfract, +-- expon => rexpon, +-- sign => fp_sign, +-- fraction_width => fraction_width, +-- exponent_width => exponent_width, +-- round_style => round_style, +-- denormalize => denormalize, +-- nguard => divguard); +-- else +-- -- If we shift "fractr" so far that it becomes zero, return zero. +-- fpresult := zerofp (fraction_width => fraction_width, +-- exponent_width => exponent_width); +-- end if; +-- end if; +-- return fpresult; +-- end function remainder; + +-- -- "mod" function +-- function modulo ( +-- l, r : UNRESOLVED_float; -- floating point input +-- constant round_style : round_type := float_round_style; -- rounding option +-- constant guard : NATURAL := float_guard_bits; -- number of guard bits +-- constant check_error : BOOLEAN := float_check_error; -- check for errors +-- constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP +-- return UNRESOLVED_float is +-- constant fraction_width : NATURAL := - mine(l'low, r'low); -- length of FP output fraction +-- constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent +-- variable lfptype, rfptype : valid_fpstate; +-- variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); +-- variable remres : UNRESOLVED_float (exponent_width downto -fraction_width); +-- begin -- remainder +-- if (fraction_width = 0 or l'length < 7 or r'length < 7) then +-- lfptype := isx; +-- else +-- lfptype := classfp (l, check_error); +-- rfptype := classfp (r, check_error); +-- end if; +-- if (lfptype = isx or rfptype = isx) then +-- fpresult := (others => 'X'); +-- elsif (lfptype = nan or lfptype = quiet_nan) +-- or (rfptype = nan or rfptype = quiet_nan) +-- -- Return quiet NAN, IEEE754-1985-7.1,1 +-- or (lfptype = pos_inf or lfptype = neg_inf) -- inf rem x +-- -- Return quiet NAN, IEEE754-1985-7.1,5 +-- or (rfptype = pos_zero or rfptype = neg_zero) then -- x rem 0 +-- -- Return quiet NAN, IEEE754-1985-7.1,5 +-- fpresult := qnanfp (fraction_width => fraction_width, +-- exponent_width => exponent_width); +-- elsif (rfptype = pos_inf or rfptype = neg_inf) then -- x rem inf = 0 +-- fpresult := zerofp (fraction_width => fraction_width, +-- exponent_width => exponent_width); +-- else +-- remres := remainder (l => abs(l), +-- r => abs(r), +-- round_style => round_style, +-- guard => guard, +-- check_error => false, +-- denormalize => denormalize); +-- -- MOD is the same as REM, but you do something different with +-- -- negative values +-- if (is_negative (l)) then +-- remres := - remres; +-- end if; +-- if (is_negative (l) = is_negative (r) or remres = 0) then +-- fpresult := remres; +-- else +-- fpresult := add (l => remres, +-- r => r, +-- round_style => round_style, +-- guard => guard, +-- check_error => false, +-- denormalize => denormalize); +-- end if; +-- end if; +-- return fpresult; +-- end function modulo; + + -- Square root of a floating point number. Done using Newton's Iteration. +-- function sqrt ( +-- arg : UNRESOLVED_float; -- floating point input +-- constant round_style : round_type := float_round_style; +-- constant guard : NATURAL := float_guard_bits; +-- constant check_error : BOOLEAN := float_check_error; +-- constant denormalize : BOOLEAN := float_denormalize) +-- return UNRESOLVED_float is +-- constant fraction_width : NATURAL := guard-arg'low; -- length of FP output fraction +-- constant exponent_width : NATURAL := arg'high; -- length of FP output exponent +-- variable sign : STD_ULOGIC; +-- variable fpresult : float (arg'range); +-- variable fptype : valid_fpstate; +-- variable iexpon : SIGNED(exponent_width-1 downto 0); -- exponents +-- variable expon : SIGNED(exponent_width downto 0); -- exponents +-- variable ufact : ufixed (0 downto arg'low); +-- variable fact : ufixed (2 downto -fraction_width); -- fraction +-- variable resb : ufixed (fact'high+1 downto fact'low); +-- begin -- square root +-- fptype := Classfp (arg, check_error); +-- classcase : case fptype is +-- when isx => +-- fpresult := (others => 'X'); +-- when nan | quiet_nan | +-- -- Return quiet NAN, IEEE754-1985-7.1,1 +-- neg_normal | neg_denormal | neg_inf => -- sqrt (neg) +-- -- Return quiet NAN, IEEE754-1985-7.1.6 +-- fpresult := qnanfp (fraction_width => fraction_width-guard, +-- exponent_width => exponent_width); +-- when pos_inf => -- Sqrt (inf), return infinity +-- fpresult := pos_inffp (fraction_width => fraction_width-guard, +-- exponent_width => exponent_width); +-- when pos_zero => -- return 0 +-- fpresult := zerofp (fraction_width => fraction_width-guard, +-- exponent_width => exponent_width); +-- when neg_zero => -- IEEE754-1985-6.3 return -0 +-- fpresult := neg_zerofp (fraction_width => fraction_width-guard, +-- exponent_width => exponent_width); +-- when others => +-- break_number (arg => arg, +-- denormalize => denormalize, +-- check_error => false, +-- fract => ufact, +-- expon => iexpon, +-- sign => sign); +-- expon := resize (iexpon+1, expon'length); -- get exponent +-- fact := resize (ufact, fact'high, fact'low); +-- if (expon(0) = '1') then +-- fact := fact sla 1; -- * 2.0 +-- end if; +-- expon := shift_right (expon, 1); -- exponent/2 +-- -- Newton's iteration - root := (1 + arg) / 2 +-- resb := (fact + 1) sra 1; +-- for j in 0 to fraction_width/4 loop +-- -- root := (root + (arg/root))/2 +-- resb := resize (arg => (resb + (fact/resb)) sra 1, +-- left_index => resb'high, +-- right_index => resb'low, +-- round_style => fixed_truncate, +-- overflow_style => fixed_wrap); +-- end loop; +-- fpresult := normalize (fract => resb, +-- expon => expon-1, +-- sign => '0', +-- exponent_width => arg'high, +-- fraction_width => -arg'low, +-- round_style => round_style, +-- denormalize => denormalize, +-- nguard => guard); +-- end case classcase; +-- return fpresult; +-- end function sqrt; + + function Is_Negative (arg : UNRESOLVED_float) return BOOLEAN is + -- Technically -0 should return "false", but I'm leaving that case out. + begin + return (to_x01(arg(arg'high)) = '1'); + end function Is_Negative; + + -- compare functions + -- =, /=, >=, <=, <, > + + function eq ( -- equal = + l, r : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + variable lfptype, rfptype : valid_fpstate; + variable is_equal, is_unordered : BOOLEAN; + constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + begin -- equal + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return false; + else + lfptype := classfp (l, check_error); + rfptype := classfp (r, check_error); + end if; + if (lfptype = neg_zero or lfptype = pos_zero) and + (rfptype = neg_zero or rfptype = pos_zero) then + is_equal := true; + else + lresize := resize (arg => to_x01(l), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rresize := resize (arg => to_x01(r), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + is_equal := (to_slv(lresize) = to_slv(rresize)); + end if; + if (check_error) then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return is_equal and not is_unordered; + end function eq; + + function lt ( -- less than < + l, r : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lfptype, rfptype : valid_fpstate; + variable expl, expr : UNSIGNED (exponent_width-1 downto 0); + variable fractl, fractr : UNSIGNED (fraction_width-1 downto 0); + variable is_less_than, is_unordered : BOOLEAN; + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + begin + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + is_less_than := false; + else + lresize := resize (arg => to_x01(l), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rresize := resize (arg => to_x01(r), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + if to_x01(l(l'high)) = to_x01(r(r'high)) then -- sign bits + expl := UNSIGNED(lresize(exponent_width-1 downto 0)); + expr := UNSIGNED(rresize(exponent_width-1 downto 0)); + if expl = expr then + fractl := UNSIGNED (to_slv(lresize(-1 downto -fraction_width))); + fractr := UNSIGNED (to_slv(rresize(-1 downto -fraction_width))); + if to_x01(l(l'high)) = '0' then -- positive number + is_less_than := (fractl < fractr); + else + is_less_than := (fractl > fractr); -- negative + end if; + else + if to_x01(l(l'high)) = '0' then -- positive number + is_less_than := (expl < expr); + else + is_less_than := (expl > expr); -- negative + end if; + end if; + else + lfptype := classfp (l, check_error); + rfptype := classfp (r, check_error); + if (lfptype = neg_zero and rfptype = pos_zero) then + is_less_than := false; -- -0 < 0 returns false. + else + is_less_than := (to_x01(l(l'high)) > to_x01(r(r'high))); + end if; + end if; + end if; + if check_error then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return is_less_than and not is_unordered; + end function lt; + + function gt ( -- greater than > + l, r : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lfptype, rfptype : valid_fpstate; + variable expl, expr : UNSIGNED (exponent_width-1 downto 0); + variable fractl, fractr : UNSIGNED (fraction_width-1 downto 0); + variable is_greater_than : BOOLEAN; + variable is_unordered : BOOLEAN; + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + begin -- greater_than + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + is_greater_than := false; + else + lresize := resize (arg => to_x01(l), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rresize := resize (arg => to_x01(r), + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + if to_x01(l(l'high)) = to_x01(r(r'high)) then -- sign bits + expl := UNSIGNED(lresize(exponent_width-1 downto 0)); + expr := UNSIGNED(rresize(exponent_width-1 downto 0)); + if expl = expr then + fractl := UNSIGNED (to_slv(lresize(-1 downto -fraction_width))); + fractr := UNSIGNED (to_slv(rresize(-1 downto -fraction_width))); + if to_x01(l(l'high)) = '0' then -- positive number + is_greater_than := fractl > fractr; + else + is_greater_than := fractl < fractr; -- negative + end if; + else + if to_x01(l(l'high)) = '0' then -- positive number + is_greater_than := expl > expr; + else + is_greater_than := expl < expr; -- negative + end if; + end if; + else + lfptype := classfp (l, check_error); + rfptype := classfp (r, check_error); + if (lfptype = pos_zero and rfptype = neg_zero) then + is_greater_than := false; -- 0 > -0 returns false. + else + is_greater_than := to_x01(l(l'high)) < to_x01(r(r'high)); + end if; + end if; + end if; + if check_error then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return is_greater_than and not is_unordered; + end function gt; + + -- purpose: /= function + function ne ( -- not equal /= + l, r : UNRESOLVED_float; + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + variable is_equal, is_unordered : BOOLEAN; + begin + is_equal := eq (l => l, + r => r, + check_error => false, + denormalize => denormalize); + if check_error then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return not (is_equal and not is_unordered); + end function ne; + + function le ( -- less than or equal to <= + l, r : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + variable is_greater_than, is_unordered : BOOLEAN; + begin + is_greater_than := gt (l => l, + r => r, + check_error => false, + denormalize => denormalize); + if check_error then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return not is_greater_than and not is_unordered; + end function le; + + function ge ( -- greater than or equal to >= + l, r : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + variable is_less_than, is_unordered : BOOLEAN; + begin + is_less_than := lt (l => l, + r => r, + check_error => false, + denormalize => denormalize); + if check_error then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return not is_less_than and not is_unordered; + end function ge; + + function \?=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is + constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lfptype, rfptype : valid_fpstate; + variable is_equal, is_unordered : STD_ULOGIC; + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + begin -- ?= + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + else + lfptype := classfp (l, float_check_error); + rfptype := classfp (r, float_check_error); + end if; + if (lfptype = neg_zero or lfptype = pos_zero) and + (rfptype = neg_zero or rfptype = pos_zero) then + is_equal := '1'; + else + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => float_denormalize, + denormalize => float_denormalize); + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => float_denormalize, + denormalize => float_denormalize); + is_equal := \?=\ (to_sulv(lresize), to_sulv(rresize)); + end if; + if (float_check_error) then + if (lfptype = nan or lfptype = quiet_nan or + rfptype = nan or rfptype = quiet_nan) then + is_unordered := '1'; + else + is_unordered := '0'; + end if; + else + is_unordered := '0'; + end if; + return is_equal and not is_unordered; + end function \?=\; + + function \?/=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is + constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lfptype, rfptype : valid_fpstate; + variable is_equal, is_unordered : STD_ULOGIC; + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + begin -- ?/= + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + else + lfptype := classfp (l, float_check_error); + rfptype := classfp (r, float_check_error); + end if; + if (lfptype = neg_zero or lfptype = pos_zero) and + (rfptype = neg_zero or rfptype = pos_zero) then + is_equal := '1'; + else + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => float_denormalize, + denormalize => float_denormalize); + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => float_denormalize, + denormalize => float_denormalize); + is_equal := \?=\ (to_sulv(lresize), to_sulv(rresize)); + end if; + if (float_check_error) then + if (lfptype = nan or lfptype = quiet_nan or + rfptype = nan or rfptype = quiet_nan) then + is_unordered := '1'; + else + is_unordered := '0'; + end if; + else + is_unordered := '0'; + end if; + return not (is_equal and not is_unordered); + end function \?/=\; + + function \?>\ (L, R : UNRESOLVED_float) return STD_ULOGIC is + constant fraction_width : NATURAL := -mine(l'low, r'low); + variable founddash : BOOLEAN := false; + begin + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + founddash := true; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + founddash := true; + end if; + end loop; + if founddash then + report "float_pkg:" + & " ""?>"": '-' found in compare string" + severity error; + return 'X'; + elsif is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + + function \?>=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is + constant fraction_width : NATURAL := -mine(l'low, r'low); + variable founddash : BOOLEAN := false; + begin + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + founddash := true; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + founddash := true; + end if; + end loop; + if founddash then + report "float_pkg:" + & " ""?>="": '-' found in compare string" + severity error; + return 'X'; + elsif is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + + function \?<\ (L, R : UNRESOLVED_float) return STD_ULOGIC is + constant fraction_width : NATURAL := -mine(l'low, r'low); + variable founddash : BOOLEAN := false; + begin + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + founddash := true; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + founddash := true; + end if; + end loop; + if founddash then + report "float_pkg:" + & " ""?<"": '-' found in compare string" + severity error; + return 'X'; + elsif is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + + function \?<=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is + constant fraction_width : NATURAL := -mine(l'low, r'low); + variable founddash : BOOLEAN := false; + begin + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + founddash := true; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + founddash := true; + end if; + end loop; + if founddash then + report "float_pkg:" + & " ""?<="": '-' found in compare string" + severity error; + return 'X'; + elsif is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + + function std_match (L, R : UNRESOLVED_float) return BOOLEAN is + begin + if (L'high = R'high and L'low = R'low) then + return std_match(to_sulv(L), to_sulv(R)); + else + report "float_pkg:" + & "STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" + severity warning; + return false; + end if; + end function std_match; + + function find_rightmost (arg : UNRESOLVED_float; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'reverse_range loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'high+1; -- return out of bounds 'high + end function find_rightmost; + + function find_leftmost (arg : UNRESOLVED_float; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'range loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'low-1; -- return out of bounds 'low + end function find_leftmost; + + -- These override the defaults for the compare operators. + function "=" (l, r : UNRESOLVED_float) return BOOLEAN is + begin + return eq(l, r); + end function "="; + + function "/=" (l, r : UNRESOLVED_float) return BOOLEAN is + begin + return ne(l, r); + end function "/="; + + function ">=" (l, r : UNRESOLVED_float) return BOOLEAN is + begin + return ge(l, r); + end function ">="; + + function "<=" (l, r : UNRESOLVED_float) return BOOLEAN is + begin + return le(l, r); + end function "<="; + + function ">" (l, r : UNRESOLVED_float) return BOOLEAN is + begin + return gt(l, r); + end function ">"; + + function "<" (l, r : UNRESOLVED_float) return BOOLEAN is + begin + return lt(l, r); + end function "<"; + + -- purpose: maximum of two numbers (overrides default) + function maximum ( + L, R : UNRESOLVED_float) + return UNRESOLVED_float is + constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + begin + if ((L'length < 1) or (R'length < 1)) then return NAFP; + end if; + lresize := resize (l, exponent_width, fraction_width); + rresize := resize (r, exponent_width, fraction_width); + if lresize > rresize then return lresize; + else return rresize; + end if; + end function maximum; + + function minimum ( + L, R : UNRESOLVED_float) + return UNRESOLVED_float is + constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); + begin + if ((L'length < 1) or (R'length < 1)) then return NAFP; + end if; + lresize := resize (l, exponent_width, fraction_width); + rresize := resize (r, exponent_width, fraction_width); + if lresize > rresize then return rresize; + else return lresize; + end if; + end function minimum; + + ----------------------------------------------------------------------------- + -- conversion functions + ----------------------------------------------------------------------------- + + -- Converts a floating point number of one format into another format + function resize ( + arg : UNRESOLVED_float; -- Floating point input + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + constant in_fraction_width : NATURAL := -arg'low; -- length of FP output fraction + constant in_exponent_width : NATURAL := arg'high; -- length of FP output exponent + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + -- result value + variable fptype : valid_fpstate; + variable expon_in : SIGNED (in_exponent_width-1 downto 0); + variable fract_in : UNSIGNED (in_fraction_width downto 0); + variable round : BOOLEAN; + variable expon_out : SIGNED (exponent_width-1 downto 0); -- output fract + variable fract_out : UNSIGNED (fraction_width downto 0); -- output fract + variable passguard : NATURAL; + begin + fptype := classfp(arg, check_error); + if ((fptype = pos_denormal or fptype = neg_denormal) and denormalize_in + and (in_exponent_width < exponent_width + or in_fraction_width < fraction_width)) + or in_exponent_width > exponent_width + or in_fraction_width > fraction_width then + -- size reduction + classcase : case fptype is + when isx => + result := (others => 'X'); + when nan | quiet_nan => + result := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf => + result := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + when neg_inf => + result := neg_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_zero | neg_zero => + result := zerofp (fraction_width => fraction_width, -- hate -0 + exponent_width => exponent_width); + when others => + break_number ( + arg => arg, + fptyp => fptype, + denormalize => denormalize_in, + fract => fract_in, + expon => expon_in); + if fraction_width > in_fraction_width and denormalize_in then + -- You only get here if you have a denormal input + fract_out := (others => '0'); -- pad with zeros + fract_out (fraction_width downto + fraction_width - in_fraction_width) := fract_in; + result := normalize ( + fract => fract_out, + expon => expon_in, + sign => arg(arg'high), + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => 0); + else + result := normalize ( + fract => fract_in, + expon => expon_in, + sign => arg(arg'high), + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => in_fraction_width - fraction_width); + end if; + end case classcase; + else -- size increase or the same size + if exponent_width > in_exponent_width then + expon_in := SIGNED(arg (in_exponent_width-1 downto 0)); + if fptype = pos_zero or fptype = neg_zero then + result (exponent_width-1 downto 0) := (others => '0'); + elsif expon_in = -1 then -- inf or nan (shorts out check_error) + result (exponent_width-1 downto 0) := (others => '1'); + else + -- invert top BIT + expon_in(expon_in'high) := not expon_in(expon_in'high); + expon_out := resize (expon_in, expon_out'length); -- signed expand + -- Flip it back. + expon_out(expon_out'high) := not expon_out(expon_out'high); + result (exponent_width-1 downto 0) := UNRESOLVED_float(expon_out); + end if; + result (exponent_width) := arg (in_exponent_width); -- sign + else -- exponent_width = in_exponent_width + result (exponent_width downto 0) := arg (in_exponent_width downto 0); + end if; + if fraction_width > in_fraction_width then + result (-1 downto -fraction_width) := (others => '0'); -- zeros + result (-1 downto -in_fraction_width) := + arg (-1 downto -in_fraction_width); + else -- fraction_width = in_fraciton_width + result (-1 downto -fraction_width) := + arg (-1 downto -in_fraction_width); + end if; + end if; + return result; + end function resize; + + function resize ( + arg : UNRESOLVED_float; -- floating point input + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + variable result : UNRESOLVED_float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := resize (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style, + check_error => check_error, + denormalize_in => denormalize_in, + denormalize => denormalize); + return result; + end if; + end function resize; + + function to_float32 ( + arg : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float32 is + begin + return resize (arg => arg, + exponent_width => float32'high, + fraction_width => -float32'low, + round_style => round_style, + check_error => check_error, + denormalize_in => denormalize_in, + denormalize => denormalize); + end function to_float32; + + function to_float64 ( + arg : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float64 is + begin + return resize (arg => arg, + exponent_width => float64'high, + fraction_width => -float64'low, + round_style => round_style, + check_error => check_error, + denormalize_in => denormalize_in, + denormalize => denormalize); + end function to_float64; + + function to_float128 ( + arg : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float128 is + begin + return resize (arg => arg, + exponent_width => float128'high, + fraction_width => -float128'low, + round_style => round_style, + check_error => check_error, + denormalize_in => denormalize_in, + denormalize => denormalize); + end function to_float128; + + -- to_float (Real) + -- typically not Synthesizable unless the input is a constant. + function to_float ( + arg : REAL; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + variable arg_real : REAL; -- Real version of argument + variable validfp : boundary_type; -- Check for valid results + variable exp : INTEGER; -- Integer version of exponent + variable expon : UNSIGNED (exponent_width - 1 downto 0); + -- Unsigned version of exp. + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable fract : UNSIGNED (fraction_width-1 downto 0); + variable frac : REAL; -- Real version of fraction + constant roundfrac : REAL := 2.0 ** (-2 - fract'high); -- used for rounding + variable round : BOOLEAN; -- to round or not to round + begin + result := (others => '0'); + arg_real := arg; + if arg_real < 0.0 then + result (exponent_width) := '1'; + arg_real := - arg_real; -- Make it positive. + else + result (exponent_width) := '0'; + end if; + test_boundary (arg => arg_real, + fraction_width => fraction_width, + exponent_width => exponent_width, + denormalize => denormalize, + btype => validfp, + log2i => exp); + if validfp = zero then + return result; -- Result initialized to "0". + elsif validfp = infinity then + result (exponent_width - 1 downto 0) := (others => '1'); -- Exponent all "1" + -- return infinity. + return result; + else + if validfp = denormal then -- Exponent will default to "0". + expon := (others => '0'); + frac := arg_real * (2.0 ** (to_integer(expon_base)-1)); + else -- Number less than 1. "normal" number + expon := UNSIGNED (to_signed (exp-1, exponent_width)); + expon(exponent_width-1) := not expon(exponent_width-1); + frac := (arg_real / 2.0 ** exp) - 1.0; -- Number less than 1. + end if; + for i in 0 to fract'high loop + if frac >= 2.0 ** (-1 - i) then + fract (fract'high - i) := '1'; + frac := frac - 2.0 ** (-1 - i); + else + fract (fract'high - i) := '0'; + end if; + end loop; + round := false; + case round_style is + when round_nearest => + if frac > roundfrac or ((frac = roundfrac) and fract(0) = '1') then + round := true; + end if; + when round_inf => + if frac /= 0.0 and result(exponent_width) = '0' then + round := true; + end if; + when round_neginf => + if frac /= 0.0 and result(exponent_width) = '1' then + round := true; + end if; + when others => + null; -- don't round + end case; + if (round) then + if and_reduce (fract) = '1' then -- fraction is all "1" + expon := expon + 1; + fract := (others => '0'); + else + fract := fract + 1; + end if; + end if; + result (exponent_width-1 downto 0) := UNRESOLVED_float(expon); + result (-1 downto -fraction_width) := UNRESOLVED_float(fract); + return result; + end if; + end function to_float; + + -- to_float (Integer) + function to_float ( + arg : INTEGER; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + variable arg_int : NATURAL; -- Natural version of argument + variable expon : SIGNED (exponent_width-1 downto 0); + variable exptmp : SIGNED (exponent_width-1 downto 0); + -- Unsigned version of exp. + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable fract : UNSIGNED (fraction_width-1 downto 0) := (others => '0'); + variable fracttmp : UNSIGNED (fraction_width-1 downto 0); + variable round : BOOLEAN; + variable shift : NATURAL; + variable shiftr : NATURAL; + variable roundfrac : NATURAL; -- used in rounding + begin + if arg < 0 then + result (exponent_width) := '1'; + arg_int := -arg; -- Make it positive. + else + result (exponent_width) := '0'; + arg_int := arg; + end if; + if arg_int = 0 then + result := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + -- If the number is larger than we can represent in this number system + -- we need to return infinity. + shift := log2(arg_int); + if shift > to_integer(expon_base) then + -- worry about infinity + if result (exponent_width) = '0' then + result := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + -- return negative infinity. + result := neg_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + end if; + else -- Normal number (can't be denormal) + -- Compute Exponent + expon := to_signed (shift-1, expon'length); -- positive fraction. + -- Compute Fraction + arg_int := arg_int - 2**shift; -- Subtract off the 1.0 + shiftr := shift; + for I in fract'high downto maximum (fract'high - shift + 1, 0) loop + shiftr := shiftr - 1; + if (arg_int >= 2**shiftr) then + arg_int := arg_int - 2**shiftr; + fract(I) := '1'; + else + fract(I) := '0'; + end if; + end loop; + -- Rounding routine + round := false; + if arg_int > 0 then + roundfrac := 2**(shiftr-1); + case round_style is + when round_nearest => + if arg_int > roundfrac or + ((arg_int = roundfrac) and fract(0) = '1') then + round := true; + end if; + when round_inf => + if arg_int /= 0 and result (exponent_width) = '0' then + round := true; + end if; + when round_neginf => + if arg_int /= 0 and result (exponent_width) = '1' then + round := true; + end if; + when others => + null; + end case; + end if; + if round then + fp_round(fract_in => fract, + expon_in => expon, + fract_out => fracttmp, + expon_out => exptmp); + fract := fracttmp; + expon := exptmp; + end if; + -- Put the number together and return + expon(exponent_width-1) := not expon(exponent_width-1); + result (exponent_width-1 downto 0) := UNRESOLVED_float(expon); + result (-1 downto -fraction_width) := UNRESOLVED_float(fract); + end if; + end if; + return result; + end function to_float; + + -- to_float (unsigned) + function to_float ( + arg : UNSIGNED; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; + variable sarg : SIGNED (ARG_LEFT+1 downto 0); -- signed version of arg + begin + if arg'length < 1 then + return NAFP; + end if; + sarg (XARG'range) := SIGNED (XARG); + sarg (sarg'high) := '0'; + result := to_float (arg => sarg, + exponent_width => exponent_width, + fraction_width => fraction_width, + round_style => round_style); + return result; + end function to_float; + + -- to_float (signed) + function to_float ( + arg : SIGNED; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; + variable arg_int : UNSIGNED(xarg'range); -- Real version of argument + variable argb2 : UNSIGNED(xarg'high/2 downto 0); -- log2 of input + variable rexp : SIGNED (exponent_width - 1 downto 0); + variable exp : SIGNED (exponent_width - 1 downto 0); + -- signed version of exp. + variable expon : UNSIGNED (exponent_width - 1 downto 0); + -- Unsigned version of exp. + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable round : BOOLEAN; + variable fract : UNSIGNED (fraction_width-1 downto 0); + variable rfract : UNSIGNED (fraction_width-1 downto 0); + variable sign : STD_ULOGIC; -- sign bit + begin + if arg'length < 1 then + return NAFP; + end if; + if Is_X (xarg) then + result := (others => 'X'); + elsif (xarg = 0) then + result := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + else -- Normal number (can't be denormal) + sign := to_X01(xarg (xarg'high)); + arg_int := UNSIGNED(abs (to_01(xarg))); + -- Compute Exponent + argb2 := to_unsigned(find_leftmost(arg_int, '1'), argb2'length); -- Log2 + if argb2 > UNSIGNED(expon_base) then + result := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + result (exponent_width) := sign; + else + exp := SIGNED(resize(argb2, exp'length)); + arg_int := shift_left (arg_int, arg_int'high-to_integer(exp)); + if (arg_int'high > fraction_width) then + fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width)); + round := check_round ( + fract_in => fract (0), + sign => sign, + remainder => arg_int((arg_int'high-fraction_width-1) + downto 0), + round_style => round_style); + if round then + fp_round(fract_in => fract, + expon_in => exp, + fract_out => rfract, + expon_out => rexp); + else + rfract := fract; + rexp := exp; + end if; + else + rexp := exp; + rfract := (others => '0'); + rfract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) := + arg_int (arg_int'high-1 downto 0); + end if; + result (exponent_width) := sign; + expon := UNSIGNED (rexp-1); + expon(exponent_width-1) := not expon(exponent_width-1); + result (exponent_width-1 downto 0) := UNRESOLVED_float(expon); + result (-1 downto -fraction_width) := UNRESOLVED_float(rfract); + end if; + end if; + return result; + end function to_float; + + -- std_logic_vector to float + function to_float ( + arg : STD_ULOGIC_VECTOR; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction + return UNRESOLVED_float is + variable fpvar : UNRESOLVED_float (exponent_width downto -fraction_width); + begin + if arg'length < 1 then + return NAFP; + end if; + fpvar := UNRESOLVED_float(arg); + return fpvar; + end function to_float; + + -- purpose: converts a ufixed to a floating point + function to_float ( + arg : UNRESOLVED_ufixed; -- unsigned fixed point input + constant exponent_width : NATURAL := float_exponent_width; -- width of exponent + constant fraction_width : NATURAL := float_fraction_width; -- width of fraction + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions + return UNRESOLVED_float is + variable sarg : sfixed (arg'high+1 downto arg'low); -- Signed version of arg + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + begin -- function to_float + if (arg'length < 1) then + return NAFP; + end if; + sarg (arg'range) := sfixed (arg); + sarg (sarg'high) := '0'; + result := to_float (arg => sarg, + exponent_width => exponent_width, + fraction_width => fraction_width, + round_style => round_style, + denormalize => denormalize); + return result; + end function to_float; + + function to_float ( + arg : UNRESOLVED_sfixed; -- signed fixed point + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- rounding option + return UNRESOLVED_float is + constant integer_width : INTEGER := arg'high; + constant in_fraction_width : INTEGER := arg'low; + variable xresult : sfixed (integer_width downto in_fraction_width); + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + variable arg_int : UNSIGNED(integer_width - in_fraction_width + downto 0); -- unsigned version of argument + variable argx : SIGNED (integer_width - in_fraction_width downto 0); + variable exp, exptmp : SIGNED (exponent_width downto 0); + variable expon : UNSIGNED (exponent_width - 1 downto 0); + -- Unsigned version of exp. + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable fract, fracttmp : UNSIGNED (fraction_width-1 downto 0) := + (others => '0'); + variable round : BOOLEAN := false; + begin + if (arg'length < 1) then + return NAFP; + end if; + xresult := to_01(arg, 'X'); + argx := SIGNED(to_slv(xresult)); + if (Is_X (arg)) then + result := (others => 'X'); + elsif (argx = 0) then + result := (others => '0'); + else + result := (others => '0'); -- zero out the result + if argx(argx'left) = '1' then -- toss the sign bit + result (exponent_width) := '1'; -- Negative number + arg_int := UNSIGNED(to_x01(not STD_LOGIC_VECTOR (argx))) + 1; -- Make it positive with two's complement + else + result (exponent_width) := '0'; + arg_int := UNSIGNED(to_x01(STD_LOGIC_VECTOR (argx))); -- new line: direct conversion to unsigned + end if; + -- Compute Exponent + exp := to_signed(find_leftmost(arg_int, '1'), exp'length); -- Log2 + if exp + in_fraction_width > expon_base then -- return infinity + result (-1 downto -fraction_width) := (others => '0'); + result (exponent_width -1 downto 0) := (others => '1'); + return result; + elsif (denormalize and + (exp + in_fraction_width <= -resize(expon_base, exp'length))) then + exp := -resize(expon_base, exp'length); + -- shift by a constant + arg_int := shift_left (arg_int, + (arg_int'high + to_integer(expon_base) + + in_fraction_width - 1)); + if (arg_int'high > fraction_width) then + fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width)); + round := check_round ( + fract_in => arg_int(arg_int'high-fraction_width), + sign => result(result'high), + remainder => arg_int((arg_int'high-fraction_width-1) + downto 0), + round_style => round_style); + if (round) then + fp_round (fract_in => arg_int (arg_int'high-1 downto + (arg_int'high-fraction_width)), + expon_in => exp, + fract_out => fract, + expon_out => exptmp); + exp := exptmp; + end if; + else + fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) := + arg_int (arg_int'high-1 downto 0); + end if; + else + arg_int := shift_left (arg_int, arg_int'high-to_integer(exp)); + exp := exp + in_fraction_width; + if (arg_int'high > fraction_width) then + fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width)); + round := check_round ( + fract_in => fract(0), + sign => result(result'high), + remainder => arg_int((arg_int'high-fraction_width-1) + downto 0), + round_style => round_style); + if (round) then + fp_round (fract_in => fract, + expon_in => exp, + fract_out => fracttmp, + expon_out => exptmp); + fract := fracttmp; + exp := exptmp; + end if; + else + fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) := + arg_int (arg_int'high-1 downto 0); + end if; + end if; + expon := UNSIGNED (resize(exp-1, exponent_width)); + expon(exponent_width-1) := not expon(exponent_width-1); + result (exponent_width-1 downto 0) := UNRESOLVED_float(expon); + result (-1 downto -fraction_width) := UNRESOLVED_float(fract); + end if; + return result; + end function to_float; + + -- size_res functions + -- Integer to float + function to_float ( + arg : INTEGER; + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style) -- rounding option + return UNRESOLVED_float is + variable result : UNRESOLVED_float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style); + return result; + end if; + end function to_float; + + -- real to float + function to_float ( + arg : REAL; + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + variable result : UNRESOLVED_float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style, + denormalize => denormalize); + return result; + end if; + end function to_float; + + -- unsigned to float + function to_float ( + arg : UNSIGNED; + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style) -- rounding option + return UNRESOLVED_float is + variable result : UNRESOLVED_float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style); + return result; + end if; + end function to_float; + + -- signed to float + function to_float ( + arg : SIGNED; + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style) -- rounding + return UNRESOLVED_float is + variable result : UNRESOLVED_float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style); + return result; + end if; + end function to_float; + + -- std_ulogic_vector to float + function to_float ( + arg : STD_ULOGIC_VECTOR; + size_res : UNRESOLVED_float) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low); + return result; + end if; + end function to_float; + + -- unsigned fixed point to float + function to_float ( + arg : UNRESOLVED_ufixed; -- unsigned fixed point input + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions + return UNRESOLVED_float is + variable result : UNRESOLVED_float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style, + denormalize => denormalize); + return result; + end if; + end function to_float; + + -- signed fixed point to float + function to_float ( + arg : UNRESOLVED_sfixed; + size_res : UNRESOLVED_float; + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- rounding option + return UNRESOLVED_float is + variable result : UNRESOLVED_float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style, + denormalize => denormalize); + return result; + end if; + end function to_float; + + -- to_integer (float) + function to_integer ( + arg : UNRESOLVED_float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error) -- check for errors + return INTEGER is + variable validfp : valid_fpstate; -- Valid FP state + variable frac : UNSIGNED (-arg'low downto 0); -- Fraction + variable fract : UNSIGNED (1-arg'low downto 0); -- Fraction + variable expon : SIGNED (arg'high-1 downto 0); + variable isign : STD_ULOGIC; -- internal version of sign + variable round : STD_ULOGIC; -- is rounding needed? + variable result : INTEGER; + variable base : INTEGER; -- Integer exponent + begin + validfp := classfp (arg, check_error); + classcase : case validfp is + when isx | nan | quiet_nan | pos_zero | neg_zero | pos_denormal | neg_denormal => + result := 0; -- return 0 + when pos_inf => + result := INTEGER'high; + when neg_inf => + result := INTEGER'low; + when others => + break_number ( + arg => arg, + fptyp => validfp, + denormalize => false, + fract => frac, + expon => expon); + fract (fract'high) := '0'; -- Add extra bit for 0.6 case + fract (fract'high-1 downto 0) := frac; + isign := to_x01 (arg (arg'high)); + base := to_integer (expon) + 1; + if base < -1 then + result := 0; + elsif base >= frac'high then + result := to_integer (fract) * 2**(base - frac'high); + else -- We need to round + if base = -1 then -- trap for 0.6 case. + result := 0; + else + result := to_integer (fract (frac'high downto frac'high-base)); + end if; + -- rounding routine + case round_style is + when round_nearest => + if frac'high - base > 1 then + round := fract (frac'high - base - 1) and + (fract (frac'high - base) + or (or_reduce (fract (frac'high - base - 2 downto 0)))); + else + round := fract (frac'high - base - 1) and + fract (frac'high - base); + end if; + when round_inf => + round := fract(frac'high - base - 1) and not isign; + when round_neginf => + round := fract(frac'high - base - 1) and isign; + when others => + round := '0'; + end case; + if round = '1' then + result := result + 1; + end if; + end if; + if isign = '1' then + result := - result; + end if; + end case classcase; + return result; + end function to_integer; + + -- to_unsigned (float) + function to_unsigned ( + arg : UNRESOLVED_float; -- floating point input + constant size : NATURAL; -- length of output + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error) -- check for errors + return UNSIGNED is + variable validfp : valid_fpstate; -- Valid FP state + variable frac : UNSIGNED (size-1 downto 0); -- Fraction + variable sign : STD_ULOGIC; -- not used + begin + validfp := classfp (arg, check_error); + classcase : case validfp is + when isx | nan | quiet_nan => + frac := (others => 'X'); + when pos_zero | neg_inf | neg_zero | neg_normal | pos_denormal | neg_denormal => + frac := (others => '0'); -- return 0 + when pos_inf => + frac := (others => '1'); + when others => + float_to_unsigned ( + arg => arg, + frac => frac, + sign => sign, + denormalize => false, + bias => 0, + round_style => round_style); + end case classcase; + return (frac); + end function to_unsigned; + + -- to_signed (float) + function to_signed ( + arg : UNRESOLVED_float; -- floating point input + constant size : NATURAL; -- length of output + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error) -- check for errors + return SIGNED is + variable sign : STD_ULOGIC; -- true if negative + variable validfp : valid_fpstate; -- Valid FP state + variable frac : UNSIGNED (size-1 downto 0); -- Fraction + variable result : SIGNED (size-1 downto 0); + begin + validfp := classfp (arg, check_error); + classcase : case validfp is + when isx | nan | quiet_nan => + result := (others => 'X'); + when pos_zero | neg_zero | pos_denormal | neg_denormal => + result := (others => '0'); -- return 0 + when pos_inf => + result := (others => '1'); + result (result'high) := '0'; + when neg_inf => + result := (others => '0'); + result (result'high) := '1'; + when others => + float_to_unsigned ( + arg => arg, + sign => sign, + frac => frac, + denormalize => false, + bias => 0, + round_style => round_style); + result (size-1) := '0'; + result (size-2 downto 0) := SIGNED(frac (size-2 downto 0)); + if sign = '1' then + -- Because the most negative signed number is 1 less than the most + -- positive signed number, we need this code. + if frac(frac'high) = '1' then -- return most negative number + result := (others => '0'); + result (result'high) := '1'; + else + result := -result; + end if; + else + if frac(frac'high) = '1' then -- return most positive number + result := (others => '1'); + result (result'high) := '0'; + end if; + end if; + end case classcase; + return result; + end function to_signed; + + -- purpose: Converts a float to ufixed + function to_ufixed ( + arg : UNRESOLVED_float; -- fp input + constant left_index : INTEGER; -- integer part + constant right_index : INTEGER; -- fraction part + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate + constant round_style : fixed_round_style_type := fixed_round_style; -- rounding + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return UNRESOLVED_ufixed is + constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : INTEGER := arg'high; -- length of FP output exponent + constant size : INTEGER := left_index - right_index + 4; -- unsigned size + variable expon_base : INTEGER; -- exponent offset + variable validfp : valid_fpstate; -- Valid FP state + variable exp : INTEGER; -- Exponent + variable expon : UNSIGNED (exponent_width-1 downto 0); -- Vectorized exponent + -- Base to divide fraction by + variable frac : UNSIGNED (size-1 downto 0) := (others => '0'); -- Fraction + variable frac_shift : UNSIGNED (size-1 downto 0); -- Fraction shifted + variable shift : INTEGER; + variable result_big : UNRESOLVED_ufixed (left_index downto right_index-3); + variable result : UNRESOLVED_ufixed (left_index downto right_index); -- result + begin -- function to_ufixed + validfp := classfp (arg, check_error); + classcase : case validfp is + when isx | nan | quiet_nan => + frac := (others => 'X'); + when pos_zero | neg_inf | neg_zero | neg_normal | neg_denormal => + frac := (others => '0'); -- return 0 + when pos_inf => + frac := (others => '1'); -- always saturate + when others => + expon_base := 2**(exponent_width-1) -1; -- exponent offset + -- Figure out the fraction + if (validfp = pos_denormal) and denormalize then + exp := -expon_base +1; + frac (frac'high) := '0'; -- Remove the "1.0". + else + -- exponent /= '0', normal floating point + expon := UNSIGNED(arg (exponent_width-1 downto 0)); + expon(exponent_width-1) := not expon(exponent_width-1); + exp := to_integer (SIGNED(expon)) +1; + frac (frac'high) := '1'; -- Add the "1.0". + end if; + shift := (frac'high - 3 + right_index) - exp; + if fraction_width > frac'high then -- Can only use size-2 bits + frac (frac'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto + -frac'high))); + else -- can use all bits + frac (frac'high-1 downto frac'high-fraction_width) := + UNSIGNED (to_slv (arg(-1 downto -fraction_width))); + end if; + frac_shift := frac srl shift; + if shift < 0 then -- Overflow + frac := (others => '1'); + else + frac := frac_shift; + end if; + end case classcase; + result_big := to_ufixed ( + arg => STD_ULOGIC_VECTOR(frac), + left_index => left_index, + right_index => (right_index-3)); + result := resize (arg => result_big, + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_ufixed; + + -- purpose: Converts a float to sfixed + function to_sfixed ( + arg : UNRESOLVED_float; -- fp input + constant left_index : INTEGER; -- integer part + constant right_index : INTEGER; -- fraction part + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate + constant round_style : fixed_round_style_type := fixed_round_style; -- rounding + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return UNRESOLVED_sfixed is + constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : INTEGER := arg'high; -- length of FP output exponent + constant size : INTEGER := left_index - right_index + 4; -- unsigned size + variable expon_base : INTEGER; -- exponent offset + variable validfp : valid_fpstate; -- Valid FP state + variable exp : INTEGER; -- Exponent + variable sign : BOOLEAN; -- true if negative + variable expon : UNSIGNED (exponent_width-1 downto 0); -- Vectorized exponent + -- Base to divide fraction by + variable frac : UNSIGNED (size-2 downto 0) := (others => '0'); -- Fraction + variable frac_shift : UNSIGNED (size-2 downto 0); -- Fraction shifted + variable shift : INTEGER; + variable rsigned : SIGNED (size-1 downto 0); -- signed version of result + variable result_big : UNRESOLVED_sfixed (left_index downto right_index-3); + variable result : UNRESOLVED_sfixed (left_index downto right_index) + := (others => '0'); -- result + begin -- function to_sfixed + validfp := classfp (arg, check_error); + classcase : case validfp is + when isx | nan | quiet_nan => + result := (others => 'X'); + when pos_zero | neg_zero => + result := (others => '0'); -- return 0 + when neg_inf => + result (left_index) := '1'; -- return smallest negative number + when pos_inf => + result := (others => '1'); -- return largest number + result (left_index) := '0'; + when others => + expon_base := 2**(exponent_width-1) -1; -- exponent offset + if arg(exponent_width) = '0' then + sign := false; + else + sign := true; + end if; + -- Figure out the fraction + if (validfp = pos_denormal or validfp = neg_denormal) + and denormalize then + exp := -expon_base +1; + frac (frac'high) := '0'; -- Add the "1.0". + else + -- exponent /= '0', normal floating point + expon := UNSIGNED(arg (exponent_width-1 downto 0)); + expon(exponent_width-1) := not expon(exponent_width-1); + exp := to_integer (SIGNED(expon)) +1; + frac (frac'high) := '1'; -- Add the "1.0". + end if; + shift := (frac'high - 3 + right_index) - exp; + if fraction_width > frac'high then -- Can only use size-2 bits + frac (frac'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto + -frac'high))); + else -- can use all bits + frac (frac'high-1 downto frac'high-fraction_width) := + UNSIGNED (to_slv (arg(-1 downto -fraction_width))); + end if; + frac_shift := frac srl shift; + if shift < 0 then -- Overflow + frac := (others => '1'); + else + frac := frac_shift; + end if; + if not sign then + rsigned := SIGNED("0" & frac); + else + rsigned := -(SIGNED("0" & frac)); + end if; + result_big := to_sfixed ( + arg => STD_LOGIC_VECTOR(rsigned), + left_index => left_index, + right_index => (right_index-3)); + result := resize (arg => result_big, + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + end case classcase; + return result; + end function to_sfixed; + + -- size_res versions + -- float to unsigned + function to_unsigned ( + arg : UNRESOLVED_float; -- floating point input + size_res : UNSIGNED; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error) -- check for errors + return UNSIGNED is + variable result : UNSIGNED (size_res'range); + begin + if (SIZE_RES'length = 0) then + return result; + else + result := to_unsigned ( + arg => arg, + size => size_res'length, + round_style => round_style, + check_error => check_error); + return result; + end if; + end function to_unsigned; + + -- float to signed + function to_signed ( + arg : UNRESOLVED_float; -- floating point input + size_res : SIGNED; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error) -- check for errors + return SIGNED is + variable result : SIGNED (size_res'range); + begin + if (SIZE_RES'length = 0) then + return result; + else + result := to_signed ( + arg => arg, + size => size_res'length, + round_style => round_style, + check_error => check_error); + return result; + end if; + end function to_signed; + + -- purpose: Converts a float to unsigned fixed point + function to_ufixed ( + arg : UNRESOLVED_float; -- fp input + size_res : UNRESOLVED_ufixed; + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate + constant round_style : fixed_round_style_type := fixed_round_style; -- rounding + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_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, + overflow_style => overflow_style, + round_style => round_style, + check_error => check_error, + denormalize => denormalize); + return result; + end if; + end function to_ufixed; + + -- float to signed fixed point + function to_sfixed ( + arg : UNRESOLVED_float; -- fp input + size_res : UNRESOLVED_sfixed; + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate + constant round_style : fixed_round_style_type := fixed_round_style; -- rounding + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_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, + overflow_style => overflow_style, + round_style => round_style, + check_error => check_error, + denormalize => denormalize); + return result; + end if; + end function to_sfixed; + + -- to_real (float) + -- typically not Synthesizable unless the input is a constant. + function to_real ( + arg : UNRESOLVED_float; -- floating point input + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return REAL is + constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : INTEGER := arg'high; -- length of FP output exponent + variable sign : REAL; -- Sign, + or - 1 + variable exp : INTEGER; -- Exponent + variable expon_base : INTEGER; -- exponent offset + variable frac : REAL := 0.0; -- Fraction + variable validfp : valid_fpstate; -- Valid FP state + variable expon : UNSIGNED (exponent_width - 1 downto 0) + := (others => '1'); -- Vectorized exponent + begin + validfp := classfp (arg, check_error); + classcase : case validfp is + when isx | pos_zero | neg_zero | nan | quiet_nan => + return 0.0; + when neg_inf => + return REAL'low; -- Negative infinity. + when pos_inf => + return REAL'high; -- Positive infinity + when others => + expon_base := 2**(exponent_width-1) -1; + if to_X01(arg(exponent_width)) = '0' then + sign := 1.0; + else + sign := -1.0; + end if; + -- Figure out the fraction + for i in 0 to fraction_width-1 loop + if to_X01(arg (-1 - i)) = '1' then + frac := frac + (2.0 **(-1 - i)); + end if; + end loop; -- i + if validfp = pos_normal or validfp = neg_normal or not denormalize then + -- exponent /= '0', normal floating point + expon := UNSIGNED(arg (exponent_width-1 downto 0)); + expon(exponent_width-1) := not expon(exponent_width-1); + exp := to_integer (SIGNED(expon)) +1; + sign := sign * (2.0 ** exp) * (1.0 + frac); + else -- exponent = '0', IEEE extended floating point + exp := 1 - expon_base; + sign := sign * (2.0 ** exp) * frac; + end if; + return sign; + end case classcase; + end function to_real; + + -- For Verilog compatability + function realtobits (arg : REAL) return STD_ULOGIC_VECTOR is + variable result : float64; -- 64 bit floating point + begin + result := to_float (arg => arg, + exponent_width => float64'high, + fraction_width => -float64'low); + return to_sulv (result); + end function realtobits; + + function bitstoreal (arg : STD_ULOGIC_VECTOR) return REAL is + variable arg64 : float64; -- arg converted to float + begin + arg64 := to_float (arg => arg, + exponent_width => float64'high, + fraction_width => -float64'low); + return to_real (arg64); + end function bitstoreal; + + -- purpose: Removes meta-logical values from FP string + function to_01 ( + arg : UNRESOLVED_float; -- floating point input + XMAP : STD_LOGIC := '0') + return UNRESOLVED_float is + variable result : UNRESOLVED_float (arg'range); + begin -- function to_01 + if (arg'length < 1) then + assert NO_WARNING + report "float_pkg:" + & "TO_01: null detected, returning NULL" + severity warning; + return NAFP; + end if; + result := UNRESOLVED_float (STD_LOGIC_VECTOR(to_01(UNSIGNED(to_slv(arg)), XMAP))); + return result; + end function to_01; + + function Is_X + (arg : UNRESOLVED_float) + return BOOLEAN is + begin + return Is_X (to_slv(arg)); + end function Is_X; + + function to_X01 (arg : UNRESOLVED_float) return UNRESOLVED_float is + variable result : UNRESOLVED_float (arg'range); + begin + if (arg'length < 1) then + assert NO_WARNING + report "float_pkg:" + & "TO_X01: null detected, returning NULL" + severity warning; + return NAFP; + else + result := UNRESOLVED_float (to_X01(to_slv(arg))); + return result; + end if; + end function to_X01; + + function to_X01Z (arg : UNRESOLVED_float) return UNRESOLVED_float is + variable result : UNRESOLVED_float (arg'range); + begin + if (arg'length < 1) then + assert NO_WARNING + report "float_pkg:" + & "TO_X01Z: null detected, returning NULL" + severity warning; + return NAFP; + else + result := UNRESOLVED_float (to_X01Z(to_slv(arg))); + return result; + end if; + end function to_X01Z; + + function to_UX01 (arg : UNRESOLVED_float) return UNRESOLVED_float is + variable result : UNRESOLVED_float (arg'range); + begin + if (arg'length < 1) then + assert NO_WARNING + report "float_pkg:" + & "TO_UX01: null detected, returning NULL" + severity warning; + return NAFP; + else + result := UNRESOLVED_float (to_UX01(to_slv(arg))); + return result; + end if; + end function to_UX01; + + -- These allows the base math functions to use the default values + -- of their parameters. Thus they do full IEEE floating point. + function "+" (l, r : UNRESOLVED_float) return UNRESOLVED_float is + begin + return add (l, r); + end function "+"; + + function "-" (l, r : UNRESOLVED_float) return UNRESOLVED_float is + begin + return subtract (l, r); + end function "-"; + + function "*" (l, r : UNRESOLVED_float) return UNRESOLVED_float is + begin + return multiply (l, r); + end function "*"; + + function "/" (l, r : UNRESOLVED_float) return UNRESOLVED_float is + begin + return divide (l, r); + end function "/"; + +-- function "rem" (l, r : UNRESOLVED_float) return UNRESOLVED_float is +-- begin +-- return remainder (l, r); +-- end function "rem"; + +-- function "mod" (l, r : UNRESOLVED_float) return UNRESOLVED_float is +-- begin +-- return modulo (l, r); +-- end function "mod"; + + -- overloaded versions + function "+" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return add (l, r_float); + end function "+"; + + function "+" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return add (l_float, r); + end function "+"; + + function "+" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return add (l, r_float); + end function "+"; + + function "+" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return add (l_float, r); + end function "+"; + + function "-" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return subtract (l, r_float); + end function "-"; + + function "-" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return subtract (l_float, r); + end function "-"; + + function "-" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return subtract (l, r_float); + end function "-"; + + function "-" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return subtract (l_float, r); + end function "-"; + + function "*" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return multiply (l, r_float); + end function "*"; + + function "*" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return multiply (l_float, r); + end function "*"; + + function "*" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return multiply (l, r_float); + end function "*"; + + function "*" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return multiply (l_float, r); + end function "*"; + + function "/" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return divide (l, r_float); + end function "/"; + + function "/" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return divide (l_float, r); + end function "/"; + + function "/" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return divide (l, r_float); + end function "/"; + + function "/" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return divide (l_float, r); + end function "/"; + +-- function "rem" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is +-- variable r_float : UNRESOLVED_float (l'range); +-- begin +-- r_float := to_float (r, l'high, -l'low); +-- return remainder (l, r_float); +-- end function "rem"; + +-- function "rem" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is +-- variable l_float : UNRESOLVED_float (r'range); +-- begin +-- l_float := to_float(l, r'high, -r'low); +-- return remainder (l_float, r); +-- end function "rem"; + +-- function "rem" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is +-- variable r_float : UNRESOLVED_float (l'range); +-- begin +-- r_float := to_float (r, l'high, -l'low); +-- return remainder (l, r_float); +-- end function "rem"; + +-- function "rem" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is +-- variable l_float : UNRESOLVED_float (r'range); +-- begin +-- l_float := to_float(l, r'high, -r'low); +-- return remainder (l_float, r); +-- end function "rem"; + +-- function "mod" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is +-- variable r_float : UNRESOLVED_float (l'range); +-- begin +-- r_float := to_float (r, l'high, -l'low); +-- return modulo (l, r_float); +-- end function "mod"; + +-- function "mod" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is +-- variable l_float : UNRESOLVED_float (r'range); +-- begin +-- l_float := to_float(l, r'high, -r'low); +-- return modulo (l_float, r); +-- end function "mod"; + +-- function "mod" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is +-- variable r_float : UNRESOLVED_float (l'range); +-- begin +-- r_float := to_float (r, l'high, -l'low); +-- return modulo (l, r_float); +-- end function "mod"; + +-- function "mod" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is +-- variable l_float : UNRESOLVED_float (r'range); +-- begin +-- l_float := to_float(l, r'high, -r'low); +-- return modulo (l_float, r); +-- end function "mod"; + + function "=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return eq (l, r_float); + end function "="; + + function "/=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return ne (l, r_float); + end function "/="; + + function ">=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return ge (l, r_float); + end function ">="; + + function "<=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return le (l, r_float); + end function "<="; + + function ">" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return gt (l, r_float); + end function ">"; + + function "<" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return lt (l, r_float); + end function "<"; + + function "=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return eq (l_float, r); + end function "="; + + function "/=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return ne (l_float, r); + end function "/="; + + function ">=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return ge (l_float, r); + end function ">="; + + function "<=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return le (l_float, r); + end function "<="; + + function ">" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return gt (l_float, r); + end function ">"; + + function "<" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return lt (l_float, r); + end function "<"; + + function "=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return eq (l, r_float); + end function "="; + + function "/=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return ne (l, r_float); + end function "/="; + + function ">=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return ge (l, r_float); + end function ">="; + + function "<=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return le (l, r_float); + end function "<="; + + function ">" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return gt (l, r_float); + end function ">"; + + function "<" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return lt (l, r_float); + end function "<"; + + function "=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return eq (l_float, r); + end function "="; + + function "/=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return ne (l_float, r); + end function "/="; + + function ">=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return ge (l_float, r); + end function ">="; + + function "<=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return le (l_float, r); + end function "<="; + + function ">" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return gt (l_float, r); + end function ">"; + + function "<" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float(l, r'high, -r'low); + return lt (l_float, r); + end function "<"; + + -- ?= overloads + function \?=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?=\ (l, r_float); + end function \?=\; + + function \?/=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?/=\ (l, r_float); + end function \?/=\; + + function \?>\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?>\ (l, r_float); + end function \?>\; + + function \?>=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?>=\ (l, r_float); + end function \?>=\; + + function \?<\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?<\ (l, r_float); + end function \?<\; + + function \?<=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?<=\ (l, r_float); + end function \?<=\; + + -- real and float + function \?=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?=\ (l_float, r); + end function \?=\; + + function \?/=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?/=\ (l_float, r); + end function \?/=\; + + function \?>\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?>\ (l_float, r); + end function \?>\; + + function \?>=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?>=\ (l_float, r); + end function \?>=\; + + function \?<\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?<\ (l_float, r); + end function \?<\; + + function \?<=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?<=\ (l_float, r); + end function \?<=\; + + -- ?= overloads + function \?=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?=\ (l, r_float); + end function \?=\; + + function \?/=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?/=\ (l, r_float); + end function \?/=\; + + function \?>\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?>\ (l, r_float); + end function \?>\; + + function \?>=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?>=\ (l, r_float); + end function \?>=\; + + function \?<\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?<\ (l, r_float); + end function \?<\; + + function \?<=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return \?<=\ (l, r_float); + end function \?<=\; + + -- integer and float + function \?=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?=\ (l_float, r); + end function \?=\; + + function \?/=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?/=\ (l_float, r); + end function \?/=\; + + function \?>\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?>\ (l_float, r); + end function \?>\; + + function \?>=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?>=\ (l_float, r); + end function \?>=\; + + function \?<\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?<\ (l_float, r); + end function \?<\; + + function \?<=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return \?<=\ (l_float, r); + end function \?<=\; + + -- minimum and maximum overloads + function minimum (l : UNRESOLVED_float; r : REAL) + return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return minimum (l, r_float); + end function minimum; + + function maximum (l : UNRESOLVED_float; r : REAL) + return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return maximum (l, r_float); + end function maximum; + + function minimum (l : REAL; r : UNRESOLVED_float) + return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return minimum (l_float, r); + end function minimum; + + function maximum (l : REAL; r : UNRESOLVED_float) + return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return maximum (l_float, r); + end function maximum; + + function minimum (l : UNRESOLVED_float; r : INTEGER) + return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return minimum (l, r_float); + end function minimum; + + function maximum (l : UNRESOLVED_float; r : INTEGER) + return UNRESOLVED_float is + variable r_float : UNRESOLVED_float (l'range); + begin + r_float := to_float (r, l'high, -l'low); + return maximum (l, r_float); + end function maximum; + + function minimum (l : INTEGER; r : UNRESOLVED_float) + return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return minimum (l_float, r); + end function minimum; + + function maximum (l : INTEGER; r : UNRESOLVED_float) + return UNRESOLVED_float is + variable l_float : UNRESOLVED_float (r'range); + begin + l_float := to_float (l, r'high, -r'low); + return maximum (l_float, r); + end function maximum; + + ---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + function "not" (L : UNRESOLVED_float) return UNRESOLVED_float is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + RESULT := not to_sulv(L); + return to_float (RESULT, L'high, -L'low); + end function "not"; + + function "and" (L, R : UNRESOLVED_float) return UNRESOLVED_float is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) and to_sulv(R); + else + assert NO_WARNING + report "float_pkg:" + & """and"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_float (RESULT, L'high, -L'low); + end function "and"; + + function "or" (L, R : UNRESOLVED_float) return UNRESOLVED_float is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) or to_sulv(R); + else + assert NO_WARNING + report "float_pkg:" + & """or"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_float (RESULT, L'high, -L'low); + end function "or"; + + function "nand" (L, R : UNRESOLVED_float) return UNRESOLVED_float is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) nand to_sulv(R); + else + assert NO_WARNING + report "float_pkg:" + & """nand"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_float (RESULT, L'high, -L'low); + end function "nand"; + + function "nor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) nor to_sulv(R); + else + assert NO_WARNING + report "float_pkg:" + & """nor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_float (RESULT, L'high, -L'low); + end function "nor"; + + function "xor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) xor to_sulv(R); + else + assert NO_WARNING + report "float_pkg:" + & """xor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_float (RESULT, L'high, -L'low); + end function "xor"; + + function "xnor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) xnor to_sulv(R); + else + assert NO_WARNING + report "float_pkg:" + & """xnor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_float (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 : UNRESOLVED_float) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (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 : UNRESOLVED_float; R : STD_ULOGIC) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (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 : UNRESOLVED_float) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (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 : UNRESOLVED_float; R : STD_ULOGIC) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (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 : UNRESOLVED_float) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (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 : UNRESOLVED_float; R : STD_ULOGIC) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (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 : UNRESOLVED_float) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (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 : UNRESOLVED_float; R : STD_ULOGIC) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (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 : UNRESOLVED_float) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (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 : UNRESOLVED_float; R : STD_ULOGIC) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (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 : UNRESOLVED_float) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (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 : UNRESOLVED_float; R : STD_ULOGIC) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (L'range); + begin + for i in result'range loop + result(i) := L(i) xnor R; + end loop; + return result; + end function "xnor"; + + -- Reduction operator_reduces, same as numeric_std functions + + function and_reduce (l : UNRESOLVED_float) return STD_ULOGIC is + begin + return and_reduce (to_sulv(l)); + end function and_reduce; + + function nand_reduce (l : UNRESOLVED_float) return STD_ULOGIC is + begin + return nand_reduce (to_sulv(l)); + end function nand_reduce; + + function or_reduce (l : UNRESOLVED_float) return STD_ULOGIC is + begin + return or_reduce (to_sulv(l)); + end function or_reduce; + + function nor_reduce (l : UNRESOLVED_float) return STD_ULOGIC is + begin + return nor_reduce (to_sulv(l)); + end function nor_reduce; + + function xor_reduce (l : UNRESOLVED_float) return STD_ULOGIC is + begin + return xor_reduce (to_sulv(l)); + end function xor_reduce; + + function xnor_reduce (l : UNRESOLVED_float) return STD_ULOGIC is + begin + return xnor_reduce (to_sulv(l)); + end function xnor_reduce; + + ----------------------------------------------------------------------------- + -- Recommended Functions from the IEEE 754 Appendix + ----------------------------------------------------------------------------- + -- returns x with the sign of y. + function Copysign ( + x, y : UNRESOLVED_float) -- floating point input + return UNRESOLVED_float is + begin + return y(y'high) & x (x'high-1 downto x'low); + end function Copysign; + + -- Returns y * 2**n for integral values of N without computing 2**n + function Scalb ( + y : UNRESOLVED_float; -- floating point input + N : INTEGER; -- exponent to add + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + constant fraction_width : NATURAL := -mine(y'low, y'low); -- length of FP output fraction + constant exponent_width : NATURAL := y'high; -- length of FP output exponent + variable arg, result : UNRESOLVED_float (exponent_width downto -fraction_width); -- internal argument + variable expon : SIGNED (exponent_width-1 downto 0); -- Vectorized exp + variable exp : SIGNED (exponent_width downto 0); + variable ufract : UNSIGNED (fraction_width downto 0); + constant expon_base : SIGNED (exponent_width-1 downto 0) + := gen_expon_base(exponent_width); -- exponent offset + variable fptype : valid_fpstate; + begin + -- This can be done by simply adding N to the exponent. + arg := to_01 (y, 'X'); + fptype := classfp(arg, check_error); + classcase : case fptype is + when isx => + result := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + result := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when others => + break_number ( + arg => arg, + fptyp => fptype, + denormalize => denormalize, + fract => ufract, + expon => expon); + exp := resize (expon, exp'length) + N; + result := normalize ( + fract => ufract, + expon => exp, + sign => to_x01 (arg (arg'high)), + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => 0); + end case classcase; + return result; + end function Scalb; + + -- Returns y * 2**n for integral values of N without computing 2**n + function Scalb ( + y : UNRESOLVED_float; -- floating point input + N : SIGNED; -- exponent to add + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return UNRESOLVED_float is + variable n_int : INTEGER; + begin + n_int := to_integer(N); + return Scalb (y => y, + N => n_int, + round_style => round_style, + check_error => check_error, + denormalize => denormalize); + end function Scalb; + + -- returns the unbiased exponent of x + function Logb ( + x : UNRESOLVED_float) -- floating point input + return INTEGER is + constant fraction_width : NATURAL := -mine (x'low, x'low); -- length of FP output fraction + constant exponent_width : NATURAL := x'high; -- length of FP output exponent + variable result : INTEGER; -- result + variable arg : UNRESOLVED_float (exponent_width downto -fraction_width); -- internal argument + variable expon : SIGNED (exponent_width - 1 downto 0); + variable fract : UNSIGNED (fraction_width downto 0); + constant expon_base : INTEGER := 2**(exponent_width-1) -1; -- exponent + -- offset +1 + variable fptype : valid_fpstate; + begin + -- Just return the exponent. + arg := to_01 (x, 'X'); + fptype := classfp(arg); + classcase : case fptype is + when isx | nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + result := 0; + when pos_denormal | neg_denormal => + fract (fraction_width) := '0'; + fract (fraction_width-1 downto 0) := + UNSIGNED (to_slv(arg(-1 downto -fraction_width))); + result := find_leftmost (fract, '1') -- Find the first "1" + - fraction_width; -- subtract the length we want + result := -expon_base + 1 + result; + when others => + expon := SIGNED(arg (exponent_width - 1 downto 0)); + expon(exponent_width-1) := not expon(exponent_width-1); + expon := expon + 1; + result := to_integer (expon); + end case classcase; + return result; + end function Logb; + + -- returns the unbiased exponent of x + function Logb ( + x : UNRESOLVED_float) -- floating point input + return SIGNED is + constant exponent_width : NATURAL := x'high; -- length of FP output exponent + variable result : SIGNED (exponent_width - 1 downto 0); -- result + begin + -- Just return the exponent. + result := to_signed (Logb (x), exponent_width); + return result; + end function Logb; + + -- returns the next representable neighbor of x in the direction toward y +-- function Nextafter ( +-- x, y : UNRESOLVED_float; -- floating point input +-- constant check_error : BOOLEAN := float_check_error; -- check for errors +-- constant denormalize : BOOLEAN := float_denormalize) +-- return UNRESOLVED_float is +-- constant fraction_width : NATURAL := -mine(x'low, x'low); -- length of FP output fraction +-- constant exponent_width : NATURAL := x'high; -- length of FP output exponent +-- function "=" ( +-- l, r : UNRESOLVED_float) -- inputs +-- return BOOLEAN is +-- begin -- function "=" +-- return eq (l => l, +-- r => r, +-- check_error => false); +-- end function "="; +-- function ">" ( +-- l, r : UNRESOLVED_float) -- inputs +-- return BOOLEAN is +-- begin -- function ">" +-- return gt (l => l, +-- r => r, +-- check_error => false); +-- end function ">"; +-- variable fract : UNSIGNED (fraction_width-1 downto 0); +-- variable expon : UNSIGNED (exponent_width-1 downto 0); +-- variable sign : STD_ULOGIC; +-- variable result : UNRESOLVED_float (exponent_width downto -fraction_width); +-- variable validfpx, validfpy : valid_fpstate; -- Valid FP state +-- begin -- fp_Nextafter +-- -- If Y > X, add one to the fraction, otherwise subtract. +-- validfpx := classfp (x, check_error); +-- validfpy := classfp (y, check_error); +-- if validfpx = isx or validfpy = isx then +-- result := (others => 'X'); +-- return result; +-- elsif (validfpx = nan or validfpy = nan) then +-- return nanfp (fraction_width => fraction_width, +-- exponent_width => exponent_width); +-- elsif (validfpx = quiet_nan or validfpy = quiet_nan) then +-- return qnanfp (fraction_width => fraction_width, +-- exponent_width => exponent_width); +-- elsif x = y then -- Return X +-- return x; +-- else +-- fract := UNSIGNED (to_slv (x (-1 downto -fraction_width))); -- Fraction +-- expon := UNSIGNED (x (exponent_width - 1 downto 0)); -- exponent +-- sign := x(exponent_width); -- sign bit +-- if (y > x) then +-- -- Increase the number given +-- if validfpx = neg_inf then +-- -- return most negative number +-- expon := (others => '1'); +-- expon (0) := '0'; +-- fract := (others => '1'); +-- elsif validfpx = pos_zero or validfpx = neg_zero then +-- -- return smallest denormal number +-- sign := '0'; +-- expon := (others => '0'); +-- fract := (others => '0'); +-- fract(0) := '1'; +-- elsif validfpx = pos_normal then +-- if and_reduce (fract) = '1' then -- fraction is all "1". +-- if and_reduce (expon (exponent_width-1 downto 1)) = '1' +-- and expon (0) = '0' then +-- -- Exponent is one away from infinity. +-- assert NO_WARNING +-- report "float_pkg:" +-- & "FP_NEXTAFTER: NextAfter overflow" +-- severity warning; +-- return pos_inffp (fraction_width => fraction_width, +-- exponent_width => exponent_width); +-- else +-- expon := expon + 1; +-- fract := (others => '0'); +-- end if; +-- else +-- fract := fract + 1; +-- end if; +-- elsif validfpx = pos_denormal then +-- if and_reduce (fract) = '1' then -- fraction is all "1". +-- -- return smallest possible normal number +-- expon := (others => '0'); +-- expon(0) := '1'; +-- fract := (others => '0'); +-- else +-- fract := fract + 1; +-- end if; +-- elsif validfpx = neg_normal then +-- if or_reduce (fract) = '0' then -- fraction is all "0". +-- if or_reduce (expon (exponent_width-1 downto 1)) = '0' and +-- expon (0) = '1' then -- Smallest exponent +-- -- return the largest negative denormal number +-- expon := (others => '0'); +-- fract := (others => '1'); +-- else +-- expon := expon - 1; +-- fract := (others => '1'); +-- end if; +-- else +-- fract := fract - 1; +-- end if; +-- elsif validfpx = neg_denormal then +-- if or_reduce (fract(fract'high downto 1)) = '0' +-- and fract (0) = '1' then -- Smallest possible fraction +-- return zerofp (fraction_width => fraction_width, +-- exponent_width => exponent_width); +-- else +-- fract := fract - 1; +-- end if; +-- end if; +-- else +-- -- Decrease the number +-- if validfpx = pos_inf then +-- -- return most positive number +-- expon := (others => '1'); +-- expon (0) := '0'; +-- fract := (others => '1'); +-- elsif validfpx = pos_zero +-- or classfp (x) = neg_zero then +-- -- return smallest negative denormal number +-- sign := '1'; +-- expon := (others => '0'); +-- fract := (others => '0'); +-- fract(0) := '1'; +-- elsif validfpx = neg_normal then +-- if and_reduce (fract) = '1' then -- fraction is all "1". +-- if and_reduce (expon (exponent_width-1 downto 1)) = '1' +-- and expon (0) = '0' then +-- -- Exponent is one away from infinity. +-- assert NO_WARNING +-- report "float_pkg:" +-- & "FP_NEXTAFTER: NextAfter overflow" +-- severity warning; +-- return neg_inffp (fraction_width => fraction_width, +-- exponent_width => exponent_width); +-- else +-- expon := expon + 1; -- Fraction overflow +-- fract := (others => '0'); +-- end if; +-- else +-- fract := fract + 1; +-- end if; +-- elsif validfpx = neg_denormal then +-- if and_reduce (fract) = '1' then -- fraction is all "1". +-- -- return smallest possible normal number +-- expon := (others => '0'); +-- expon(0) := '1'; +-- fract := (others => '0'); +-- else +-- fract := fract + 1; +-- end if; +-- elsif validfpx = pos_normal then +-- if or_reduce (fract) = '0' then -- fraction is all "0". +-- if or_reduce (expon (exponent_width-1 downto 1)) = '0' and +-- expon (0) = '1' then -- Smallest exponent +-- -- return the largest positive denormal number +-- expon := (others => '0'); +-- fract := (others => '1'); +-- else +-- expon := expon - 1; +-- fract := (others => '1'); +-- end if; +-- else +-- fract := fract - 1; +-- end if; +-- elsif validfpx = pos_denormal then +-- if or_reduce (fract(fract'high downto 1)) = '0' +-- and fract (0) = '1' then -- Smallest possible fraction +-- return zerofp (fraction_width => fraction_width, +-- exponent_width => exponent_width); +-- else +-- fract := fract - 1; +-- end if; +-- end if; +-- end if; +-- result (-1 downto -fraction_width) := UNRESOLVED_float(fract); +-- result (exponent_width -1 downto 0) := UNRESOLVED_float(expon); +-- result (exponent_width) := sign; +-- return result; +-- end if; +-- end function Nextafter; + + -- Returns True if X is unordered with Y. + function Unordered ( + x, y : UNRESOLVED_float) -- floating point input + return BOOLEAN is + variable lfptype, rfptype : valid_fpstate; + begin + lfptype := classfp (x); + rfptype := classfp (y); + if (lfptype = nan or lfptype = quiet_nan or + rfptype = nan or rfptype = quiet_nan or + lfptype = isx or rfptype = isx) then + return true; + else + return false; + end if; + end function Unordered; + + function Finite ( + x : UNRESOLVED_float) + return BOOLEAN is + variable fp_state : valid_fpstate; -- fp state + begin + fp_state := Classfp (x); + if (fp_state = pos_inf) or (fp_state = neg_inf) then + return true; + else + return false; + end if; + end function Finite; + + function Isnan ( + x : UNRESOLVED_float) + return BOOLEAN is + variable fp_state : valid_fpstate; -- fp state + begin + fp_state := Classfp (x); + if (fp_state = nan) or (fp_state = quiet_nan) then + return true; + else + return false; + end if; + end function Isnan; + + -- Function to return constants. + function zerofp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float is + constant result : UNRESOLVED_float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + return result; + end function zerofp; + + function nanfp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + result (exponent_width-1 downto 0) := (others => '1'); + -- Exponent all "1" + result (-1) := '1'; -- MSB of Fraction "1" + -- Note: From W. Khan "IEEE Standard 754 for Binary Floating Point" + -- The difference between a signaling NAN and a quiet NAN is that + -- the MSB of the Fraction is a "1" in a Signaling NAN, and is a + -- "0" in a quiet NAN. + return result; + end function nanfp; + + function qnanfp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + result (exponent_width-1 downto 0) := (others => '1'); + -- Exponent all "1" + result (-fraction_width) := '1'; -- LSB of Fraction "1" + -- (Could have been any bit) + return result; + end function qnanfp; + + function pos_inffp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + result (exponent_width-1 downto 0) := (others => '1'); -- Exponent all "1" + return result; + end function pos_inffp; + + function neg_inffp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + result (exponent_width downto 0) := (others => '1'); -- top bits all "1" + return result; + end function neg_inffp; + + function neg_zerofp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + result (exponent_width) := '1'; + return result; + end function neg_zerofp; + + -- size_res versions + function zerofp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float is + begin + return zerofp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function zerofp; + + function nanfp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float is + begin + return nanfp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function nanfp; + + function qnanfp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float is + begin + return qnanfp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function qnanfp; + + function pos_inffp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float is + begin + return pos_inffp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function pos_inffp; + + function neg_inffp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float is + begin + return neg_inffp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function neg_inffp; + + function neg_zerofp ( + size_res : UNRESOLVED_float) -- variable is only use for sizing + return UNRESOLVED_float is + begin + return neg_zerofp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function neg_zerofp; + +-- rtl_synthesis off +-- pragma synthesis_off + + --%%% these functions are copied from std_logic_1164 (VHDL-200X edition) + -- Textio functions + -- purpose: writes float into a line (NOTE changed basetype) + 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 NBSP : CHARACTER := CHARACTER'val(160); -- space character + 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 NUS : STRING(2 to 1) := (others => ' '); + + -- purpose: Skips white space + procedure skip_whitespace ( + L : inout LINE) is + variable readOk : BOOLEAN; + variable c : CHARACTER; + begin + while L /= null and L.all'length /= 0 loop + if (L.all(1) = ' ' or L.all(1) = NBSP or L.all(1) = HT) then + read (l, c, readOk); + else + exit; + end if; + end loop; + end procedure skip_whitespace; + +-- %%% Replicated textio functions + function to_ostring (value : STD_LOGIC_VECTOR) 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 result; + end if; + end function to_ostring; + ------------------------------------------------------------------- + function to_hstring (value : STD_LOGIC_VECTOR) 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 result; + end if; + end function to_hstring; + 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 "float_pkg:" + & "OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + result := "UUU"; + good := false; + end case; + end procedure Char2TriBits; + + procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : STD_LOGIC_VECTOR(0 to ne*3 - 1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, ok); + i := 0; + while i < ne loop + -- Bail out if there was a bad read + if not ok then + good := false; + return; + elsif c = '_' then + if i = 0 then + good := false; -- Begins with an "_" + return; + elsif lastu then + good := false; -- "__" detected + return; + else + lastu := true; + end if; + else + Char2TriBits(c, sv(3*i to 3*i+2), ok, false); + if not ok then + good := false; + return; + end if; + i := i + 1; + lastu := false; + end if; + if i < ne then + read(L, c, ok); + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + good := true; + VALUE := sv (pad to sv'high); + end if; + else + good := true; -- read into a null array + end if; + end procedure OREAD; + + -- 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 "float_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 STD_LOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : STD_LOGIC_VECTOR(0 to ne*4 - 1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, ok); + i := 0; + while i < ne loop + -- Bail out if there was a bad read + if not ok then + good := false; + return; + elsif c = '_' then + if i = 0 then + good := false; -- Begins with an "_" + return; + elsif lastu then + good := false; -- "__" detected + return; + else + lastu := true; + end if; + else + Char2QuadBits(c, sv(4*i to 4*i+3), ok, false); + if not ok then + good := false; + return; + end if; + i := i + 1; + lastu := false; + end if; + if i < ne then + read(L, c, ok); + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + good := true; + VALUE := sv (pad to sv'high); + end if; + else + good := true; -- Null input string, skips whitespace + end if; + end procedure HREAD; + +-- %%% END replicated textio functions + + -- purpose: Checks the punctuation in a line + procedure check_punctuation ( + arg : in STRING; + colon : out BOOLEAN; -- There was a colon in the line + dot : out BOOLEAN; -- There was a dot in the line + good : out BOOLEAN; -- True if enough characters found + chars : in INTEGER) is + -- Examples. Legal inputs are "0000000", "0000.000", "0:000:000" + alias xarg : STRING (1 to arg'length) is arg; -- make it downto range + variable icolon, idot : BOOLEAN; -- internal + variable j : INTEGER := 0; -- charters read + begin + good := false; + icolon := false; + idot := false; + for i in 1 to arg'length loop + if xarg(i) = ' ' or xarg(i) = NBSP or xarg(i) = HT or j = chars then + exit; + elsif xarg(i) = ':' then + icolon := true; + elsif xarg(i) = '.' then + idot := true; + elsif xarg (i) /= '_' then + j := j + 1; + end if; + end loop; + if j = chars then + good := true; -- There are enough charactes to read + end if; + colon := icolon; + if idot and icolon then + dot := false; + else + dot := idot; + end if; + end procedure check_punctuation; + + -- purpose: Searches a line for a ":" and replaces it with a ".". + procedure fix_colon ( + arg : inout STRING; + chars : in integer) is + alias xarg : STRING (1 to arg'length) is arg; -- make it downto range + variable j : INTEGER := 0; -- charters read + begin + for i in 1 to arg'length loop + if xarg(i) = ' ' or xarg(i) = NBSP or xarg(i) = HT or j > chars then + exit; + elsif xarg(i) = ':' then + xarg (i) := '.'; + elsif xarg (i) /= '_' then + j := j + 1; + end if; + end loop; + end procedure fix_colon; + + procedure WRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_float; -- floating point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + variable s : STRING(1 to value'high - value'low +3); + variable sindx : INTEGER; + begin -- function write + s(1) := MVL9_to_char(STD_ULOGIC(VALUE(VALUE'high))); + s(2) := ':'; + sindx := 3; + for i in VALUE'high-1 downto 0 loop + s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i))); + sindx := sindx + 1; + end loop; + s(sindx) := ':'; + sindx := sindx + 1; + for i in -1 downto VALUE'low loop + 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 UNRESOLVED_float) is + -- Possible data: 0:0000:0000000 + -- 000000000000 + variable c : CHARACTER; + variable mv : UNRESOLVED_float (VALUE'range); + variable readOk : BOOLEAN; + variable lastu : BOOLEAN := false; -- last character was an "_" + variable i : INTEGER; -- index variable + begin -- READ + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + READ (l, c, readOk); + if VALUE'length > 0 then + i := value'high; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + report "float_pkg:" + & "READ(float): " + & "Error end of file encountered." + severity error; + return; + elsif c = ' ' or c = CR or c = HT then -- reading done. + if (i /= value'low) then + report "float_pkg:" + & "READ(float): " + & "Warning: Value truncated." + severity warning; + return; + end if; + elsif c = '_' then + if i = value'high then -- Begins with an "_" + report "float_pkg:" + & "READ(float): " + & "String begins with an ""_""" severity error; + return; + elsif lastu then -- "__" detected + report "float_pkg:" + & "READ(float): " + & "Two underscores detected in input string ""__""" + severity error; + return; + else + lastu := true; + end if; + elsif c = ':' or c = '.' then -- separator, ignore + if not (i = -1 or i = value'high-1) then + report "float_pkg:" + & "READ(float): " + & "Warning: Separator point does not match number format: '" + & c & "' encountered at location " & INTEGER'image(i) & "." + severity warning; + end if; + lastu := false; + elsif (char_to_MVL9plus(c) = error) then + report "float_pkg:" + & "READ(float): " + & "Error: Character '" & c & "' read, expected STD_ULOGIC literal." + severity error; + return; + else + mv (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + VALUE := mv; + return; + end if; + lastu := false; + end if; + READ (l, c, readOk); + end loop readloop; + end if; + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is + -- Possible data: 0:0000:0000000 + -- 000000000000 + variable c : CHARACTER; + variable mv : UNRESOLVED_float (VALUE'range); + variable lastu : BOOLEAN := false; -- last character was an "_" + variable i : INTEGER; -- index variable + variable readOk : BOOLEAN; + begin -- READ + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + READ (l, c, readOk); + if VALUE'length > 0 then + i := value'high; + good := false; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + return; + elsif c = ' ' or c = CR or c = HT then -- reading done + return; + elsif c = '_' then + if i = 0 then -- Begins with an "_" + return; + elsif lastu then -- "__" detected + return; + else + lastu := true; + end if; + elsif c = ':' or c = '.' then -- separator, ignore + -- good := (i = -1 or i = value'high-1); + lastu := false; + elsif (char_to_MVL9plus(c) = error) then + return; + else + mv (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + good := true; + VALUE := mv; + return; + end if; + lastu := false; + end if; + READ (l, c, readOk); + end loop readloop; + else + good := true; -- read into a null array + end if; + end procedure READ; + + procedure OWRITE ( + L : inout LINE; -- access type (pointer) + VALUE : in UNRESOLVED_float; -- value to write + JUSTIFIED : in SIDE := right; -- which side to justify text + FIELD : in WIDTH := 0) is -- width of field + begin + WRITE (L => L, + VALUE => to_ostring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure OWRITE; + + procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float) is + constant ne : INTEGER := ((value'length+2)/3) * 3; -- pad + variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv + variable slvu : ufixed (VALUE'range); -- Unsigned fixed point + variable c : CHARACTER; + variable ok : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable colon, dot : BOOLEAN; + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + check_punctuation (arg => L.all, + colon => colon, + dot => dot, + good => ok, + chars => ne/3); + if not ok then + report "float_pkg:" & "OREAD: " + & "short string encounted: " & L.all + & " needs to have " & integer'image (ne/3) + & " valid octal characters." + severity error; + return; + elsif dot then + OREAD (L, slvu, ok); -- read it like a UFIXED number + if not ok then + report "float_pkg:" & "OREAD: " + & "error encounted reading STRING " & L.all + severity error; + return; + else + VALUE := UNRESOLVED_float (slvu); + end if; + elsif colon then + OREAD (L, nybble, ok); -- read the sign bit + if not ok then + report "float_pkg:" & "OREAD: " + & "End of string encountered" + severity error; + return; + elsif nybble (2 downto 1) /= "00" then + report "float_pkg:" & "OREAD: " + & "Illegal sign bit STRING encounted " + severity error; + return; + end if; + read (l, c, ok); -- read the colon + fix_colon (L.all, ne/3); -- replaces the colon with a ".". + OREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number + if not ok then + report "float_pkg:" & "OREAD: " + & "error encounted reading STRING " & L.all + severity error; + return; + else + slvu (slvu'high) := nybble (0); + VALUE := UNRESOLVED_float (slvu); + end if; + else + OREAD (L, slv, ok); + if not ok then + report "float_pkg:" & "OREAD: " + & "Error encounted during read" + severity error; + return; + end if; + if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then + report "float_pkg:" & "OREAD: " + & "Vector truncated." + severity error; + return; + end if; + VALUE := to_float (slv(VALUE'high-VALUE'low downto 0), + VALUE'high, -VALUE'low); + end if; + end if; + end procedure OREAD; + + procedure OREAD(L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is + constant ne : INTEGER := ((value'length+2)/3) * 3; -- pad + variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv + variable slvu : ufixed (VALUE'range); -- Unsigned fixed point + variable c : CHARACTER; + variable ok : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable colon, dot : BOOLEAN; + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + GOOD := false; + Skip_whitespace (L); + if VALUE'length > 0 then + check_punctuation (arg => L.all, + colon => colon, + dot => dot, + good => ok, + chars => ne/3); + if not ok then + return; + elsif dot then + OREAD (L, slvu, ok); -- read it like a UFIXED number + if not ok then + return; + else + VALUE := UNRESOLVED_float (slvu); + end if; + elsif colon then + OREAD (L, nybble, ok); -- read the sign bit + if not ok then + return; + elsif nybble (2 downto 1) /= "00" then + return; + end if; + read (l, c, ok); -- read the colon + fix_colon (L.all, ne/3); -- replaces the colon with a ".". + OREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number + if not ok then + return; + else + slvu (slvu'high) := nybble (0); + VALUE := UNRESOLVED_float (slvu); + end if; + else + OREAD (L, slv, ok); + if not ok then + return; + end if; + if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then + return; + end if; + VALUE := to_float (slv(VALUE'high-VALUE'low downto 0), + VALUE'high, -VALUE'low); + end if; + GOOD := true; + end if; + end procedure OREAD; + + procedure HWRITE ( + L : inout LINE; -- access type (pointer) + VALUE : in UNRESOLVED_float; -- value to write + JUSTIFIED : in SIDE := right; -- which side to justify text + FIELD : in WIDTH := 0) is -- width of field + begin + WRITE (L => L, + VALUE => to_hstring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure HWRITE; + + procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float) is + constant ne : INTEGER := ((value'length+3)/4) * 4; -- pad + variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv + variable slvu : ufixed (VALUE'range); -- Unsigned fixed point + variable c : CHARACTER; + variable ok : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable colon, dot : BOOLEAN; + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + check_punctuation (arg => L.all, + colon => colon, + dot => dot, + good => ok, + chars => ne/4); + if not ok then + report "float_pkg:" & "HREAD: " + & "short string encounted: " & L.all + & " needs to have " & integer'image (ne/4) + & " valid hex characters." + severity error; + return; + elsif dot then + HREAD (L, slvu, ok); -- read it like a UFIXED number + if not ok then + report "float_pkg:" & "HREAD: " + & "error encounted reading STRING " & L.all + severity error; + return; + else + VALUE := UNRESOLVED_float (slvu); + end if; + elsif colon then + HREAD (L, nybble, ok); -- read the sign bit + if not ok then + report "float_pkg:" & "HREAD: " + & "End of string encountered" + severity error; + return; + elsif nybble (3 downto 1) /= "000" then + report "float_pkg:" & "HREAD: " + & "Illegal sign bit STRING encounted " + severity error; + return; + end if; + read (l, c, ok); -- read the colon + fix_colon (L.all, ne/4); -- replaces the colon with a ".". + HREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number + if not ok then + report "float_pkg:" & "HREAD: " + & "error encounted reading STRING " & L.all + severity error; + return; + else + slvu (slvu'high) := nybble (0); + VALUE := UNRESOLVED_float (slvu); + end if; + else + HREAD (L, slv, ok); + if not ok then + report "float_pkg:" & "HREAD: " + & "Error encounted during read" + severity error; + return; + end if; + if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then + report "float_pkg:" & "HREAD: " + & "Vector truncated." + severity error; + return; + end if; + VALUE := to_float (slv(VALUE'high-VALUE'low downto 0), + VALUE'high, -VALUE'low); + end if; + end if; + end procedure HREAD; + + procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is + constant ne : INTEGER := ((value'length+3)/4) * 4; -- pad + variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv + variable slvu : ufixed (VALUE'range); -- Unsigned fixed point + variable c : CHARACTER; + variable ok : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable colon, dot : BOOLEAN; + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + GOOD := false; + Skip_whitespace (L); + if VALUE'length > 0 then + check_punctuation (arg => L.all, + colon => colon, + dot => dot, + good => ok, + chars => ne/4); + if not ok then + return; + elsif dot then + HREAD (L, slvu, ok); -- read it like a UFIXED number + if not ok then + return; + else + VALUE := UNRESOLVED_float (slvu); + end if; + elsif colon then + HREAD (L, nybble, ok); -- read the sign bit + if not ok then + return; + elsif nybble (3 downto 1) /= "000" then + return; + end if; + read (l, c, ok); -- read the colon + fix_colon (L.all, ne/4); -- replaces the colon with a ".". + HREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number + if not ok then + return; + else + slvu (slvu'high) := nybble (0); + VALUE := UNRESOLVED_float (slvu); + end if; + else + HREAD (L, slv, ok); + if not ok then + return; + end if; + if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then + return; + end if; + VALUE := to_float (slv(VALUE'high-VALUE'low downto 0), + VALUE'high, -VALUE'low); + end if; + GOOD := true; + end if; + end procedure HREAD; + + function to_string (value : UNRESOLVED_float) return STRING is + variable s : STRING(1 to value'high - value'low +3); + variable sindx : INTEGER; + begin -- function write + s(1) := MVL9_to_char(STD_ULOGIC(VALUE(VALUE'high))); + s(2) := ':'; + sindx := 3; + for i in VALUE'high-1 downto 0 loop + s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i))); + sindx := sindx + 1; + end loop; + s(sindx) := ':'; + sindx := sindx + 1; + for i in -1 downto VALUE'low loop + s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i))); + sindx := sindx + 1; + end loop; + return s; + end function to_string; + + function to_hstring (value : UNRESOLVED_float) return STRING is + variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); + begin + floop : for i in slv'range loop + slv(i) := to_X01Z (value(i + value'low)); + end loop floop; + return to_hstring (slv); + end function to_hstring; + + function to_ostring (value : UNRESOLVED_float) return STRING is + variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); + begin + floop : for i in slv'range loop + slv(i) := to_X01Z (value(i + value'low)); + end loop floop; + return to_ostring (slv); + end function to_ostring; + + function from_string ( + bstring : STRING; -- binary string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + READ (L, result, good); + deallocate (L); + assert (good) + report "float_pkg:" + & "from_string: Bad string " & bstring + severity error; + return result; + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + OREAD (L, result, good); + deallocate (L); + assert (good) + report "float_pkg:" + & "from_ostring: Bad string " & ostring + severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return UNRESOLVED_float is + variable result : UNRESOLVED_float (exponent_width downto -fraction_width); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + HREAD (L, result, good); + deallocate (L); + assert (good) + report "float_pkg:" + & "from_hstring: Bad string " & hstring + severity error; + return result; + end function from_hstring; + + function from_string ( + bstring : STRING; -- binary string + size_res : UNRESOLVED_float) -- used for sizing only + return UNRESOLVED_float is + begin + return from_string (bstring => bstring, + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : UNRESOLVED_float) -- used for sizing only + return UNRESOLVED_float is + begin + return from_ostring (ostring => ostring, + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : UNRESOLVED_float) -- used for sizing only + return UNRESOLVED_float is + begin + return from_hstring (hstring => hstring, + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function from_hstring; +-- rtl_synthesis on +-- pragma synthesis_on + function to_float ( + arg : STD_LOGIC_VECTOR; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction + return UNRESOLVED_float is + begin + return to_float ( + arg => std_ulogic_vector (arg), + exponent_width => exponent_width, + fraction_width => fraction_width); + end function to_float; + + function to_float ( + arg : STD_LOGIC_VECTOR; + size_res : UNRESOLVED_float) + return UNRESOLVED_float is + begin + return to_float ( + arg => std_ulogic_vector (arg), + size_res => size_res); + end function to_float; + + -- For Verilog compatability + function realtobits (arg : REAL) return STD_LOGIC_VECTOR is + variable result : float64; -- 64 bit floating point + begin + result := to_float (arg => arg, + exponent_width => float64'high, + fraction_width => -float64'low); + return to_slv (result); + end function realtobits; + + function bitstoreal (arg : STD_LOGIC_VECTOR) return REAL is + variable arg64 : float64; -- arg converted to float + begin + arg64 := to_float (arg => arg, + exponent_width => float64'high, + fraction_width => -float64'low); + return to_real (arg64); + end function bitstoreal; + +end package body float_pkg; diff --git a/ieee_proposed/rtl/numeric_std_additions.vhd b/ieee_proposed/rtl/numeric_std_additions.vhd new file mode 100644 index 0000000..4440d27 --- /dev/null +++ b/ieee_proposed/rtl/numeric_std_additions.vhd @@ -0,0 +1,2886 @@ +------------------------------------------------------------------------------ +-- "numeric_std_additions" package contains the additions to the standard +-- "numeric_std" package proposed by the VHDL-200X-ft working group. +-- 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.numeric_std_additions.all; +-- (this package is independant of "std_logic_1164_additions") +-- Last Modified: $Date: 2007/09/27 14:46:32 $ +-- RCS ID: $Id: numeric_std_additions.vhdl,v 1.9 2007/09/27 14:46:32 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; +use std.textio.all; + +package numeric_std_additions is + -- Make these a subtype of "signed" and "unsigned" for compatability +-- type UNRESOLVED_UNSIGNED is array (NATURAL range <>) of STD_ULOGIC; +-- type UNRESOLVED_SIGNED is array (NATURAL range <>) of STD_ULOGIC; + + subtype UNRESOLVED_UNSIGNED is UNSIGNED; + subtype UNRESOLVED_SIGNED is SIGNED; +-- alias U_UNSIGNED is UNRESOLVED_UNSIGNED; +-- alias U_SIGNED is UNRESOLVED_SIGNED; + subtype U_UNSIGNED is UNSIGNED; + subtype U_SIGNED is SIGNED; + + -- Id: A.3R + function "+"(L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + -- Result subtype: UNSIGNED(L'RANGE) + -- Result: Similar to A.3 where R is a one bit UNSIGNED + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'RANGE) + -- Result: Similar to A.3 where L is a one bit UNSIGNED + + -- Id: A.4R + function "+"(L : SIGNED; R : STD_ULOGIC) return SIGNED; + -- Result subtype: SIGNED(L'RANGE) + -- Result: Similar to A.4 where R is bit 0 of a non-negative + -- SIGNED + + -- Id: A.4L + function "+"(L : STD_ULOGIC; R : SIGNED) return SIGNED; + -- Result subtype: UNSIGNED(R'RANGE) + -- Result: Similar to A.4 where L is bit 0 of a non-negative + -- SIGNED + -- Id: A.9R + function "-"(L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + -- Result subtype: UNSIGNED(L'RANGE) + -- Result: Similar to A.9 where R is a one bit UNSIGNED + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'RANGE) + -- Result: Similar to A.9 where L is a one bit UNSIGNED + + -- Id: A.10R + function "-"(L : SIGNED; R : STD_ULOGIC) return SIGNED; + -- Result subtype: SIGNED(L'RANGE) + -- Result: Similar to A.10 where R is bit 0 of a non-negative + -- SIGNED + + -- Id: A.10L + function "-"(L : STD_ULOGIC; R : SIGNED) return SIGNED; + -- Result subtype: UNSIGNED(R'RANGE) + -- Result: Similar to A.10 where R is bit 0 of a non-negative + -- SIGNED + + -- Id: M.2B + -- %%% function "?=" (L, R : UNSIGNED) return std_ulogic; + -- %%% function "?/=" (L, R : UNSIGNED) return std_ulogic; + -- %%% function "?>" (L, R : UNSIGNED) return std_ulogic; + -- %%% function "?>=" (L, R : UNSIGNED) return std_ulogic; + -- %%% function "?<" (L, R : UNSIGNED) return std_ulogic; + -- %%% function "?<=" (L, R : UNSIGNED) return std_ulogic; +-- function \?=\ (L, R : UNSIGNED) return STD_ULOGIC; +-- function \?/=\ (L, R : UNSIGNED) return STD_ULOGIC; + function \?>\ (L, R : UNSIGNED) return STD_ULOGIC; + function \?>=\ (L, R : UNSIGNED) return STD_ULOGIC; + function \?<\ (L, R : UNSIGNED) return STD_ULOGIC; + function \?<=\ (L, R : UNSIGNED) return STD_ULOGIC; +-- function \?=\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC; +-- function \?/=\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC; + function \?>\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC; + function \?>=\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC; + function \?<\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC; + function \?<=\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC; +-- function \?=\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC; +-- function \?/=\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC; + function \?>\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC; + function \?>=\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC; + function \?<\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC; + function \?<=\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: terms compared per STD_LOGIC_1164 intent, + -- returns an 'X' if a metavalue is passed + + -- Id: M.3B + -- %%% function "?=" (L, R : SIGNED) return std_ulogic; + -- %%% function "?/=" (L, R : SIGNED) return std_ulogic; + -- %%% function "?>" (L, R : SIGNED) return std_ulogic; + -- %%% function "?>=" (L, R : SIGNED) return std_ulogic; + -- %%% function "?<" (L, R : SIGNED) return std_ulogic; + -- %%% function "?<=" (L, R : SIGNED) return std_ulogic; +-- function \?=\ (L, R : SIGNED) return STD_ULOGIC; +-- function \?/=\ (L, R : SIGNED) return STD_ULOGIC; + function \?>\ (L, R : SIGNED) return STD_ULOGIC; + function \?>=\ (L, R : SIGNED) return STD_ULOGIC; + function \?<\ (L, R : SIGNED) return STD_ULOGIC; + function \?<=\ (L, R : SIGNED) return STD_ULOGIC; +-- function \?=\ (L : SIGNED; R : INTEGER) return STD_ULOGIC; +-- function \?/=\ (L : SIGNED; R : INTEGER) return STD_ULOGIC; + function \?>\ (L : SIGNED; R : INTEGER) return STD_ULOGIC; + function \?>=\ (L : SIGNED; R : INTEGER) return STD_ULOGIC; + function \?<\ (L : SIGNED; R : INTEGER) return STD_ULOGIC; + function \?<=\ (L : SIGNED; R : INTEGER) return STD_ULOGIC; +-- function \?=\ (L : INTEGER; R : SIGNED) return STD_ULOGIC; +-- function \?/=\ (L : INTEGER; R : SIGNED) return STD_ULOGIC; + function \?>\ (L : INTEGER; R : SIGNED) return STD_ULOGIC; + function \?>=\ (L : INTEGER; R : SIGNED) return STD_ULOGIC; + function \?<\ (L : INTEGER; R : SIGNED) return STD_ULOGIC; + function \?<=\ (L : INTEGER; R : SIGNED) return STD_ULOGIC; + -- Result subtype: std_ulogic + -- Result: terms compared per STD_LOGIC_1164 intent, + -- returns an 'X' if a metavalue is passed + + -- size_res versions of these functions (Bugzilla 165) + function TO_UNSIGNED (ARG : NATURAL; SIZE_RES : UNSIGNED) return UNSIGNED; + -- Result subtype: UNRESOLVED_UNSIGNED(SIZE_RES'length-1 downto 0) + function TO_SIGNED (ARG : INTEGER; SIZE_RES : SIGNED) return SIGNED; + -- Result subtype: UNRESOLVED_SIGNED(SIZE_RES'length-1 downto 0) + function RESIZE (ARG, SIZE_RES : UNSIGNED) return UNSIGNED; + -- Result subtype: UNRESOLVED_UNSIGNED (SIZE_RES'length-1 downto 0) + function RESIZE (ARG, SIZE_RES : SIGNED) return SIGNED; + -- Result subtype: UNRESOLVED_SIGNED (SIZE_RES'length-1 downto 0) + ----------------------------------------------------------------------------- + -- New/updated funcitons for VHDL-200X fast track + ----------------------------------------------------------------------------- + + -- Overloaded functions from "std_logic_1164" + function To_X01 (s : UNSIGNED) return UNSIGNED; + function To_X01 (s : SIGNED) return SIGNED; + + function To_X01Z (s : UNSIGNED) return UNSIGNED; + function To_X01Z (s : SIGNED) return SIGNED; + + function To_UX01 (s : UNSIGNED) return UNSIGNED; + function To_UX01 (s : SIGNED) return SIGNED; + + function Is_X (s : UNSIGNED) return BOOLEAN; + function Is_X (s : SIGNED) return BOOLEAN; + + function "sla" (ARG : SIGNED; COUNT : INTEGER) return SIGNED; + function "sla" (ARG : UNSIGNED; COUNT : INTEGER) return UNSIGNED; + + function "sra" (ARG : SIGNED; COUNT : INTEGER) return SIGNED; + function "sra" (ARG : UNSIGNED; COUNT : INTEGER) return UNSIGNED; + + -- Returns the maximum (or minimum) of the two numbers provided. + -- All types (both inputs and the output) must be the same. + -- These override the implicit funcitons, using the local ">" operator + function maximum ( + l, r : UNSIGNED) -- inputs + return UNSIGNED; + + function maximum ( + l, r : SIGNED) -- inputs + return SIGNED; + + function minimum ( + l, r : UNSIGNED) -- inputs + return UNSIGNED; + + function minimum ( + l, r : SIGNED) -- inputs + return SIGNED; + + function maximum ( + l : UNSIGNED; r : NATURAL) -- inputs + return UNSIGNED; + + function maximum ( + l : SIGNED; r : INTEGER) -- inputs + return SIGNED; + + function minimum ( + l : UNSIGNED; r : NATURAL) -- inputs + return UNSIGNED; + + function minimum ( + l : SIGNED; r : INTEGER) -- inputs + return SIGNED; + + function maximum ( + l : NATURAL; r : UNSIGNED) -- inputs + return UNSIGNED; + + function maximum ( + l : INTEGER; r : SIGNED) -- inputs + return SIGNED; + + function minimum ( + l : NATURAL; r : UNSIGNED) -- inputs + return UNSIGNED; + + function minimum ( + l : INTEGER; r : SIGNED) -- inputs + return SIGNED; + -- Finds the first "Y" in the input string. Returns an integer index + -- into that string. If "Y" does not exist in the string, then the + -- "find_rightmost" returns arg'low -1, and "find_leftmost" returns -1 + function find_rightmost ( + arg : UNSIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; + + function find_rightmost ( + arg : SIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; + + function find_leftmost ( + arg : UNSIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; + + function find_leftmost ( + arg : SIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; + + function TO_UNRESOLVED_UNSIGNED (ARG, SIZE : NATURAL) return UNRESOLVED_UNSIGNED; + -- Result subtype: UNRESOLVED_UNSIGNED(SIZE-1 downto 0) + -- Result: Converts a nonnegative INTEGER to an UNRESOLVED_UNSIGNED vector with + -- the specified SIZE. + + alias TO_U_UNSIGNED is + TO_UNRESOLVED_UNSIGNED[NATURAL, NATURAL return UNRESOLVED_UNSIGNED]; + + function TO_UNRESOLVED_SIGNED (ARG : INTEGER; SIZE : NATURAL) return UNRESOLVED_SIGNED; + -- Result subtype: UNRESOLVED_SIGNED(SIZE-1 downto 0) + -- Result: Converts an INTEGER to an UNRESOLVED_SIGNED vector of the specified SIZE. + + alias TO_U_SIGNED is + TO_UNRESOLVED_SIGNED[NATURAL, NATURAL return UNRESOLVED_SIGNED]; + + -- L.15 + function "and" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.16 + function "and" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.17 + function "or" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.18 + function "or" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.19 + function "nand" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.20 + function "nand" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.21 + function "nor" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.22 + function "nor" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.23 + function "xor" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.24 + function "xor" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.25 + function "xnor" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.26 + function "xnor" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.27 + function "and" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.28 + function "and" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + +-- L.29 + function "or" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.30 + function "or" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + +-- L.31 + function "nand" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.32 + function "nand" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + +-- L.33 + function "nor" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.34 + function "nor" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + +-- L.35 + function "xor" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.36 + function "xor" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + +-- L.37 + function "xnor" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.38 + function "xnor" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + + -- %%% remove 12 functions (old syntax) + function and_reduce(l : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of and'ing all of the bits of the vector. + + function nand_reduce(l : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nand'ing all of the bits of the vector. + + function or_reduce(l : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of or'ing all of the bits of the vector. + + function nor_reduce(l : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nor'ing all of the bits of the vector. + + function xor_reduce(l : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xor'ing all of the bits of the vector. + + function xnor_reduce(l : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xnor'ing all of the bits of the vector. + + function and_reduce(l : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of and'ing all of the bits of the vector. + + function nand_reduce(l : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nand'ing all of the bits of the vector. + + function or_reduce(l : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of or'ing all of the bits of the vector. + + function nor_reduce(l : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nor'ing all of the bits of the vector. + + function xor_reduce(l : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xor'ing all of the bits of the vector. + + function xnor_reduce(l : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xnor'ing all of the bits of the vector. + + -- %%% Uncomment the following 12 functions (new syntax) + -- function "and" ( l : SIGNED ) RETURN std_ulogic; + -- function "nand" ( l : SIGNED ) RETURN std_ulogic; + -- function "or" ( l : SIGNED ) RETURN std_ulogic; + -- function "nor" ( l : SIGNED ) RETURN std_ulogic; + -- function "xor" ( l : SIGNED ) RETURN std_ulogic; + -- function "xnor" ( l : SIGNED ) RETURN std_ulogic; + -- function "and" ( l : UNSIGNED ) RETURN std_ulogic; + -- function "nand" ( l : UNSIGNED ) RETURN std_ulogic; + -- function "or" ( l : UNSIGNED ) RETURN std_ulogic; + -- function "nor" ( l : UNSIGNED ) RETURN std_ulogic; + -- function "xor" ( l : UNSIGNED ) RETURN std_ulogic; + -- function "xnor" ( l : UNSIGNED ) RETURN std_ulogic; + + -- rtl_synthesis off +-- pragma synthesis_off + ------------------------------------------------------------------- + -- string functions + ------------------------------------------------------------------- + function to_string (value : UNSIGNED) return STRING; + function to_string (value : SIGNED) return STRING; + + -- explicitly defined operations + + alias to_bstring is to_string [UNSIGNED return STRING]; + alias to_bstring is to_string [SIGNED return STRING]; + alias to_binary_string is to_string [UNSIGNED return STRING]; + alias to_binary_string is to_string [SIGNED return STRING]; + + function to_ostring (value : UNSIGNED) return STRING; + function to_ostring (value : SIGNED) return STRING; + alias to_octal_string is to_ostring [UNSIGNED return STRING]; + alias to_octal_string is to_ostring [SIGNED return STRING]; + + function to_hstring (value : UNSIGNED) return STRING; + function to_hstring (value : SIGNED) return STRING; + alias to_hex_string is to_hstring [UNSIGNED return STRING]; + alias to_hex_string is to_hstring [SIGNED return STRING]; + + procedure READ(L : inout LINE; VALUE : out UNSIGNED; GOOD : out BOOLEAN); + + procedure READ(L : inout LINE; VALUE : out UNSIGNED); + + procedure READ(L : inout LINE; VALUE : out SIGNED; GOOD : out BOOLEAN); + + procedure READ(L : inout LINE; VALUE : out SIGNED); + + procedure WRITE (L : inout LINE; VALUE : in UNSIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + procedure WRITE (L : inout LINE; VALUE : in SIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + alias BREAD is READ [LINE, UNSIGNED, BOOLEAN]; + alias BREAD is READ [LINE, SIGNED, BOOLEAN]; + + alias BREAD is READ [LINE, UNSIGNED]; + alias BREAD is READ [LINE, SIGNED]; + + alias BINARY_READ is READ [LINE, UNSIGNED, BOOLEAN]; + alias BINARY_READ is READ [LINE, SIGNED, BOOLEAN]; + + alias BINARY_READ is READ [LINE, UNSIGNED]; + alias BINARY_READ is READ [LINE, SIGNED]; + + procedure OREAD (L : inout LINE; VALUE : out UNSIGNED; GOOD : out BOOLEAN); + procedure OREAD (L : inout LINE; VALUE : out SIGNED; GOOD : out BOOLEAN); + + procedure OREAD (L : inout LINE; VALUE : out UNSIGNED); + procedure OREAD (L : inout LINE; VALUE : out SIGNED); + + alias OCTAL_READ is OREAD [LINE, UNSIGNED, BOOLEAN]; + alias OCTAL_READ is OREAD [LINE, SIGNED, BOOLEAN]; + + alias OCTAL_READ is OREAD [LINE, UNSIGNED]; + alias OCTAL_READ is OREAD [LINE, SIGNED]; + + procedure HREAD (L : inout LINE; VALUE : out UNSIGNED; GOOD : out BOOLEAN); + procedure HREAD (L : inout LINE; VALUE : out SIGNED; GOOD : out BOOLEAN); + + procedure HREAD (L : inout LINE; VALUE : out UNSIGNED); + procedure HREAD (L : inout LINE; VALUE : out SIGNED); + + alias HEX_READ is HREAD [LINE, UNSIGNED, BOOLEAN]; + alias HEX_READ is HREAD [LINE, SIGNED, BOOLEAN]; + + alias HEX_READ is HREAD [LINE, UNSIGNED]; + alias HEX_READ is HREAD [LINE, SIGNED]; + + alias BWRITE is WRITE [LINE, UNSIGNED, SIDE, WIDTH]; + alias BWRITE is WRITE [LINE, SIGNED, SIDE, WIDTH]; + + alias BINARY_WRITE is WRITE [LINE, UNSIGNED, SIDE, WIDTH]; + alias BINARY_WRITE is WRITE [LINE, SIGNED, SIDE, WIDTH]; + + procedure OWRITE (L : inout LINE; VALUE : in UNSIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + procedure OWRITE (L : inout LINE; VALUE : in SIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + alias OCTAL_WRITE is OWRITE [LINE, UNSIGNED, SIDE, WIDTH]; + alias OCTAL_WRITE is OWRITE [LINE, SIGNED, SIDE, WIDTH]; + + procedure HWRITE (L : inout LINE; VALUE : in UNSIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + procedure HWRITE (L : inout LINE; VALUE : in SIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + alias HEX_WRITE is HWRITE [LINE, UNSIGNED, SIDE, WIDTH]; + alias HEX_WRITE is HWRITE [LINE, SIGNED, SIDE, WIDTH]; + + -- rtl_synthesis on +-- pragma synthesis_on +end package numeric_std_additions; + +package body numeric_std_additions is + constant NAU : UNSIGNED(0 downto 1) := (others => '0'); + constant NAS : SIGNED(0 downto 1) := (others => '0'); + constant NO_WARNING : BOOLEAN := false; -- default to emit warnings + function MAX (left, right : INTEGER) return INTEGER is + begin + if left > right then return left; + else return right; + end if; + end function MAX; + + -- Id: A.3R + function "+"(L : UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + variable XR : UNSIGNED(L'length-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L + XR); + end function "+"; + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + variable XL : UNSIGNED(R'length-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL + R); + end function "+"; + + -- Id: A.4R + function "+"(L : SIGNED; R: STD_ULOGIC) return SIGNED is + variable XR : SIGNED(L'length-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L + XR); + end function "+"; + + -- Id: A.4L + function "+"(L : STD_ULOGIC; R: SIGNED) return SIGNED is + variable XL : SIGNED(R'length-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL + R); + end function "+"; + + -- Id: A.9R + function "-"(L : UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + variable XR : UNSIGNED(L'length-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L - XR); + end function "-"; + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + variable XL : UNSIGNED(R'length-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL - R); + end function "-"; + + -- Id: A.10R + function "-"(L : SIGNED; R: STD_ULOGIC) return SIGNED is + variable XR : SIGNED(L'length-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L - XR); + end function "-"; + + -- Id: A.10L + function "-"(L : STD_ULOGIC; R: SIGNED) return SIGNED is + variable XL : SIGNED(R'length-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL - R); + end function "-"; + +-- 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') -- | - | +-- ); + +-- %%% FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic IS +-- function \?=\ ( l, r : STD_ULOGIC ) return STD_ULOGIC is +-- variable value : STD_ULOGIC; +-- begin +-- return match_logic_table (l, r); +-- end function \?=\; +-- function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is +-- begin +-- return no_match_logic_table (l, r); +-- end function \?/=\; + + -- "?=" operator is similar to "std_match", but returns a std_ulogic.. + -- Id: M.2B +-- function \?=\ (L, R: UNSIGNED) return STD_ULOGIC is +-- constant L_LEFT : INTEGER := L'length-1; +-- constant R_LEFT : INTEGER := R'length-1; +-- alias XL : UNSIGNED(L_LEFT downto 0) is L; +-- alias XR : UNSIGNED(R_LEFT downto 0) is R; +-- constant SIZE : NATURAL := MAX(L'length, R'length); +-- variable LX : UNSIGNED(SIZE-1 downto 0); +-- variable RX : UNSIGNED(SIZE-1 downto 0); +-- variable result, result1 : STD_ULOGIC; -- result +-- begin +-- -- Logically identical to an "=" operator. +-- if ((L'length < 1) or (R'length < 1)) then +-- assert NO_WARNING +-- report "NUMERIC_STD.""?="": null detected, returning X" +-- severity warning; +-- return 'X'; +-- else +-- LX := RESIZE(XL, SIZE); +-- RX := RESIZE(XR, SIZE); +-- result := '1'; +-- for i in LX'low to LX'high loop +-- result1 := \?=\(LX(i), RX(i)); +-- if result1 = 'U' then +-- return 'U'; +-- elsif result1 = 'X' or result = 'X' then +-- result := 'X'; +-- else +-- result := result and result1; +-- end if; +-- end loop; +-- return result; +-- end if; +-- end function \?=\; + +-- -- %%% Replace with the following function +-- -- function "?=" (L, R: UNSIGNED) return std_ulogic is +-- -- end function "?="; + +-- -- Id: M.3B +-- function \?=\ (L, R: SIGNED) return STD_ULOGIC is +-- constant L_LEFT : INTEGER := L'length-1; +-- constant R_LEFT : INTEGER := R'length-1; +-- alias XL : SIGNED(L_LEFT downto 0) is L; +-- alias XR : SIGNED(R_LEFT downto 0) is R; +-- constant SIZE : NATURAL := MAX(L'length, R'length); +-- variable LX : SIGNED(SIZE-1 downto 0); +-- variable RX : SIGNED(SIZE-1 downto 0); +-- variable result, result1 : STD_ULOGIC; -- result +-- begin -- ?= +-- if ((L'length < 1) or (R'length < 1)) then +-- assert NO_WARNING +-- report "NUMERIC_STD.""?="": null detected, returning X" +-- severity warning; +-- return 'X'; +-- else +-- LX := RESIZE(XL, SIZE); +-- RX := RESIZE(XR, SIZE); +-- result := '1'; +-- for i in LX'low to LX'high loop +-- result1 := \?=\ (LX(i), RX(i)); +-- if result1 = 'U' then +-- return 'U'; +-- elsif result1 = 'X' or result = 'X' then +-- result := 'X'; +-- else +-- result := result and result1; +-- end if; +-- end loop; +-- return result; +-- end if; +-- end function \?=\; + -- %%% Replace with the following function +-- function "?=" (L, R: signed) return std_ulogic is +-- end function "?="; + + -- Id: C.75 +-- function \?=\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC is +-- begin +-- return \?=\ (TO_UNSIGNED(L, R'length), R); +-- end function \?=\; + +-- -- Id: C.76 +-- function \?=\ (L : INTEGER; R : SIGNED) return STD_ULOGIC is +-- begin +-- return \?=\ (TO_SIGNED(L, R'length), R); +-- end function \?=\; + +-- -- Id: C.77 +-- function \?=\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC is +-- begin +-- return \?=\ (L, TO_UNSIGNED(R, L'length)); +-- end function \?=\; + +-- -- Id: C.78 +-- function \?=\ (L : SIGNED; R : INTEGER) return STD_ULOGIC is +-- begin +-- return \?=\ (L, TO_SIGNED(R, L'length)); +-- end function \?=\; + +-- function \?/=\ (L, R : UNSIGNED) return STD_ULOGIC is +-- constant L_LEFT : INTEGER := L'length-1; +-- constant R_LEFT : INTEGER := R'length-1; +-- alias XL : UNSIGNED(L_LEFT downto 0) is L; +-- alias XR : UNSIGNED(R_LEFT downto 0) is R; +-- constant SIZE : NATURAL := MAX(L'length, R'length); +-- variable LX : UNSIGNED(SIZE-1 downto 0); +-- variable RX : UNSIGNED(SIZE-1 downto 0); +-- variable result, result1 : STD_ULOGIC; -- result +-- begin -- ?= +-- if ((L'length < 1) or (R'length < 1)) then +-- assert NO_WARNING +-- report "NUMERIC_STD.""?/="": null detected, returning X" +-- severity warning; +-- return 'X'; +-- else +-- LX := RESIZE(XL, SIZE); +-- RX := RESIZE(XR, SIZE); +-- result := '0'; +-- for i in LX'low to LX'high loop +-- result1 := \?/=\ (LX(i), RX(i)); +-- if result1 = 'U' then +-- return 'U'; +-- elsif result1 = 'X' or result = 'X' then +-- result := 'X'; +-- else +-- result := result or result1; +-- end if; +-- end loop; +-- return result; +-- end if; +-- end function \?/=\; +-- -- %%% function "?/=" (L, R : UNSIGNED) return std_ulogic is +-- -- %%% end function "?/="; +-- function \?/=\ (L, R : SIGNED) return STD_ULOGIC is +-- constant L_LEFT : INTEGER := L'length-1; +-- constant R_LEFT : INTEGER := R'length-1; +-- alias XL : SIGNED(L_LEFT downto 0) is L; +-- alias XR : SIGNED(R_LEFT downto 0) is R; +-- constant SIZE : NATURAL := MAX(L'length, R'length); +-- variable LX : SIGNED(SIZE-1 downto 0); +-- variable RX : SIGNED(SIZE-1 downto 0); +-- variable result, result1 : STD_ULOGIC; -- result +-- begin -- ?= +-- if ((L'length < 1) or (R'length < 1)) then +-- assert NO_WARNING +-- report "NUMERIC_STD.""?/="": null detected, returning X" +-- severity warning; +-- return 'X'; +-- else +-- LX := RESIZE(XL, SIZE); +-- RX := RESIZE(XR, SIZE); +-- result := '0'; +-- for i in LX'low to LX'high loop +-- result1 := \?/=\ (LX(i), RX(i)); +-- if result1 = 'U' then +-- return 'U'; +-- elsif result1 = 'X' or result = 'X' then +-- result := 'X'; +-- else +-- result := result or result1; +-- end if; +-- end loop; +-- return result; +-- end if; +-- end function \?/=\; +-- -- %%% function "?/=" (L, R : SIGNED) return std_ulogic is +-- -- %%% end function "?/="; + +-- -- Id: C.75 +-- function \?/=\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC is +-- begin +-- return \?/=\ (TO_UNSIGNED(L, R'length), R); +-- end function \?/=\; + +-- -- Id: C.76 +-- function \?/=\ (L : INTEGER; R : SIGNED) return STD_ULOGIC is +-- begin +-- return \?/=\ (TO_SIGNED(L, R'length), R); +-- end function \?/=\; + +-- -- Id: C.77 +-- function \?/=\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC is +-- begin +-- return \?/=\ (L, TO_UNSIGNED(R, L'length)); +-- end function \?/=\; + +-- -- Id: C.78 +-- function \?/=\ (L : SIGNED; R : INTEGER) return STD_ULOGIC is +-- begin +-- return \?/=\ (L, TO_SIGNED(R, L'length)); +-- end function \?/=\; + + function \?>\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + -- %%% function "?>" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?>"\; + function \?>\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + -- %%% function "?>" (L, R : SIGNED) return std_ulogic is + -- %%% end function "?>"; + -- Id: C.57 + function \?>\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC is + begin + return \?>\ (TO_UNSIGNED(L, R'length), R); + end function \?>\; + + -- Id: C.58 + function \?>\ (L : INTEGER; R : SIGNED) return STD_ULOGIC is + begin + return \?>\ (TO_SIGNED(L, R'length),R); + end function \?>\; + + -- Id: C.59 + function \?>\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC is + begin + return \?>\ (L, TO_UNSIGNED(R, L'length)); + end function \?>\; + + -- Id: C.60 + function \?>\ (L : SIGNED; R : INTEGER) return STD_ULOGIC is + begin + return \?>\ (L, TO_SIGNED(R, L'length)); + end function \?>\; + + function \?>=\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + -- %%% function "?>=" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?>="; + function \?>=\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + -- %%% function "?>=" (L, R : SIGNED) return std_ulogic is + -- %%% end function "?>="; + + function \?>=\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC is + begin + return \?>=\ (TO_UNSIGNED(L, R'length), R); + end function \?>=\; + + -- Id: C.64 + function \?>=\ (L : INTEGER; R : SIGNED) return STD_ULOGIC is + begin + return \?>=\ (TO_SIGNED(L, R'length),R); + end function \?>=\; + + -- Id: C.65 + function \?>=\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC is + begin + return \?>=\ (L, TO_UNSIGNED(R, L'length)); + end function \?>=\; + + -- Id: C.66 + function \?>=\ (L : SIGNED; R : INTEGER) return STD_ULOGIC is + begin + return \?>=\ (L, TO_SIGNED(R, L'length)); + end function \?>=\; + + function \?<\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + -- %%% function "?<" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?<"; + function \?<\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + -- %%% function "?<" (L, R : SIGNED) return std_ulogic is + -- %%% end function "?<"; + + -- Id: C.57 + function \?<\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC is + begin + return \?<\ (TO_UNSIGNED(L, R'length), R); + end function \?<\; + + -- Id: C.58 + function \?<\ (L : INTEGER; R : SIGNED) return STD_ULOGIC is + begin + return \?<\ (TO_SIGNED(L, R'length),R); + end function \?<\; + + -- Id: C.59 + function \?<\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC is + begin + return \?<\ (L, TO_UNSIGNED(R, L'length)); + end function \?<\; + + -- Id: C.60 + function \?<\ (L : SIGNED; R : INTEGER) return STD_ULOGIC is + begin + return \?<\ (L, TO_SIGNED(R, L'length)); + end function \?<\; + + function \?<=\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + -- %%% function "?<=" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?<="; + function \?<=\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + -- %%% function "?<=" (L, R : SIGNED) return std_ulogic is + -- %%% end function "?<="; + -- Id: C.63 + function \?<=\ (L : NATURAL; R : UNSIGNED) return STD_ULOGIC is + begin + return \?<=\ (TO_UNSIGNED(L, R'length), R); + end function \?<=\; + + -- Id: C.64 + function \?<=\ (L : INTEGER; R : SIGNED) return STD_ULOGIC is + begin + return \?<=\ (TO_SIGNED(L, R'length),R); + end function \?<=\; + + -- Id: C.65 + function \?<=\ (L : UNSIGNED; R : NATURAL) return STD_ULOGIC is + begin + return \?<=\ (L, TO_UNSIGNED(R, L'length)); + end function \?<=\; + + -- Id: C.66 + function \?<=\ (L : SIGNED; R : INTEGER) return STD_ULOGIC is + begin + return \?<=\ (L, TO_SIGNED(R, L'length)); + end function \?<=\; + + -- size_res versions of these functions (Bugzilla 165) + function TO_UNSIGNED (ARG : NATURAL; SIZE_RES : UNSIGNED) + return UNSIGNED is + begin + return TO_UNSIGNED (ARG => ARG, + SIZE => SIZE_RES'length); + end function TO_UNSIGNED; + + function TO_SIGNED (ARG : INTEGER; SIZE_RES : SIGNED) + return SIGNED is + begin + return TO_SIGNED (ARG => ARG, + SIZE => SIZE_RES'length); + end function TO_SIGNED; + + function RESIZE (ARG, SIZE_RES : SIGNED) + return SIGNED is + begin + return RESIZE (ARG => ARG, + NEW_SIZE => SIZE_RES'length); + end function RESIZE; + + function RESIZE (ARG, SIZE_RES : UNSIGNED) + return UNSIGNED is + begin + return RESIZE (ARG => ARG, + NEW_SIZE => SIZE_RES'length); + end function RESIZE; + + -- Id: S.9 + function "sll" (ARG : UNSIGNED; COUNT : INTEGER) + return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SHIFT_RIGHT(ARG, -COUNT); + end if; + end function "sll"; + + ------------------------------------------------------------------------------ + -- Note: Function S.10 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.10 + function "sll" (ARG : SIGNED; COUNT : INTEGER) + return SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), -COUNT)); + end if; + end function "sll"; + + ------------------------------------------------------------------------------ + -- Note: Function S.11 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.11 + function "srl" (ARG : UNSIGNED; COUNT : INTEGER) + return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(ARG, COUNT); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end function "srl"; + + ------------------------------------------------------------------------------ + -- Note: Function S.12 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.12 + function "srl" (ARG : SIGNED; COUNT : INTEGER) + return SIGNED is + begin + if (COUNT >= 0) then + return SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end function "srl"; + + ------------------------------------------------------------------------------ + -- Note: Function S.13 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.13 + function "rol" (ARG : UNSIGNED; COUNT : INTEGER) + return UNSIGNED is + begin + if (COUNT >= 0) then + return ROTATE_LEFT(ARG, COUNT); + else + return ROTATE_RIGHT(ARG, -COUNT); + end if; + end function "rol"; + + ------------------------------------------------------------------------------ + -- Note: Function S.14 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.14 + function "rol" (ARG : SIGNED; COUNT : INTEGER) + return SIGNED is + begin + if (COUNT >= 0) then + return ROTATE_LEFT(ARG, COUNT); + else + return ROTATE_RIGHT(ARG, -COUNT); + end if; + end function "rol"; + + ------------------------------------------------------------------------------ + -- Note: Function S.15 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.15 + function "ror" (ARG : UNSIGNED; COUNT : INTEGER) + return UNSIGNED is + begin + if (COUNT >= 0) then + return ROTATE_RIGHT(ARG, COUNT); + else + return ROTATE_LEFT(ARG, -COUNT); + end if; + end function "ror"; + + ------------------------------------------------------------------------------ + -- Note: Function S.16 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.16 + function "ror" (ARG : SIGNED; COUNT : INTEGER) + return SIGNED is + begin + if (COUNT >= 0) then + return ROTATE_RIGHT(ARG, COUNT); + else + return ROTATE_LEFT(ARG, -COUNT); + end if; + end function "ror"; + +-- begin LCS-2006-120 + + ------------------------------------------------------------------------------ + -- Note: Function S.17 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.17 + function "sla" (ARG : UNSIGNED; COUNT : INTEGER) + return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SHIFT_RIGHT(ARG, -COUNT); + end if; + end function "sla"; + + ------------------------------------------------------------------------------ + -- Note: Function S.18 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.18 + function "sla" (ARG : SIGNED; COUNT : INTEGER) + return SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SHIFT_RIGHT(ARG, -COUNT); + end if; + end function "sla"; + + ------------------------------------------------------------------------------ + -- Note: Function S.19 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.19 + function "sra" (ARG : UNSIGNED; COUNT : INTEGER) + return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(ARG, COUNT); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end function "sra"; + + ------------------------------------------------------------------------------ + -- Note: Function S.20 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.20 + 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"; + + -- These functions are in std_logic_1164 and are defined for + -- std_logic_vector. They are overloaded here. + function To_X01 ( s : UNSIGNED ) return UNSIGNED is + begin + return UNSIGNED (To_X01 (STD_LOGIC_VECTOR (s))); + end function To_X01; + + function To_X01 ( s : SIGNED ) return SIGNED is + begin + return SIGNED (To_X01 (STD_LOGIC_VECTOR (s))); + end function To_X01; + + function To_X01Z ( s : UNSIGNED ) return UNSIGNED is + begin + return UNSIGNED (To_X01Z (STD_LOGIC_VECTOR (s))); + end function To_X01Z; + + function To_X01Z ( s : SIGNED ) return SIGNED is + begin + return SIGNED (To_X01Z (STD_LOGIC_VECTOR (s))); + end function To_X01Z; + + function To_UX01 ( s : UNSIGNED ) return UNSIGNED is + begin + return UNSIGNED (To_UX01 (STD_LOGIC_VECTOR (s))); + end function To_UX01; + + function To_UX01 ( s : SIGNED ) return SIGNED is + begin + return SIGNED (To_UX01 (STD_LOGIC_VECTOR (s))); + end function To_UX01; + + function Is_X ( s : UNSIGNED ) return BOOLEAN is + begin + return Is_X (STD_LOGIC_VECTOR (s)); + end function Is_X; + + function Is_X ( s : SIGNED ) return BOOLEAN is + begin + return Is_X (STD_LOGIC_VECTOR (s)); + end function Is_X; + + ----------------------------------------------------------------------------- + -- New/updated functions for VHDL-200X fast track + ----------------------------------------------------------------------------- + + -- Returns the maximum (or minimum) of the two numbers provided. + -- All types (both inputs and the output) must be the same. + -- These override the implicit functions, using the local ">" operator + -- UNSIGNED output + function MAXIMUM (L, R : UNSIGNED) return UNSIGNED is + constant SIZE : NATURAL := MAX(L'length, R'length); + variable L01 : UNSIGNED(SIZE-1 downto 0); + variable R01 : UNSIGNED(SIZE-1 downto 0); + begin + if ((L'length < 1) or (R'length < 1)) then return NAU; + end if; + L01 := TO_01(RESIZE(L, SIZE), 'X'); + if (L01(L01'left) = 'X') then return L01; + end if; + R01 := TO_01(RESIZE(R, SIZE), 'X'); + if (R01(R01'left) = 'X') then return R01; + end if; + if L01 < R01 then + return R01; + else + return L01; + end if; + end function MAXIMUM; + + -- signed output + function MAXIMUM (L, R : SIGNED) return SIGNED is + constant SIZE : NATURAL := MAX(L'length, R'length); + variable L01 : SIGNED(SIZE-1 downto 0); + variable R01 : SIGNED(SIZE-1 downto 0); + begin + if ((L'length < 1) or (R'length < 1)) then return NAS; + end if; + L01 := TO_01(RESIZE(L, SIZE), 'X'); + if (L01(L01'left) = 'X') then return L01; + end if; + R01 := TO_01(RESIZE(R, SIZE), 'X'); + if (R01(R01'left) = 'X') then return R01; + end if; + if L01 < R01 then + return R01; + else + return L01; + end if; + end function MAXIMUM; + + -- UNSIGNED output + function MINIMUM (L, R : UNSIGNED) return UNSIGNED is + constant SIZE : NATURAL := MAX(L'length, R'length); + variable L01 : UNSIGNED(SIZE-1 downto 0); + variable R01 : UNSIGNED(SIZE-1 downto 0); + begin + if ((L'length < 1) or (R'length < 1)) then return NAU; + end if; + L01 := TO_01(RESIZE(L, SIZE), 'X'); + if (L01(L01'left) = 'X') then return L01; + end if; + R01 := TO_01(RESIZE(R, SIZE), 'X'); + if (R01(R01'left) = 'X') then return R01; + end if; + if L01 < R01 then + return L01; + else + return R01; + end if; + end function MINIMUM; + + + -- signed output + function MINIMUM (L, R : SIGNED) return SIGNED is + constant SIZE : NATURAL := MAX(L'length, R'length); + variable L01 : SIGNED(SIZE-1 downto 0); + variable R01 : SIGNED(SIZE-1 downto 0); + begin + if ((L'length < 1) or (R'length < 1)) then return NAS; + end if; + L01 := TO_01(RESIZE(L, SIZE), 'X'); + if (L01(L01'left) = 'X') then return L01; + end if; + R01 := TO_01(RESIZE(R, SIZE), 'X'); + if (R01(R01'left) = 'X') then return R01; + end if; + if L01 < R01 then + return L01; + else + return R01; + end if; + end function MINIMUM; + + -- Id: C.39 + function MINIMUM (L : NATURAL; R : UNSIGNED) + return UNSIGNED is + begin + return MINIMUM(TO_UNSIGNED(L, R'length), R); + end function MINIMUM; + + -- Id: C.40 + function MINIMUM (L : INTEGER; R : SIGNED) + return SIGNED is + begin + return MINIMUM(TO_SIGNED(L, R'length), R); + end function MINIMUM; + + -- Id: C.41 + function MINIMUM (L : UNSIGNED; R : NATURAL) + return UNSIGNED is + begin + return MINIMUM(L, TO_UNSIGNED(R, L'length)); + end function MINIMUM; + + -- Id: C.42 + function MINIMUM (L : SIGNED; R : INTEGER) + return SIGNED is + begin + return MINIMUM(L, TO_SIGNED(R, L'length)); + end function MINIMUM; + + -- Id: C.45 + function MAXIMUM (L : NATURAL; R : UNSIGNED) + return UNSIGNED is + begin + return MAXIMUM(TO_UNSIGNED(L, R'length), R); + end function MAXIMUM; + + -- Id: C.46 + function MAXIMUM (L : INTEGER; R : SIGNED) + return SIGNED is + begin + return MAXIMUM(TO_SIGNED(L, R'length), R); + end function MAXIMUM; + + -- Id: C.47 + function MAXIMUM (L : UNSIGNED; R : NATURAL) + return UNSIGNED is + begin + return MAXIMUM(L, TO_UNSIGNED(R, L'length)); + end function MAXIMUM; + + -- Id: C.48 + function MAXIMUM (L : SIGNED; R : INTEGER) + return SIGNED is + begin + return MAXIMUM(L, TO_SIGNED(R, L'length)); + end function MAXIMUM; + + function find_rightmost ( + arg : UNSIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER is + alias xarg : UNSIGNED(arg'length-1 downto 0) is arg; + begin + for_loop: for i in xarg'reverse_range loop + if xarg(i) = y then + return i; + end if; + end loop; + return -1; + end function find_rightmost; + + function find_rightmost ( + arg : SIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER is + alias xarg : SIGNED(arg'length-1 downto 0) is arg; + begin + for_loop: for i in xarg'reverse_range loop + if xarg(i) = y then + return i; + end if; + end loop; + return -1; + end function find_rightmost; + + function find_leftmost ( + arg : UNSIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER is + alias xarg : UNSIGNED(arg'length-1 downto 0) is arg; + begin + for_loop: for i in xarg'range loop + if xarg(i) = y then + return i; + end if; + end loop; + return -1; + end function find_leftmost; + + function find_leftmost ( + arg : SIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER is + alias xarg : SIGNED(arg'length-1 downto 0) is arg; + begin + for_loop: for i in xarg'range loop + if xarg(i) = y then + return i; + end if; + end loop; + return -1; + end function find_leftmost; + + function TO_UNRESOLVED_UNSIGNED (ARG, SIZE : NATURAL) + return UNRESOLVED_UNSIGNED is + begin + return UNRESOLVED_UNSIGNED(to_unsigned (arg, size)); + end function TO_UNRESOLVED_UNSIGNED; + -- Result subtype: UNRESOLVED_UNSIGNED(SIZE-1 downto 0) + -- Result: Converts a nonnegative INTEGER to an UNRESOLVED_UNSIGNED vector with + -- the specified SIZE. + + + function TO_UNRESOLVED_SIGNED (ARG : INTEGER; SIZE : NATURAL) + return UNRESOLVED_SIGNED is + begin + return UNRESOLVED_SIGNED(to_signed (arg, size)); + end function TO_UNRESOLVED_SIGNED; + -- Result subtype: UNRESOLVED_SIGNED(SIZE-1 downto 0) + -- Result: Converts an INTEGER to an UNRESOLVED_SIGNED vector of the specified SIZE. + + -- Performs the boolean operation on every bit in the vector +-- L.15 + function "and" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + alias rv : UNSIGNED ( 1 to r'length ) is r; + variable result : UNSIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "and" (l, rv(i)); + end loop; + return result; + end function "and"; + +-- L.16 + function "and" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + alias lv : UNSIGNED ( 1 to l'length ) is l; + variable result : UNSIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "and" (lv(i), r); + end loop; + return result; + end function "and"; + +-- L.17 + function "or" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + alias rv : UNSIGNED ( 1 to r'length ) is r; + variable result : UNSIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "or" (l, rv(i)); + end loop; + return result; + end function "or"; + +-- L.18 + function "or" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + alias lv : UNSIGNED ( 1 to l'length ) is l; + variable result : UNSIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "or" (lv(i), r); + end loop; + return result; + end function "or"; + +-- L.19 + function "nand" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + alias rv : UNSIGNED ( 1 to r'length ) is r; + variable result : UNSIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "not"("and" (l, rv(i))); + end loop; + return result; + end function "nand"; + +-- L.20 + function "nand" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + alias lv : UNSIGNED ( 1 to l'length ) is l; + variable result : UNSIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "not"("and" (lv(i), r)); + end loop; + return result; + end function "nand"; + +-- L.21 + function "nor" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + alias rv : UNSIGNED ( 1 to r'length ) is r; + variable result : UNSIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "not"("or" (l, rv(i))); + end loop; + return result; + end function "nor"; + +-- L.22 + function "nor" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + alias lv : UNSIGNED ( 1 to l'length ) is l; + variable result : UNSIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "not"("or" (lv(i), r)); + end loop; + return result; + end function "nor"; + +-- L.23 + function "xor" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + alias rv : UNSIGNED ( 1 to r'length ) is r; + variable result : UNSIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "xor" (l, rv(i)); + end loop; + return result; + end function "xor"; + +-- L.24 + function "xor" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + alias lv : UNSIGNED ( 1 to l'length ) is l; + variable result : UNSIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "xor" (lv(i), r); + end loop; + return result; + end function "xor"; + +-- L.25 + function "xnor" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + alias rv : UNSIGNED ( 1 to r'length ) is r; + variable result : UNSIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "not"("xor" (l, rv(i))); + end loop; + return result; + end function "xnor"; + +-- L.26 + function "xnor" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + alias lv : UNSIGNED ( 1 to l'length ) is l; + variable result : UNSIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "not"("xor" (lv(i), r)); + end loop; + return result; + end function "xnor"; + +-- L.27 + function "and" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + alias rv : SIGNED ( 1 to r'length ) is r; + variable result : SIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "and" (l, rv(i)); + end loop; + return result; + end function "and"; + +-- L.28 + function "and" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + alias lv : SIGNED ( 1 to l'length ) is l; + variable result : SIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "and" (lv(i), r); + end loop; + return result; + end function "and"; + +-- L.29 + function "or" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + alias rv : SIGNED ( 1 to r'length ) is r; + variable result : SIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "or" (l, rv(i)); + end loop; + return result; + end function "or"; + +-- L.30 + function "or" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + alias lv : SIGNED ( 1 to l'length ) is l; + variable result : SIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "or" (lv(i), r); + end loop; + return result; + end function "or"; + +-- L.31 + function "nand" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + alias rv : SIGNED ( 1 to r'length ) is r; + variable result : SIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "not"("and" (l, rv(i))); + end loop; + return result; + end function "nand"; + +-- L.32 + function "nand" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + alias lv : SIGNED ( 1 to l'length ) is l; + variable result : SIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "not"("and" (lv(i), r)); + end loop; + return result; + end function "nand"; + +-- L.33 + function "nor" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + alias rv : SIGNED ( 1 to r'length ) is r; + variable result : SIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "not"("or" (l, rv(i))); + end loop; + return result; + end function "nor"; + +-- L.34 + function "nor" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + alias lv : SIGNED ( 1 to l'length ) is l; + variable result : SIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "not"("or" (lv(i), r)); + end loop; + return result; + end function "nor"; + +-- L.35 + function "xor" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + alias rv : SIGNED ( 1 to r'length ) is r; + variable result : SIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "xor" (l, rv(i)); + end loop; + return result; + end function "xor"; + +-- L.36 + function "xor" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + alias lv : SIGNED ( 1 to l'length ) is l; + variable result : SIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "xor" (lv(i), r); + end loop; + return result; + end function "xor"; + +-- L.37 + function "xnor" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + alias rv : SIGNED ( 1 to r'length ) is r; + variable result : SIGNED ( 1 to r'length ); + begin + for i in result'range loop + result(i) := "not"("xor" (l, rv(i))); + end loop; + return result; + end function "xnor"; + +-- L.38 + function "xnor" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + alias lv : SIGNED ( 1 to l'length ) is l; + variable result : SIGNED ( 1 to l'length ); + begin + for i in result'range loop + result(i) := "not"("xor" (lv(i), r)); + end loop; + return result; + end function "xnor"; + + -------------------------------------------------------------------------- + -- Reduction operations + -------------------------------------------------------------------------- + -- %%% Remove the following 12 funcitons (old syntax) + function and_reduce (l : SIGNED ) return STD_ULOGIC is + begin + return and_reduce (UNSIGNED ( l )); + end function and_reduce; + + function and_reduce ( l : UNSIGNED ) return STD_ULOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : UNSIGNED ( l'length - 1 downto 0 ); + variable Result : STD_ULOGIC := '1'; -- In the case of a NULL range + begin + if (l'length >= 1) then + BUS_int := to_ux01 (l); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := "and" (BUS_int(BUS_int'right),BUS_int(BUS_int'left)); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := and_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := and_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := "and" (Upper, Lower); + end if; + end if; + return Result; + end function and_reduce; + + function nand_reduce (l : SIGNED ) return STD_ULOGIC is + begin + return "not" (and_reduce ( l )); + end function nand_reduce; + + function nand_reduce (l : UNSIGNED ) return STD_ULOGIC is + begin + return "not" (and_reduce (l )); + end function nand_reduce; + + function or_reduce (l : SIGNED ) return STD_ULOGIC is + begin + return or_reduce (UNSIGNED ( l )); + end function or_reduce; + + function or_reduce (l : UNSIGNED ) return STD_ULOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : UNSIGNED ( l'length - 1 downto 0 ); + variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range + begin + if (l'length >= 1) then + BUS_int := to_ux01 (l); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := "or" (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := or_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := or_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := "or" (Upper, Lower); + end if; + end if; + return Result; + end function or_reduce; + + function nor_reduce (l : SIGNED ) return STD_ULOGIC is + begin + return "not"(or_reduce(l)); + end function nor_reduce; + + function nor_reduce (l : UNSIGNED ) return STD_ULOGIC is + begin + return "not"(or_reduce(l)); + end function nor_reduce; + + function xor_reduce (l : SIGNED ) return STD_ULOGIC is + begin + return xor_reduce (UNSIGNED ( l )); + end function xor_reduce; + + function xor_reduce (l : UNSIGNED ) return STD_ULOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : UNSIGNED ( l'length - 1 downto 0 ); + variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range + begin + if (l'length >= 1) then + BUS_int := to_ux01 (l); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := "xor" (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := xor_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := xor_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := "xor" (Upper, Lower); + end if; + end if; + return Result; + end function xor_reduce; + + function xnor_reduce (l : SIGNED ) return STD_ULOGIC is + begin + return "not"(xor_reduce(l)); + end function xnor_reduce; + + function xnor_reduce (l : UNSIGNED ) return STD_ULOGIC is + begin + return "not"(xor_reduce(l)); + end function xnor_reduce; + + -- %%% Replace the above with the following 12 functions (New syntax) +-- function "and" ( l : SIGNED ) return std_ulogic is +-- begin +-- return and (std_logic_vector ( l )); +-- end function "and"; + +-- function "and" ( l : UNSIGNED ) return std_ulogic is +-- begin +-- return and (std_logic_vector ( l )); +-- end function "and"; + +-- function "nand" ( l : SIGNED ) return std_ulogic is +-- begin +-- return nand (std_logic_vector ( l )); +-- end function "nand"; + +-- function "nand" ( l : UNSIGNED ) return std_ulogic is +-- begin +-- return nand (std_logic_vector ( l )); +-- end function "nand"; + +-- function "or" ( l : SIGNED ) return std_ulogic is +-- begin +-- return or (std_logic_vector ( l )); +-- end function "or"; + +-- function "or" ( l : UNSIGNED ) return std_ulogic is +-- begin +-- return or (std_logic_vector ( l )); +-- end function "or"; + +-- function "nor" ( l : SIGNED ) return std_ulogic is +-- begin +-- return nor (std_logic_vector ( l )); +-- end function "nor"; + +-- function "nor" ( l : UNSIGNED ) return std_ulogic is +-- begin +-- return nor (std_logic_vector ( l )); +-- end function "nor"; + +-- function "xor" ( l : SIGNED ) return std_ulogic is +-- begin +-- return xor (std_logic_vector ( l )); +-- end function "xor"; + +-- function "xor" ( l : UNSIGNED ) return std_ulogic is +-- begin +-- return xor (std_logic_vector ( l )); +-- end function "xor"; + +-- function "xnor" ( l : SIGNED ) return std_ulogic is +-- begin +-- return xnor (std_logic_vector ( l )); +-- end function "xnor"; + +-- function "xnor" ( l : UNSIGNED ) return std_ulogic is +-- begin +-- return xnor (std_logic_vector ( l )); +-- end function "xnor"; + + -- rtl_synthesis off +-- pragma synthesis_off + ------------------------------------------------------------------- + -- TO_STRING + ------------------------------------------------------------------- + -- Type and constant definitions used to map STD_ULOGIC values + -- into/from character values. + 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 => ' '); -- NULL array + + function to_string (value : UNSIGNED) return STRING is + alias ivalue : UNSIGNED(1 to value'length) is value; + variable result : STRING(1 to value'length); + begin + if value'length < 1 then + return NUS; + else + for i in ivalue'range loop + result(i) := MVL9_to_char( iValue(i) ); + end loop; + return result; + end if; + end function to_string; + + function to_string (value : SIGNED) return STRING is + alias ivalue : SIGNED(1 to value'length) is value; + variable result : STRING(1 to value'length); + begin + if value'length < 1 then + return NUS; + else + for i in ivalue'range loop + result(i) := MVL9_to_char( iValue(i) ); + end loop; + return result; + end if; + end function to_string; + + function to_hstring (value : SIGNED) 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 => value(value'high)); -- Extend sign bit + end if; + ivalue := pad & STD_LOGIC_VECTOR (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 result; + end if; + end function to_hstring; + + function to_ostring (value : SIGNED) 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 => value (value'high)); -- Extend sign bit + end if; + ivalue := pad & STD_LOGIC_VECTOR (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 result; + end if; + end function to_ostring; + + function to_hstring (value : UNSIGNED) 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 & STD_LOGIC_VECTOR (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 result; + end if; + end function to_hstring; + + function to_ostring (value : UNSIGNED) 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 & STD_LOGIC_VECTOR (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 result; + end if; + end function to_ostring; + + ----------------------------------------------------------------------------- + -- Read and Write routines + ----------------------------------------------------------------------------- + + -- Routines copied from the "std_logic_1164_additions" package + -- purpose: Skips white space + procedure skip_whitespace ( + L : inout LINE) is + variable readOk : BOOLEAN; + variable c : CHARACTER; + begin + while L /= null and L.all'length /= 0 loop + if (L.all(1) = ' ' or L.all(1) = NBSP or L.all(1) = HT) then + read (l, c, readOk); + else + exit; + end if; + end loop; + end procedure skip_whitespace; + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable m : STD_ULOGIC; + variable c : CHARACTER; + variable mv : STD_ULOGIC_VECTOR(0 to VALUE'length-1); + variable readOk : BOOLEAN; + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, readOk); + i := 0; + good := true; + while i < VALUE'length loop + if not readOk then -- Bail out if there was a bad read + good := false; + return; + elsif c = '_' then + if i = 0 then + good := false; -- Begins with an "_" + return; + elsif lastu then + good := false; -- "__" detected + return; + else + lastu := true; + end if; + elsif (char_to_MVL9plus(c) = error) then + good := false; -- Illegal character + return; + else + mv(i) := char_to_MVL9(c); + i := i + 1; + if i > mv'high then -- reading done + VALUE := mv; + return; + end if; + lastu := false; + end if; + read(L, c, readOk); + end loop; + else + good := true; -- read into a null array + end if; + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is + variable m : STD_ULOGIC; + variable c : CHARACTER; + variable readOk : BOOLEAN; + variable mv : STD_ULOGIC_VECTOR(0 to VALUE'length-1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then -- non Null input string + read (l, c, readOk); + i := 0; + while i < VALUE'length loop + if readOk = false then -- Bail out if there was a bad read + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "End of string encountered" + severity error; + return; + elsif c = '_' then + if i = 0 then + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "String begins with an ""_""" severity error; + return; + elsif lastu then + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "Two underscores detected in input string ""__""" + severity error; + return; + else + lastu := true; + end if; + elsif char_to_MVL9plus(c) = error then + report + "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) Error: Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + return; + else + mv(i) := char_to_MVL9(c); + i := i + 1; + if i > mv'high then + VALUE := mv; + return; + end if; + lastu := false; + end if; + read(L, c, readOk); + end loop; + end if; + end procedure READ; + + -- purpose: or reduction + function or_reduce ( + arg : STD_ULOGIC_VECTOR) + return STD_ULOGIC is + variable uarg : UNSIGNED (arg'range); + begin + uarg := unsigned(arg); + return or_reduce (uarg); + end function or_reduce; + + procedure Char2QuadBits (C : CHARACTER; + RESULT : out STD_ULOGIC_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 + "STD_LOGIC_1164.HREAD Read a '" & c & + "', expected a Hex character (0-F)." + severity error; + good := false; + end case; + end procedure Char2QuadBits; + + procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : STD_ULOGIC_VECTOR(0 to ne*4 - 1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, ok); + i := 0; + while i < ne loop + -- Bail out if there was a bad read + if not ok then + good := false; + return; + elsif c = '_' then + if i = 0 then + good := false; -- Begins with an "_" + return; + elsif lastu then + good := false; -- "__" detected + return; + else + lastu := true; + end if; + else + Char2QuadBits(c, sv(4*i to 4*i+3), ok, false); + if not ok then + good := false; + return; + end if; + i := i + 1; + lastu := false; + end if; + if i < ne then + read(L, c, ok); + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + good := true; + VALUE := sv (pad to sv'high); + end if; + else + good := true; -- Null input string, skips whitespace + end if; + end procedure HREAD; + + procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : STD_ULOGIC_VECTOR(0 to ne*4 - 1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then -- non Null input string + read (l, c, ok); + i := 0; + while i < ne loop + -- Bail out if there was a bad read + if not ok then + report "STD_LOGIC_1164.HREAD " + & "End of string encountered" + severity error; + return; + end if; + if c = '_' then + if i = 0 then + report "STD_LOGIC_1164.HREAD " + & "String begins with an ""_""" severity error; + return; + elsif lastu then + report "STD_LOGIC_1164.HREAD " + & "Two underscores detected in input string ""__""" + severity error; + return; + else + lastu := true; + end if; + else + Char2QuadBits(c, sv(4*i to 4*i+3), ok, true); + if not ok then + return; + end if; + i := i + 1; + lastu := false; + end if; + if i < ne then + read(L, c, ok); + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + report "STD_LOGIC_1164.HREAD Vector truncated" + severity error; + else + VALUE := sv (pad to sv'high); + end if; + end if; + end procedure HREAD; + + -- Octal Read and Write procedures for STD_ULOGIC_VECTOR. + -- Modified from the original to be more forgiving. + + procedure Char2TriBits (C : CHARACTER; + RESULT : out STD_ULOGIC_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 + "STD_LOGIC_1164.OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + good := false; + end case; + end procedure Char2TriBits; + + procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : STD_ULOGIC_VECTOR(0 to ne*3 - 1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, ok); + i := 0; + while i < ne loop + -- Bail out if there was a bad read + if not ok then + good := false; + return; + elsif c = '_' then + if i = 0 then + good := false; -- Begins with an "_" + return; + elsif lastu then + good := false; -- "__" detected + return; + else + lastu := true; + end if; + else + Char2TriBits(c, sv(3*i to 3*i+2), ok, false); + if not ok then + good := false; + return; + end if; + i := i + 1; + lastu := false; + end if; + if i < ne then + read(L, c, ok); + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + good := true; + VALUE := sv (pad to sv'high); + end if; + else + good := true; -- read into a null array + end if; + end procedure OREAD; + + procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is + variable c : CHARACTER; + variable ok : BOOLEAN; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : STD_ULOGIC_VECTOR(0 to ne*3 - 1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, ok); + i := 0; + while i < ne loop + -- Bail out if there was a bad read + if not ok then + report "STD_LOGIC_1164.OREAD " + & "End of string encountered" + severity error; + return; + elsif c = '_' then + if i = 0 then + report "STD_LOGIC_1164.OREAD " + & "String begins with an ""_""" severity error; + return; + elsif lastu then + report "STD_LOGIC_1164.OREAD " + & "Two underscores detected in input string ""__""" + severity error; + return; + else + lastu := true; + end if; + else + Char2TriBits(c, sv(3*i to 3*i+2), ok, true); + if not ok then + return; + end if; + i := i + 1; + lastu := false; + end if; + if i < ne then + read(L, c, ok); + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + report "STD_LOGIC_1164.OREAD Vector truncated" + severity error; + else + VALUE := sv (pad to sv'high); + end if; + end if; + end procedure OREAD; + -- End copied code. + + procedure READ (L : inout LINE; VALUE : out UNSIGNED; + GOOD : out BOOLEAN) is + variable ivalue : STD_ULOGIC_VECTOR(value'range); + begin + READ (L => L, + VALUE => ivalue, + GOOD => GOOD); + VALUE := UNSIGNED(ivalue); + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out UNSIGNED) is + variable ivalue : STD_ULOGIC_VECTOR(value'range); + begin + READ (L => L, + VALUE => ivalue); + VALUE := UNSIGNED (ivalue); + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out SIGNED; + GOOD : out BOOLEAN) is + variable ivalue : STD_ULOGIC_VECTOR(value'range); + begin + READ (L => L, + VALUE => ivalue, + GOOD => GOOD); + VALUE := SIGNED(ivalue); + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out SIGNED) is + variable ivalue : STD_ULOGIC_VECTOR(value'range); + begin + READ (L => L, + VALUE => ivalue); + VALUE := SIGNED (ivalue); + end procedure READ; + + procedure WRITE (L : inout LINE; VALUE : in UNSIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + begin + write (L, to_string(VALUE), JUSTIFIED, FIELD); + end procedure WRITE; + + procedure WRITE (L : inout LINE; VALUE : in SIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + begin + write (L, to_string(VALUE), JUSTIFIED, FIELD); + end procedure WRITE; + + procedure OREAD (L : inout LINE; VALUE : out UNSIGNED; + GOOD : out BOOLEAN) is + variable ivalue : STD_ULOGIC_VECTOR(value'range); + begin + OREAD (L => L, + VALUE => ivalue, + GOOD => GOOD); + VALUE := UNSIGNED(ivalue); + end procedure OREAD; + + procedure OREAD (L : inout LINE; VALUE : out SIGNED; + GOOD : out BOOLEAN) is + constant ne : INTEGER := (value'length+2)/3; + constant pad : INTEGER := ne*3 - value'length; + variable ivalue : STD_ULOGIC_VECTOR(0 to ne*3-1); + variable ok : BOOLEAN; + variable expected_padding : STD_ULOGIC_VECTOR(0 to pad-1); + begin + OREAD (L => L, + VALUE => ivalue, -- Read padded STRING + GOOD => ok); + -- Bail out if there was a bad read + if not ok then + GOOD := false; + return; + end if; + expected_padding := (others => ivalue(pad)); + if ivalue(0 to pad-1) /= expected_padding then + GOOD := false; + else + GOOD := true; + VALUE := UNRESOLVED_SIGNED (ivalue (pad to ivalue'high)); + end if; + end procedure OREAD; + + procedure OREAD (L : inout LINE; VALUE : out UNSIGNED) is + variable ivalue : STD_ULOGIC_VECTOR(value'range); + begin + OREAD (L => L, + VALUE => ivalue); + VALUE := UNSIGNED (ivalue); + end procedure OREAD; + + procedure OREAD (L : inout LINE; VALUE : out SIGNED) is + constant ne : INTEGER := (value'length+2)/3; + constant pad : INTEGER := ne*3 - value'length; + variable ivalue : STD_ULOGIC_VECTOR(0 to ne*3-1); + variable expected_padding : STD_ULOGIC_VECTOR(0 to pad-1); + begin + OREAD (L => L, + VALUE => ivalue); -- Read padded string + expected_padding := (others => ivalue(pad)); + if ivalue(0 to pad-1) /= expected_padding then + assert false + report "NUMERIC_STD.OREAD Error: Signed vector truncated" + severity error; + else + VALUE := UNRESOLVED_SIGNED (ivalue (pad to ivalue'high)); + end if; + end procedure OREAD; + + procedure HREAD (L : inout LINE; VALUE : out UNSIGNED; + GOOD : out BOOLEAN) is + variable ivalue : STD_ULOGIC_VECTOR(value'range); + begin + HREAD (L => L, + VALUE => ivalue, + GOOD => GOOD); + VALUE := UNSIGNED(ivalue); + end procedure HREAD; + + procedure HREAD (L : inout LINE; VALUE : out SIGNED; + GOOD : out BOOLEAN) is + constant ne : INTEGER := (value'length+3)/4; + constant pad : INTEGER := ne*4 - value'length; + variable ivalue : STD_ULOGIC_VECTOR(0 to ne*4-1); + variable ok : BOOLEAN; + variable expected_padding : STD_ULOGIC_VECTOR(0 to pad-1); + begin + HREAD (L => L, + VALUE => ivalue, -- Read padded STRING + GOOD => ok); + if not ok then + GOOD := false; + return; + end if; + expected_padding := (others => ivalue(pad)); + if ivalue(0 to pad-1) /= expected_padding then + GOOD := false; + else + GOOD := true; + VALUE := UNRESOLVED_SIGNED (ivalue (pad to ivalue'high)); + end if; + end procedure HREAD; + + procedure HREAD (L : inout LINE; VALUE : out UNSIGNED) is + variable ivalue : STD_ULOGIC_VECTOR(value'range); + begin + HREAD (L => L, + VALUE => ivalue); + VALUE := UNSIGNED (ivalue); + end procedure HREAD; + + procedure HREAD (L : inout LINE; VALUE : out SIGNED) is + constant ne : INTEGER := (value'length+3)/4; + constant pad : INTEGER := ne*4 - value'length; + variable ivalue : STD_ULOGIC_VECTOR(0 to ne*4-1); + variable expected_padding : STD_ULOGIC_VECTOR(0 to pad-1); + begin + HREAD (L => L, + VALUE => ivalue); -- Read padded string + expected_padding := (others => ivalue(pad)); + if ivalue(0 to pad-1) /= expected_padding then + assert false + report "NUMERIC_STD.HREAD Error: Signed vector truncated" + severity error; + else + VALUE := UNRESOLVED_SIGNED (ivalue (pad to ivalue'high)); + end if; + end procedure HREAD; + + procedure OWRITE (L : inout LINE; VALUE : in UNSIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + begin + write (L, to_ostring(VALUE), JUSTIFIED, FIELD); + end procedure OWRITE; + + procedure OWRITE (L : inout LINE; VALUE : in SIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + begin + write (L, to_ostring(VALUE), JUSTIFIED, FIELD); + end procedure OWRITE; + + procedure HWRITE (L : inout LINE; VALUE : in UNSIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + begin + write (L, to_hstring (VALUE), JUSTIFIED, FIELD); + end procedure HWRITE; + + procedure HWRITE (L : inout LINE; VALUE : in SIGNED; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + begin + write (L, to_hstring (VALUE), JUSTIFIED, FIELD); + end procedure HWRITE; + + -- rtl_synthesis on +-- pragma synthesis_on +end package body numeric_std_additions; diff --git a/ieee_proposed/rtl/numeric_std_unsigned_c.vhd b/ieee_proposed/rtl/numeric_std_unsigned_c.vhd new file mode 100644 index 0000000..30e65ee --- /dev/null +++ b/ieee_proposed/rtl/numeric_std_unsigned_c.vhd @@ -0,0 +1,2207 @@ +-- -------------------------------------------------------------------- +-- Title : Standard VHDL Synthesis Packages (1076.3, NUMERIC_STD_UNSIGNED) +-- +-- This package overloaded the arithmetic operaters for +-- "STD_ULOGIC_VECTOR", and treats this vector like an +-- "UNSIGNED" from "numeric_std". +-- +-- This is the updated (proposed) new package to be +-- balloted in January. +-- +-- New subprograms are at the end of the package header +-- and the package body. These are to be revised, ID's +-- assigned, and voted into the ballot version. +-- +-- Other changes will be noted here. +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +package NUMERIC_STD_UNSIGNED is + +-- begin LCS-2006-141 + -- Replace all subsequent occurrences of STD_LOGIC_VECTOR + -- with STD_ULOGIC_ECTOR. +-- end LCS-2006-141 + -- Id: A.3 + function "+" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(MAXIMUM(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.3R + function "+"(L : STD_ULOGIC_VECTOR; R : STD_ULOGIC) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Similar to A.3 where R is a one bit STD_ULOGIC_VECTOR + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Similar to A.3 where L is a one bit UNSIGNED + + -- Id: A.5 + function "+" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + --============================================================================ + + -- Id: A.9 + function "-" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: UNSIGNED(MAXIMUM(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.9R + function "-"(L : STD_ULOGIC_VECTOR; R : STD_ULOGIC) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Similar to A.9 where R is a one bit UNSIGNED + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Similar to A.9 where L is a one bit UNSIGNED + + -- Id: A.11 + function "-" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + --============================================================================ + + -- Id: A.15 + function "*" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.17 + function "*" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- SIZE L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- SIZE R'LENGTH before multiplication. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.23 + function "/" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.29 + function "rem" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.35 + function "mod" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + +-- begin LCS-2006-129 + --============================================================================ + -- Id: A.39 + function find_leftmost (ARG : STD_ULOGIC_VECTOR; Y : STD_ULOGIC) return INTEGER; + -- Result subtype: INTEGER + -- Result: Finds the leftmost occurrence of the value of Y in ARG. + -- Returns the index of the occurrence if it exists, or -1 otherwise. + + -- Id: A.41 + function find_rightmost (ARG : STD_ULOGIC_VECTOR; Y : STD_ULOGIC) return INTEGER; + -- Result subtype: INTEGER + -- Result: Finds the leftmost occurrence of the value of Y in ARG. + -- Returns the index of the occurrence if it exists, or -1 otherwise. + +-- end LCS-2006-129 + --============================================================================ + -- Comparison Operators + --============================================================================ + + -- Id: C.1 + function ">" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.5 + function ">" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.7 + function "<" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.11 + function "<" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.17 + function "<=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.23 + function ">=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.25 + function "=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.29 + function "=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.35 + function "/=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.37 + function MINIMUM (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR + -- Result: Returns the lesser of two UNSIGNED vectors that may be + -- of different lengths. + + -- Id: C.39 + function MINIMUM (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR + -- Result: Returns the lesser of a nonnegative INTEGER, L, and + -- an UNSIGNED vector, R. + + -- Id: C.41 + function MINIMUM (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR + -- Result: Returns the lesser of an UNSIGNED vector, L, and + -- a nonnegative INTEGER, R. + + --============================================================================ + + -- Id: C.43 + function MAXIMUM (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR + -- Result: Returns the greater of two UNSIGNED vectors that may be + -- of different lengths. + + -- Id: C.45 + function MAXIMUM (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR + -- Result: Returns the greater of a nonnegative INTEGER, L, and + -- an UNSIGNED vector, R. + + -- Id: C.47 + function MAXIMUM (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR + -- Result: Returns the greater of an UNSIGNED vector, L, and + -- a nonnegative INTEGER, R. + + --============================================================================ + -- Id: C.49 + function \?>\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.51 + function \?>\ (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L > R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.53 + function \?>\ (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + + -- Id: C.55 + function \?<\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.57 + function \?<\ (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L < R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.59 + function \?<\ (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + + -- Id: C.61 + function \?<=\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.63 + function \?<=\ (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L <= R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.65 + function \?<=\ (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + + -- Id: C.67 + function \?>=\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.69 + function \?>=\ (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L >= R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.71 + function \?>=\ (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + + -- Id: C.73 +-- function \?=\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.75 +-- function \?=\ (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L = R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.77 +-- function \?=\ (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + + -- Id: C.79 +-- function \?/=\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.81 +-- function \?/=\ (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L /= R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.83 +-- function \?/=\ (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + -- Shift and Rotate Functions + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) + return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT leftmost elements are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) + return STD_ULOGIC_VECTOR; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT rightmost elements are lost. + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) + return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) + return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + ------------------------------------------------------------------------------ + -- Note: Function S.17 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.17 + function "sla" (ARG : STD_ULOGIC_VECTOR; COUNT : INTEGER) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note: Function S.19 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.19 + function "sra" (ARG : STD_ULOGIC_VECTOR; COUNT : INTEGER) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_RIGHT(ARG, COUNT) + + + --============================================================================ + -- RESIZE Functions + --============================================================================ + + -- Id: R.2 + function RESIZE (ARG : STD_ULOGIC_VECTOR; NEW_SIZE : NATURAL) + return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(NEW_SIZE-1 downto 0) + -- Result: Resizes the UNSIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + -- size_res versions of these functions (Bugzilla 165) + function RESIZE (ARG, SIZE_RES : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR (SIZE_RES'length-1 downto 0) + --============================================================================ + -- Conversion Functions + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG : STD_ULOGIC_VECTOR) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.3 + function To_StdLogicVector (ARG, SIZE : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified SIZE. + +-- begin LCS-2006-130 + alias To_Std_Logic_Vector is + To_StdLogicVector[NATURAL, NATURAL return STD_LOGIC_VECTOR]; + alias To_SLV is + To_StdLogicVector[NATURAL, NATURAL return STD_LOGIC_VECTOR]; + -- size_res versions of these functions (Bugzilla 165) + function To_StdLogicVector (ARG : NATURAL; SIZE_RES : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(SIZE_RES'length-1 downto 0) +-- end LCS-2006-130 + -- Id: D.5 + function To_StdULogicVector (ARG, SIZE : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified SIZE. + -- size_res versions of these functions (Bugzilla 165) + function To_StdULogicVector (ARG : NATURAL; SIZE_RES : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(SIZE_RES'length-1 downto 0) +-- begin LCS-2006-130 + alias To_Std_ULogic_Vector is + To_StdULogicVector[NATURAL, NATURAL return STD_ULOGIC_VECTOR]; + alias To_SULV is + To_StdULogicVector[NATURAL, NATURAL return STD_ULOGIC_VECTOR]; + alias To_Std_ULogic_Vector is + To_StdULogicVector[NATURAL, STD_ULOGIC_VECTOR return STD_ULOGIC_VECTOR]; + alias To_SULV is + To_StdULogicVector[NATURAL, STD_ULOGIC_VECTOR return STD_ULOGIC_VECTOR]; + +-- end LCS-2006-130 + --============================================================================ + -- Translation Functions + --============================================================================ + + -- Id: T.1 + function TO_01 (S : STD_ULOGIC_VECTOR; XMAP : STD_ULOGIC := '0') + return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(S'RANGE) + -- Result: Termwise, 'H' is translated to '1', and 'L' is translated + -- to '0'. If a value other than '0'|'1'|'H'|'L' is found, + -- the array is set to (others => XMAP), and a warning is + -- issued. +-- begin LCS-2006-141 + -- Replace all subsequent occurrences of STD_LOGIC_VECTOR + -- with STD_ULOGIC_ECTOR. +-- end LCS-2006-141 + -- Id: A.3 + function "+" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(MAXIMUM(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.3R + function "+"(L : STD_LOGIC_VECTOR; R : STD_ULOGIC) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Similar to A.3 where R is a one bit STD_LOGIC_VECTOR + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Similar to A.3 where L is a one bit UNSIGNED + + -- Id: A.5 + function "+" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + --============================================================================ + + -- Id: A.9 + function "-" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: UNSIGNED(MAXIMUM(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.9R + function "-"(L : STD_LOGIC_VECTOR; R : STD_ULOGIC) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Similar to A.9 where R is a one bit UNSIGNED + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Similar to A.9 where L is a one bit UNSIGNED + + -- Id: A.11 + function "-" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + --============================================================================ + + -- Id: A.15 + function "*" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.17 + function "*" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- SIZE L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- SIZE R'LENGTH before multiplication. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.23 + function "/" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.29 + function "rem" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.35 + function "mod" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + +-- begin LCS-2006-129 + --============================================================================ + -- Id: A.39 + function find_leftmost (ARG : STD_LOGIC_VECTOR; Y : STD_ULOGIC) return INTEGER; + -- Result subtype: INTEGER + -- Result: Finds the leftmost occurrence of the value of Y in ARG. + -- Returns the index of the occurrence if it exists, or -1 otherwise. + + -- Id: A.41 + function find_rightmost (ARG : STD_LOGIC_VECTOR; Y : STD_ULOGIC) return INTEGER; + -- Result subtype: INTEGER + -- Result: Finds the leftmost occurrence of the value of Y in ARG. + -- Returns the index of the occurrence if it exists, or -1 otherwise. + +-- end LCS-2006-129 + --============================================================================ + -- Comparison Operators + --============================================================================ + + -- Id: C.1 + function ">" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.5 + function ">" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.7 + function "<" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.11 + function "<" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.17 + function "<=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.23 + function ">=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.25 + function "=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.29 + function "=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.35 + function "/=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.37 + function MINIMUM (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR + -- Result: Returns the lesser of two UNSIGNED vectors that may be + -- of different lengths. + + -- Id: C.39 + function MINIMUM (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR + -- Result: Returns the lesser of a nonnegative INTEGER, L, and + -- an UNSIGNED vector, R. + + -- Id: C.41 + function MINIMUM (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR + -- Result: Returns the lesser of an UNSIGNED vector, L, and + -- a nonnegative INTEGER, R. + + --============================================================================ + + -- Id: C.43 + function MAXIMUM (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR + -- Result: Returns the greater of two UNSIGNED vectors that may be + -- of different lengths. + + -- Id: C.45 + function MAXIMUM (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR + -- Result: Returns the greater of a nonnegative INTEGER, L, and + -- an UNSIGNED vector, R. + + -- Id: C.47 + function MAXIMUM (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR + -- Result: Returns the greater of an UNSIGNED vector, L, and + -- a nonnegative INTEGER, R. + + --============================================================================ + -- Id: C.49 + function \?>\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.51 + function \?>\ (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L > R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.53 + function \?>\ (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + + -- Id: C.55 + function \?<\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.57 + function \?<\ (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L < R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.59 + function \?<\ (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + + -- Id: C.61 + function \?<=\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.63 + function \?<=\ (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L <= R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.65 + function \?<=\ (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + + -- Id: C.67 + function \?>=\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.69 + function \?>=\ (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L >= R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.71 + function \?>=\ (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + + -- Id: C.73 +-- function \?=\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.75 +-- function \?=\ (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L = R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.77 +-- function \?=\ (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + + -- Id: C.79 +-- function \?/=\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.81 +-- function \?/=\ (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L /= R" where L is a nonnegative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.83 +-- function \?/=\ (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_ULOGIC; + -- Result subtype: STD_ULOGIC + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a nonnegative INTEGER. + + --============================================================================ + -- Shift and Rotate Functions + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) + return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT leftmost elements are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) + return STD_LOGIC_VECTOR; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT rightmost elements are lost. + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) + return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) + return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + ------------------------------------------------------------------------------ + -- Note: Function S.17 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.17 + function "sla" (ARG : STD_LOGIC_VECTOR; COUNT : INTEGER) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note: Function S.19 is not compatible with IEEE Std 1076-1987. Comment + -- out the function (declaration and body) for IEEE Std 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.19 + function "sra" (ARG : STD_LOGIC_VECTOR; COUNT : INTEGER) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_RIGHT(ARG, COUNT) + + + --============================================================================ + -- RESIZE Functions + --============================================================================ + + -- Id: R.2 + function RESIZE (ARG : STD_LOGIC_VECTOR; NEW_SIZE : NATURAL) + return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(NEW_SIZE-1 downto 0) + -- Result: Resizes the UNSIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + -- size_res versions of these functions (Bugzilla 165) + function RESIZE (ARG, SIZE_RES : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR (SIZE_RES'length-1 downto 0) + --============================================================================ + -- Conversion Functions + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG : STD_LOGIC_VECTOR) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + +-- end LCS-2006-130 + + --============================================================================ + -- Translation Functions + --============================================================================ + + -- Id: T.1 + function TO_01 (S : STD_LOGIC_VECTOR; XMAP : STD_ULOGIC := '0') + return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR(S'RANGE) + -- Result: Termwise, 'H' is translated to '1', and 'L' is translated + -- to '0'. If a value other than '0'|'1'|'H'|'L' is found, + -- the array is set to (others => XMAP), and a warning is + -- issued. +end package NUMERIC_STD_UNSIGNED; +------------------------------------------------------------------------------- +-- Proposed package body for the VHDL-200x-FT NUMERIC_STD_UNSIGNED package +-- This package body supplies a recommended implementation of these functions +-- Version: $Revision: 1.4 $ +-- Date: $Date: 2009/08/26 19:56:30 $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------- +library ieee; +use ieee.numeric_std.all; +use work.numeric_std_additions.all; + +package body NUMERIC_STD_UNSIGNED is + + -- Id: A.3 + function "+" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) + UNSIGNED(R)); + end function "+"; + + -- Id: A.3R + function "+"(L : STD_ULOGIC_VECTOR; R : STD_ULOGIC) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) + R); + end function "+"; + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (L + UNSIGNED(R)); + end function "+"; + + -- Id: A.5 + function "+" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) + R); + end function "+"; + + -- Id: A.6 + function "+" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (L + UNSIGNED(R)); + end function "+"; + + --============================================================================ + + -- Id: A.9 + function "-" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) - UNSIGNED(R)); + end function "-"; + + -- Id: A.9R + function "-"(L : STD_ULOGIC_VECTOR; R : STD_ULOGIC) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) - R); + end function "-"; + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (L - UNSIGNED(R)); + end function "-"; + + -- Id: A.11 + function "-" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) - R); + end function "-"; + + -- Id: A.12 + function "-" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (L - UNSIGNED(R)); + end function "-"; + + --============================================================================ + + -- Id: A.15 + function "*" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) * UNSIGNED(R)); + end function "*"; + + -- Id: A.17 + function "*" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) * R); + end function "*"; + + -- Id: A.18 + function "*" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (L * UNSIGNED(R)); + end function "*"; + + --============================================================================ + + -- Id: A.21 + function "/" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) / UNSIGNED(R)); + end function "/"; + + -- Id: A.23 + function "/" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) / R); + end function "/"; + + -- Id: A.24 + function "/" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (L / UNSIGNED(R)); + end function "/"; + + --============================================================================ + + -- Id: A.27 + function "rem" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) rem UNSIGNED(R)); + end function "rem"; + + -- Id: A.29 + function "rem" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) rem R); + end function "rem"; + + -- Id: A.30 + function "rem" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (L rem UNSIGNED(R)); + end function "rem"; + + --============================================================================ + + -- Id: A.33 + function "mod" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) mod UNSIGNED(R)); + end function "mod"; + + -- Id: A.35 + function "mod" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(L) mod R); + end function "mod"; + + -- Id: A.36 + function "mod" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (L mod UNSIGNED(R)); + end function "mod"; + +-- begin LCS-2006-129 + --============================================================================ + -- Id: A.39 + function find_leftmost (ARG: STD_ULOGIC_VECTOR; Y: STD_ULOGIC) return INTEGER is + begin + return find_leftmost(UNSIGNED(ARG), Y); + end function find_leftmost; + + -- Id: A.41 + function find_rightmost (ARG: STD_ULOGIC_VECTOR; Y: STD_ULOGIC) return INTEGER is + begin + return find_rightmost(UNSIGNED(ARG), Y); + end function find_rightmost; + +-- end LCS-2006-129 + --============================================================================ + + -- Id: C.1 + function ">" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) > UNSIGNED(R); + end function ">"; + + -- Id: C.3 + function ">" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L > UNSIGNED(R); + end function ">"; + + -- Id: C.5 + function ">" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) > R; + end function ">"; + + --============================================================================ + + -- Id: C.7 + function "<" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) < UNSIGNED(R); + end function "<"; + + -- Id: C.9 + function "<" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L < UNSIGNED(R); + end function "<"; + + -- Id: C.11 + function "<" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) < R; + end function "<"; + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) <= UNSIGNED(R); + end function "<="; + + -- Id: C.15 + function "<=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L <= UNSIGNED(R); + end function "<="; + + -- Id: C.17 + function "<=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) <= R; + end function "<="; + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) >= UNSIGNED(R); + end function ">="; + + -- Id: C.21 + function ">=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L >= UNSIGNED(R); + end function ">="; + + -- Id: C.23 + function ">=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) >= R; + end function ">="; + + --============================================================================ + + -- Id: C.25 + function "=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) = UNSIGNED(R); + end function "="; + + -- Id: C.27 + function "=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L = UNSIGNED(R); + end function "="; + + -- Id: C.29 + function "=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) = R; + end function "="; + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) /= UNSIGNED(R); + end function "/="; + + -- Id: C.33 + function "/=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L /= UNSIGNED(R); + end function "/="; + + -- Id: C.35 + function "/=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) /= R; + end function "/="; + + --============================================================================ + + -- Id: C.37 + function MINIMUM (L, R: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (MINIMUM(UNSIGNED(L), UNSIGNED(R))); + end function MINIMUM; + + -- Id: C.39 + function MINIMUM (L: NATURAL; R: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (MINIMUM(L, UNSIGNED(R))); + end function MINIMUM; + + -- Id: C.41 + function MINIMUM (L: STD_ULOGIC_VECTOR; R: NATURAL) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (MINIMUM(UNSIGNED(L), R)); + end function MINIMUM; + + --============================================================================ + -- Id: C.43 + function MAXIMUM (L, R: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (MAXIMUM(UNSIGNED(L), UNSIGNED(R))); + end function MAXIMUM; + + -- Id: C.45 + function MAXIMUM (L: NATURAL; R: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (MAXIMUM(L, UNSIGNED(R))); + end function MAXIMUM; + + -- Id: C.47 + function MAXIMUM (L: STD_ULOGIC_VECTOR; R: NATURAL) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (MAXIMUM(UNSIGNED(L), R)); + end function MAXIMUM; + + --============================================================================ + + -- Id: C.49 + function \?>\ (L, R: STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>\ (UNSIGNED(L), UNSIGNED(R)); + end function \?>\; + + -- Id: C.51 + function \?>\ (L: NATURAL; R: STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>\ (L, UNSIGNED(R)); + end function \?>\; + + -- Id: C.53 + function \?>\ (L: STD_ULOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is + begin + return \?>\ (UNSIGNED(L), R); + end function \?>\; + + --============================================================================ + + -- Id: C.55 + function \?<\ (L, R: STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<\ (UNSIGNED(L), UNSIGNED(R)); + end function \?<\; + + -- Id: C.57 + function \?<\ (L: NATURAL; R: STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<\ (L, UNSIGNED(R)); + end function \?<\; + + -- Id: C.59 + function \?<\ (L: STD_ULOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is + begin + return \?<\ (UNSIGNED(L), R); + end function \?<\; + + --============================================================================ + + -- Id: C.61 + function \?<=\ (L, R: STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<=\ (UNSIGNED(L), UNSIGNED(R)); + end function \?<=\; + + -- Id: C.63 + function \?<=\ (L: NATURAL; R: STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<=\ (L, UNSIGNED(R)); + end function \?<=\; + + -- Id: C.65 + function \?<=\ (L: STD_ULOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is + begin + return \?<=\ (UNSIGNED(L), R); + end function \?<=\; + + --============================================================================ + + -- Id: C.67 + function \?>=\ (L, R: STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>=\ (UNSIGNED(L), UNSIGNED(R)); + end function \?>=\; + + -- Id: C.69 + function \?>=\ (L: NATURAL; R: STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>=\ (L, UNSIGNED(R)); + end function \?>=\; + + -- Id: C.71 + function \?>=\ (L: STD_ULOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is + begin + return \?>=\ (UNSIGNED(L), R); + end function \?>=\; + + --============================================================================ + + -- Id: C.73 +-- function \?=\ (L, R: STD_ULOGIC_VECTOR) return STD_ULOGIC is +-- begin +-- return \?=\ (UNSIGNED(L), UNSIGNED(R)); +-- end function \?=\; + +-- -- Id: C.75 +-- function \?=\ (L: NATURAL; R: STD_ULOGIC_VECTOR) return STD_ULOGIC is +-- begin +-- return \?=\ (L, UNSIGNED(R)); +-- end function \?=\; + +-- -- Id: C.77 +-- function \?=\ (L: STD_ULOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is +-- begin +-- return \?=\ (UNSIGNED(L), R); +-- end function \?=\; + +-- --============================================================================ + +-- -- Id: C.79 +-- function \?/=\ (L, R: STD_ULOGIC_VECTOR) return STD_ULOGIC is +-- begin +-- return \?/=\ (UNSIGNED(L), UNSIGNED(R)); +-- end function \?/=\; + +-- -- Id: C.81 +-- function \?/=\ (L: NATURAL; R: STD_ULOGIC_VECTOR) return STD_ULOGIC is +-- begin +-- return \?/=\ (L, UNSIGNED(R)); +-- end function \?/=\; + +-- -- Id: C.83 +-- function \?/=\ (L: STD_ULOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is +-- begin +-- return \?/=\ (UNSIGNED(L), R); +-- end function \?/=\; + + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) return STD_ULOGIC_VECTOR is + begin + return std_ulogic_vector (SHIFT_LEFT(unsigned(ARG), COUNT)); + end function SHIFT_LEFT; + + -- Id: S.2 + function SHIFT_RIGHT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) return STD_ULOGIC_VECTOR is + begin + return std_ulogic_vector (SHIFT_RIGHT(unsigned(ARG), COUNT)); + end function SHIFT_RIGHT; + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) return STD_ULOGIC_VECTOR is + begin + return std_ulogic_vector (ROTATE_LEFT(unsigned(ARG), COUNT)); + end function ROTATE_LEFT; + + -- Id: S.6 + function ROTATE_RIGHT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) return STD_ULOGIC_VECTOR is + begin + return std_ulogic_vector (ROTATE_RIGHT(unsigned(ARG), COUNT)); + end function ROTATE_RIGHT; + + --============================================================================ + + -- Id: S.17 + function "sla" (ARG: STD_ULOGIC_VECTOR; COUNT: INTEGER) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(ARG) sla COUNT); + end function "sla"; + + -- Id: S.19 + function "sra" (ARG: STD_ULOGIC_VECTOR; COUNT: INTEGER) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (UNSIGNED(ARG) sra COUNT); + end function "sra"; + + --============================================================================ + + -- Id: R.2 + function RESIZE (ARG : STD_ULOGIC_VECTOR; NEW_SIZE : NATURAL) + return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR ( + RESIZE (ARG => UNSIGNED(ARG), + NEW_SIZE => NEW_SIZE)); + end function RESIZE; + + function RESIZE (ARG, SIZE_RES : STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR ( + RESIZE (ARG => UNSIGNED(ARG), + NEW_SIZE => SIZE_RES'length)); + end function RESIZE; + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG : STD_ULOGIC_VECTOR) return NATURAL is + begin + return TO_INTEGER(UNSIGNED(ARG)); + end function TO_INTEGER; + + -- Id: D.3 + function To_StdLogicVector (ARG, SIZE : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (TO_UNSIGNED(ARG => ARG, + SIZE => SIZE)); + end function To_StdLogicVector; + + function To_StdLogicVector (ARG : NATURAL; SIZE_RES : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (TO_UNSIGNED(ARG => ARG, + SIZE => SIZE_RES'length)); + end function To_StdLogicVector; + -- Id: D.5 + function To_StdULogicVector (ARG, SIZE : NATURAL) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (TO_UNSIGNED(ARG => ARG, + SIZE => SIZE)); + end function To_StdULogicVector; + + function To_StdULogicVector (ARG : NATURAL; SIZE_RES : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR (TO_UNSIGNED(ARG => ARG, + SIZE => SIZE_RES'length)); + end function To_StdULogicVector; + --============================================================================ + + -- function TO_01 is used to convert vectors to the + -- correct form for exported functions, + -- and to report if there is an element which + -- is not in (0, 1, H, L). + + -- Id: T.1 + function TO_01 (S : STD_ULOGIC_VECTOR; XMAP : STD_ULOGIC := '0') + return STD_ULOGIC_VECTOR is + begin + return STD_ULOGIC_VECTOR ( + TO_01 (S => UNSIGNED(S), + XMAP => XMAP)); + end function TO_01; + + -- Id: A.3 + function "+" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) + UNSIGNED(R)); + end function "+"; + + -- Id: A.3R + function "+"(L : STD_LOGIC_VECTOR; R : STD_ULOGIC) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) + R); + end function "+"; + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L + UNSIGNED(R)); + end function "+"; + + -- Id: A.5 + function "+" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) + R); + end function "+"; + + -- Id: A.6 + function "+" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L + UNSIGNED(R)); + end function "+"; + + --============================================================================ + + -- Id: A.9 + function "-" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) - UNSIGNED(R)); + end function "-"; + + -- Id: A.9R + function "-"(L : STD_LOGIC_VECTOR; R : STD_ULOGIC) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) - R); + end function "-"; + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L - UNSIGNED(R)); + end function "-"; + + -- Id: A.11 + function "-" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) - R); + end function "-"; + + -- Id: A.12 + function "-" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L - UNSIGNED(R)); + end function "-"; + + --============================================================================ + + -- Id: A.15 + function "*" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) * UNSIGNED(R)); + end function "*"; + + -- Id: A.17 + function "*" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) * R); + end function "*"; + + -- Id: A.18 + function "*" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L * UNSIGNED(R)); + end function "*"; + + --============================================================================ + + -- Id: A.21 + function "/" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) / UNSIGNED(R)); + end function "/"; + + -- Id: A.23 + function "/" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) / R); + end function "/"; + + -- Id: A.24 + function "/" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L / UNSIGNED(R)); + end function "/"; + + --============================================================================ + + -- Id: A.27 + function "rem" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) rem UNSIGNED(R)); + end function "rem"; + + -- Id: A.29 + function "rem" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) rem R); + end function "rem"; + + -- Id: A.30 + function "rem" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L rem UNSIGNED(R)); + end function "rem"; + + --============================================================================ + + -- Id: A.33 + function "mod" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) mod UNSIGNED(R)); + end function "mod"; + + -- Id: A.35 + function "mod" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) mod R); + end function "mod"; + + -- Id: A.36 + function "mod" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L mod UNSIGNED(R)); + end function "mod"; + +-- begin LCS-2006-129 + --============================================================================ + -- Id: A.39 + function find_leftmost (ARG: STD_LOGIC_VECTOR; Y: STD_ULOGIC) return INTEGER is + begin + return find_leftmost(UNSIGNED(ARG), Y); + end function find_leftmost; + + -- Id: A.41 + function find_rightmost (ARG: STD_LOGIC_VECTOR; Y: STD_ULOGIC) return INTEGER is + begin + return find_rightmost(UNSIGNED(ARG), Y); + end function find_rightmost; + +-- end LCS-2006-129 + --============================================================================ + + -- Id: C.1 + function ">" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) > UNSIGNED(R); + end function ">"; + + -- Id: C.3 + function ">" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L > UNSIGNED(R); + end function ">"; + + -- Id: C.5 + function ">" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) > R; + end function ">"; + + --============================================================================ + + -- Id: C.7 + function "<" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) < UNSIGNED(R); + end function "<"; + + -- Id: C.9 + function "<" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L < UNSIGNED(R); + end function "<"; + + -- Id: C.11 + function "<" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) < R; + end function "<"; + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) <= UNSIGNED(R); + end function "<="; + + -- Id: C.15 + function "<=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L <= UNSIGNED(R); + end function "<="; + + -- Id: C.17 + function "<=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) <= R; + end function "<="; + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) >= UNSIGNED(R); + end function ">="; + + -- Id: C.21 + function ">=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L >= UNSIGNED(R); + end function ">="; + + -- Id: C.23 + function ">=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) >= R; + end function ">="; + + --============================================================================ + + -- Id: C.25 + function "=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) = UNSIGNED(R); + end function "="; + + -- Id: C.27 + function "=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L = UNSIGNED(R); + end function "="; + + -- Id: C.29 + function "=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) = R; + end function "="; + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) /= UNSIGNED(R); + end function "/="; + + -- Id: C.33 + function "/=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L /= UNSIGNED(R); + end function "/="; + + -- Id: C.35 + function "/=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) /= R; + end function "/="; + + --============================================================================ + + -- Id: C.37 + function MINIMUM (L, R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (MINIMUM(UNSIGNED(L), UNSIGNED(R))); + end function MINIMUM; + + -- Id: C.39 + function MINIMUM (L: NATURAL; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (MINIMUM(L, UNSIGNED(R))); + end function MINIMUM; + + -- Id: C.41 + function MINIMUM (L: STD_LOGIC_VECTOR; R: NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (MINIMUM(UNSIGNED(L), R)); + end function MINIMUM; + + --============================================================================ + -- Id: C.43 + function MAXIMUM (L, R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (MAXIMUM(UNSIGNED(L), UNSIGNED(R))); + end function MAXIMUM; + + -- Id: C.45 + function MAXIMUM (L: NATURAL; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (MAXIMUM(L, UNSIGNED(R))); + end function MAXIMUM; + + -- Id: C.47 + function MAXIMUM (L: STD_LOGIC_VECTOR; R: NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (MAXIMUM(UNSIGNED(L), R)); + end function MAXIMUM; + + --============================================================================ + + -- Id: C.49 + function \?>\ (L, R: STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>\ (UNSIGNED(L), UNSIGNED(R)); + end function \?>\; + + -- Id: C.51 + function \?>\ (L: NATURAL; R: STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>\ (L, UNSIGNED(R)); + end function \?>\; + + -- Id: C.53 + function \?>\ (L: STD_LOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is + begin + return \?>\ (UNSIGNED(L), R); + end function \?>\; + + --============================================================================ + + -- Id: C.55 + function \?<\ (L, R: STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<\ (UNSIGNED(L), UNSIGNED(R)); + end function \?<\; + + -- Id: C.57 + function \?<\ (L: NATURAL; R: STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<\ (L, UNSIGNED(R)); + end function \?<\; + + -- Id: C.59 + function \?<\ (L: STD_LOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is + begin + return \?<\ (UNSIGNED(L), R); + end function \?<\; + + --============================================================================ + + -- Id: C.61 + function \?<=\ (L, R: STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<=\ (UNSIGNED(L), UNSIGNED(R)); + end function \?<=\; + + -- Id: C.63 + function \?<=\ (L: NATURAL; R: STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<=\ (L, UNSIGNED(R)); + end function \?<=\; + + -- Id: C.65 + function \?<=\ (L: STD_LOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is + begin + return \?<=\ (UNSIGNED(L), R); + end function \?<=\; + + --============================================================================ + + -- Id: C.67 + function \?>=\ (L, R: STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>=\ (UNSIGNED(L), UNSIGNED(R)); + end function \?>=\; + + -- Id: C.69 + function \?>=\ (L: NATURAL; R: STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>=\ (L, UNSIGNED(R)); + end function \?>=\; + + -- Id: C.71 + function \?>=\ (L: STD_LOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is + begin + return \?>=\ (UNSIGNED(L), R); + end function \?>=\; + + --============================================================================ + + -- Id: C.73 +-- function \?=\ (L, R: STD_LOGIC_VECTOR) return STD_ULOGIC is +-- begin +-- return \?=\ (UNSIGNED(L), UNSIGNED(R)); +-- end function \?=\; + +-- -- Id: C.75 +-- function \?=\ (L: NATURAL; R: STD_LOGIC_VECTOR) return STD_ULOGIC is +-- begin +-- return \?=\ (L, UNSIGNED(R)); +-- end function \?=\; + +-- -- Id: C.77 +-- function \?=\ (L: STD_LOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is +-- begin +-- return \?=\ (UNSIGNED(L), R); +-- end function \?=\; + +-- --============================================================================ + +-- -- Id: C.79 +-- function \?/=\ (L, R: STD_LOGIC_VECTOR) return STD_ULOGIC is +-- begin +-- return \?/=\ (UNSIGNED(L), UNSIGNED(R)); +-- end function \?/=\; + +-- -- Id: C.81 +-- function \?/=\ (L: NATURAL; R: STD_LOGIC_VECTOR) return STD_ULOGIC is +-- begin +-- return \?/=\ (L, UNSIGNED(R)); +-- end function \?/=\; + +-- -- Id: C.83 +-- function \?/=\ (L: STD_LOGIC_VECTOR; R: NATURAL) return STD_ULOGIC is +-- begin +-- return \?/=\ (UNSIGNED(L), R); +-- end function \?/=\; + + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (SHIFT_LEFT(unsigned(ARG), COUNT)); + end function SHIFT_LEFT; + + -- Id: S.2 + function SHIFT_RIGHT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (SHIFT_RIGHT(unsigned(ARG), COUNT)); + end function SHIFT_RIGHT; + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (ROTATE_LEFT(unsigned(ARG), COUNT)); + end function ROTATE_LEFT; + + -- Id: S.6 + function ROTATE_RIGHT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (ROTATE_RIGHT(unsigned(ARG), COUNT)); + end function ROTATE_RIGHT; + + --============================================================================ + + -- Id: S.17 + function "sla" (ARG: STD_LOGIC_VECTOR; COUNT: INTEGER) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(ARG) sla COUNT); + end function "sla"; + + -- Id: S.19 + function "sra" (ARG: STD_LOGIC_VECTOR; COUNT: INTEGER) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(ARG) sra COUNT); + end function "sra"; + + --============================================================================ + + -- Id: R.2 + function RESIZE (ARG : STD_LOGIC_VECTOR; NEW_SIZE : NATURAL) + return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR ( + RESIZE (ARG => UNSIGNED(ARG), + NEW_SIZE => NEW_SIZE)); + end function RESIZE; + + function RESIZE (ARG, SIZE_RES : STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR ( + RESIZE (ARG => UNSIGNED(ARG), + NEW_SIZE => SIZE_RES'length)); + end function RESIZE; + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG : STD_LOGIC_VECTOR) return NATURAL is + begin + return TO_INTEGER(UNSIGNED(ARG)); + end function TO_INTEGER; + + --============================================================================ + + -- function TO_01 is used to convert vectors to the + -- correct form for exported functions, + -- and to report if there is an element which + -- is not in (0, 1, H, L). + + -- Id: T.1 + function TO_01 (S : STD_LOGIC_VECTOR; XMAP : STD_ULOGIC := '0') + return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR ( + TO_01 (S => UNSIGNED(S), + XMAP => XMAP)); + end function TO_01; + +end package body NUMERIC_STD_UNSIGNED; diff --git a/ieee_proposed/rtl/standard_additions_c.vhd b/ieee_proposed/rtl/standard_additions_c.vhd new file mode 100644 index 0000000..97016af --- /dev/null +++ b/ieee_proposed/rtl/standard_additions_c.vhd @@ -0,0 +1,2073 @@ +------------------------------------------------------------------------------ +-- "standard_additions" package contains the additions to the built in +-- "standard.std" package. In the final version this package will be implicit. +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ +package standard_additions is + + function \?=\ (L, R : BOOLEAN) return BOOLEAN; + function \?/=\ (L, R : BOOLEAN) return BOOLEAN; + function \?<\ (L, R : BOOLEAN) return BOOLEAN; + function \?<=\ (L, R : BOOLEAN) return BOOLEAN; + function \?>\ (L, R : BOOLEAN) return BOOLEAN; + function \?>=\ (L, R : BOOLEAN) return BOOLEAN; + + function MINIMUM (L, R : BOOLEAN) return BOOLEAN; + function MAXIMUM (L, R : BOOLEAN) return BOOLEAN; + + function RISING_EDGE (signal S : BOOLEAN) return BOOLEAN; + function FALLING_EDGE (signal S : BOOLEAN) return BOOLEAN; + + function \?=\ (L, R : BIT) return BIT; + function \?/=\ (L, R : BIT) return BIT; + function \?<\ (L, R : BIT) return BIT; + function \?<=\ (L, R : BIT) return BIT; + function \?>\ (L, R : BIT) return BIT; + function \?>=\ (L, R : BIT) return BIT; + + function MINIMUM (L, R : BIT) return BIT; + function MAXIMUM (L, R : BIT) return BIT; + + function \??\ (L : BIT) return BOOLEAN; + + function RISING_EDGE (signal S : BIT) return BOOLEAN; + function FALLING_EDGE (signal S : BIT) return BOOLEAN; + + function MINIMUM (L, R : CHARACTER) return CHARACTER; + function MAXIMUM (L, R : CHARACTER) return CHARACTER; + + function MINIMUM (L, R : SEVERITY_LEVEL) return SEVERITY_LEVEL; + function MAXIMUM (L, R : SEVERITY_LEVEL) return SEVERITY_LEVEL; + + function MINIMUM (L, R : INTEGER) return INTEGER; + function MAXIMUM (L, R : INTEGER) return INTEGER; + + function MINIMUM (L, R : REAL) return REAL; + function MAXIMUM (L, R : REAL) return REAL; + + function "mod" (L, R : TIME) return TIME; + function "rem" (L, R : TIME) return TIME; + + function MINIMUM (L, R : TIME) return TIME; + function MAXIMUM (L, R : TIME) return TIME; + + function MINIMUM (L, R : STRING) return STRING; + function MAXIMUM (L, R : STRING) return STRING; + + function MINIMUM (L : STRING) return CHARACTER; + function MAXIMUM (L : STRING) return CHARACTER; + + type BOOLEAN_VECTOR is array (NATURAL range <>) of BOOLEAN; + + -- The predefined operations for this type are as follows: + + function "and" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "or" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "nand" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "nor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "xor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "xnor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + + function "not" (L : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + + function "and" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR; + function "and" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR; + function "or" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR; + function "or" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR; + function "nand" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR; + function "nand" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR; + function "nor" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR; + function "nor" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR; + function "xor" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR; + function "xor" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR; + function "xnor" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR; + function "xnor" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR; + + function and_reduce (L : BOOLEAN_VECTOR) return BOOLEAN; + function or_reduce (L : BOOLEAN_VECTOR) return BOOLEAN; + function nand_reduce (L : BOOLEAN_VECTOR) return BOOLEAN; + function nor_reduce (L : BOOLEAN_VECTOR) return BOOLEAN; + function xor_reduce (L : BOOLEAN_VECTOR) return BOOLEAN; + function xnor_reduce (L : BOOLEAN_VECTOR) return BOOLEAN; + + function "sll" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR; + function "srl" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR; + function "sla" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR; + function "sra" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR; + function "rol" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR; + function "ror" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR; + +-- function "=" (L, R : BOOLEAN_VECTOR) return BOOLEAN; +-- function "/=" (L, R : BOOLEAN_VECTOR) return BOOLEAN; +-- function "<" (L, R : BOOLEAN_VECTOR) return BOOLEAN; +-- function "<=" (L, R : BOOLEAN_VECTOR) return BOOLEAN; +-- function ">" (L, R : BOOLEAN_VECTOR) return BOOLEAN; +-- function ">=" (L, R : BOOLEAN_VECTOR) return BOOLEAN; + + function \?=\ (L, R : BOOLEAN_VECTOR) return BOOLEAN; + function \?/=\ (L, R : BOOLEAN_VECTOR) return BOOLEAN; + +-- function "&" (L : BOOLEAN_VECTOR; R : BOOLEAN_VECTOR) + -- return BOOLEAN_VECTOR; +-- function "&" (L : BOOLEAN_VECTOR; R : BOOLEAN) -- return BOOLEAN_VECTOR; +-- function "&" (L : BOOLEAN; R : BOOLEAN_VECTOR) -- return BOOLEAN_VECTOR; +-- function "&" (L : BOOLEAN; R : BOOLEAN) -- return BOOLEAN_VECTOR; + + function MINIMUM (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function MAXIMUM (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + + function MINIMUM (L : BOOLEAN_VECTOR) return BOOLEAN; + function MAXIMUM (L : BOOLEAN_VECTOR) return BOOLEAN; + + function "and" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "and" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + function "or" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "or" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + function "nand" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "nand" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + function "nor" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "nor" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + function "xor" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "xor" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + function "xnor" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "xnor" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + + function and_reduce (L : BIT_VECTOR) return BIT; + function or_reduce (L : BIT_VECTOR) return BIT; + function nand_reduce (L : BIT_VECTOR) return BIT; + function nor_reduce (L : BIT_VECTOR) return BIT; + function xor_reduce (L : BIT_VECTOR) return BIT; + function xnor_reduce (L : BIT_VECTOR) return BIT; + + function \?=\ (L, R : BIT_VECTOR) return BIT; + function \?/=\ (L, R : BIT_VECTOR) return BIT; + + function MINIMUM (L, R : BIT_VECTOR) return BIT_VECTOR; + function MAXIMUM (L, R : BIT_VECTOR) return BIT_VECTOR; + + function MINIMUM (L : BIT_VECTOR) return BIT; + function MAXIMUM (L : BIT_VECTOR) return BIT; + + function TO_STRING (VALUE : BIT_VECTOR) return STRING; + + alias TO_BSTRING is TO_STRING [BIT_VECTOR return STRING]; + alias TO_BINARY_STRING is TO_STRING [BIT_VECTOR return STRING]; + function TO_OSTRING (VALUE : BIT_VECTOR) return STRING; + alias TO_OCTAL_STRING is TO_OSTRING [BIT_VECTOR return STRING]; + function TO_HSTRING (VALUE : BIT_VECTOR) return STRING; + alias TO_HEX_STRING is TO_HSTRING [BIT_VECTOR return STRING]; + + type INTEGER_VECTOR is array (NATURAL range <>) of INTEGER; + + -- The predefined operations for this type are as follows: + function "=" (L, R : INTEGER_VECTOR) return BOOLEAN; + function "/=" (L, R : INTEGER_VECTOR) return BOOLEAN; + function "<" (L, R : INTEGER_VECTOR) return BOOLEAN; + function "<=" (L, R : INTEGER_VECTOR) return BOOLEAN; + function ">" (L, R : INTEGER_VECTOR) return BOOLEAN; + function ">=" (L, R : INTEGER_VECTOR) return BOOLEAN; + +-- function "&" (L : INTEGER_VECTOR; R : INTEGER_VECTOR) +-- return INTEGER_VECTOR; +-- function "&" (L : INTEGER_VECTOR; R : INTEGER) return INTEGER_VECTOR; +-- function "&" (L : INTEGER; R : INTEGER_VECTOR) return INTEGER_VECTOR; +-- function "&" (L : INTEGER; R : INTEGER) return INTEGER_VECTOR; + + function MINIMUM (L, R : INTEGER_VECTOR) return INTEGER_VECTOR; + function MAXIMUM (L, R : INTEGER_VECTOR) return INTEGER_VECTOR; + + function MINIMUM (L : INTEGER_VECTOR) return INTEGER; + function MAXIMUM (L : INTEGER_VECTOR) return INTEGER; + + type REAL_VECTOR is array (NATURAL range <>) of REAL; + + -- The predefined operations for this type are as follows: + function "=" (L, R : REAL_VECTOR) return BOOLEAN; + function "/=" (L, R : REAL_VECTOR) return BOOLEAN; + function "<" (L, R : REAL_VECTOR) return BOOLEAN; + function "<=" (L, R : REAL_VECTOR) return BOOLEAN; + function ">" (L, R : REAL_VECTOR) return BOOLEAN; + function ">=" (L, R : REAL_VECTOR) return BOOLEAN; + +-- function "&" (L : REAL_VECTOR; R : REAL_VECTOR) +-- return REAL_VECTOR; +-- function "&" (L : REAL_VECTOR; R : REAL) return REAL_VECTOR; +-- function "&" (L : REAL; R : REAL_VECTOR) return REAL_VECTOR; +-- function "&" (L : REAL; R : REAL) return REAL_VECTOR; + + function MINIMUM (L, R : REAL_VECTOR) return REAL_VECTOR; + function MAXIMUM (L, R : REAL_VECTOR) return REAL_VECTOR; + + function MINIMUM (L : REAL_VECTOR) return REAL; + function MAXIMUM (L : REAL_VECTOR) return REAL; + + type TIME_VECTOR is array (NATURAL range <>) of TIME; + + -- The predefined operations for this type are as follows: + function "=" (L, R : TIME_VECTOR) return BOOLEAN; + function "/=" (L, R : TIME_VECTOR) return BOOLEAN; + function "<" (L, R : TIME_VECTOR) return BOOLEAN; + function "<=" (L, R : TIME_VECTOR) return BOOLEAN; + function ">" (L, R : TIME_VECTOR) return BOOLEAN; + function ">=" (L, R : TIME_VECTOR) return BOOLEAN; + +-- function "&" (L : TIME_VECTOR; R : TIME_VECTOR) +-- return TIME_VECTOR; +-- function "&" (L : TIME_VECTOR; R : TIME) return TIME_VECTOR; +-- function "&" (L : TIME; R : TIME_VECTOR) return TIME_VECTOR; +-- function "&" (L : TIME; R : TIME) return TIME_VECTOR; + + function MINIMUM (L, R : TIME_VECTOR) return TIME_VECTOR; + function MAXIMUM (L, R : TIME_VECTOR) return TIME_VECTOR; + + function MINIMUM (L : TIME_VECTOR) return TIME; + function MAXIMUM (L : TIME_VECTOR) return TIME; + + function MINIMUM (L, R : FILE_OPEN_KIND) return FILE_OPEN_KIND; + function MAXIMUM (L, R : FILE_OPEN_KIND) return FILE_OPEN_KIND; + + function MINIMUM (L, R : FILE_OPEN_STATUS) return FILE_OPEN_STATUS; + function MAXIMUM (L, R : FILE_OPEN_STATUS) return FILE_OPEN_STATUS; + + -- predefined TO_STRING operations on scalar types + function TO_STRING (VALUE : BOOLEAN) return STRING; + function TO_STRING (VALUE : BIT) return STRING; + function TO_STRING (VALUE : CHARACTER) return STRING; + function TO_STRING (VALUE : SEVERITY_LEVEL) return STRING; + function TO_STRING (VALUE : INTEGER) return STRING; + function TO_STRING (VALUE : REAL) return STRING; + function TO_STRING (VALUE : TIME) return STRING; + function TO_STRING (VALUE : FILE_OPEN_KIND) return STRING; + function TO_STRING (VALUE : FILE_OPEN_STATUS) return STRING; + + -- predefined overloaded TO_STRING operations + function TO_STRING (VALUE : REAL; DIGITS : NATURAL) return STRING; + function TO_STRING (VALUE : REAL; FORMAT : STRING) return STRING; + function TO_STRING (VALUE : TIME; UNIT : TIME) return STRING; +end package standard_additions; + +------------------------------------------------------------------------------ +-- "standard_additions" package contains the additions to the built in +-- "standard.std" package. In the final version this package will be implicit. +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ +use std.textio.all; +package body standard_additions is + + function \?=\ (L, R : BOOLEAN) return BOOLEAN is + begin + return L = R; + end function \?=\; + + function \?/=\ (L, R : BOOLEAN) return BOOLEAN is + begin + return L /= R; + end function \?/=\; + + function \?<\ (L, R : BOOLEAN) return BOOLEAN is + begin + return L < R; + end function \?<\; + + function \?<=\ (L, R : BOOLEAN) return BOOLEAN is + begin + return L <= R; + end function \?<=\; + + function \?>\ (L, R : BOOLEAN) return BOOLEAN is + begin + return L > R; + end function \?>\; + + function \?>=\ (L, R : BOOLEAN) return BOOLEAN is + begin + return L >= R; + end function \?>=\; + + function MINIMUM (L, R : BOOLEAN) return BOOLEAN is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + function MAXIMUM (L, R : BOOLEAN) return BOOLEAN is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function TO_STRING (VALUE : BOOLEAN) return STRING is + begin + return BOOLEAN'image(VALUE); + end function TO_STRING; + + function RISING_EDGE (signal S : BOOLEAN) return BOOLEAN is + begin + return (s'event and (s = true) and (s'last_value = false)); + end function rising_edge; + + function FALLING_EDGE (signal S : BOOLEAN) return BOOLEAN is + begin + return (s'event and (s = false) and (s'last_value = true)); + end function falling_edge; + + function \?=\ (L, R : BIT) return BIT is + begin + if L = R then + return '1'; + else + return '0'; + end if; + end function \?=\; + + function \?/=\ (L, R : BIT) return BIT is + begin + if L /= R then + return '1'; + else + return '0'; + end if; + end function \?/=\; + + function \?<\ (L, R : BIT) return BIT is + begin + if L < R then + return '1'; + else + return '0'; + end if; + end function \?<\; + + function \?<=\ (L, R : BIT) return BIT is + begin + if L <= R then + return '1'; + else + return '0'; + end if; + end function \?<=\; + + function \?>\ (L, R : BIT) return BIT is + begin + if L > R then + return '1'; + else + return '0'; + end if; + end function \?>\; + + function \?>=\ (L, R : BIT) return BIT is + begin + if L >= R then + return '1'; + else + return '0'; + end if; + end function \?>=\; + + function MINIMUM (L, R : BIT) return BIT is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : BIT) return BIT is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function TO_STRING (VALUE : BIT) return STRING is + begin + if VALUE = '1' then + return "1"; + else + return "0"; + end if; + end function TO_STRING; + + function \??\ (L : BIT) return BOOLEAN is + begin + return L = '1'; + end function \??\; + + function RISING_EDGE (signal S : BIT) return BOOLEAN is + begin + return (s'event and (s = '1') and (s'last_value = '0')); + end function rising_edge; + + function FALLING_EDGE (signal S : BIT) return BOOLEAN is + begin + return (s'event and (s = '0') and (s'last_value = '1')); + end function falling_edge; + + function MINIMUM (L, R : CHARACTER) return CHARACTER is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : CHARACTER) return CHARACTER is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function TO_STRING (VALUE : CHARACTER) return STRING is + variable result : STRING (1 to 1); + begin + result (1) := VALUE; + return result; + end function TO_STRING; + + function MINIMUM (L, R : SEVERITY_LEVEL) return SEVERITY_LEVEL is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : SEVERITY_LEVEL) return SEVERITY_LEVEL is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function TO_STRING (VALUE : SEVERITY_LEVEL) return STRING is + begin + return SEVERITY_LEVEL'image(VALUE); + end function TO_STRING; + + function MINIMUM (L, R : INTEGER) return INTEGER is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : INTEGER) return INTEGER is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function TO_STRING (VALUE : INTEGER) return STRING is + begin + return INTEGER'image(VALUE); + end function TO_STRING; + + function MINIMUM (L, R : REAL) return REAL is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : REAL) return REAL is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function TO_STRING (VALUE : REAL) return STRING is + begin + return REAL'image (VALUE); + end function TO_STRING; + + function TO_STRING (VALUE : REAL; DIGITS : NATURAL) return STRING is + begin + return to_string (VALUE, "%1." & INTEGER'image(DIGITS) & "f"); + end function TO_STRING; + + function "mod" (L, R : TIME) return TIME is + variable lint, rint : INTEGER; + begin + lint := L / 1.0 ns; + rint := R / 1.0 ns; + return (lint mod rint) * 1.0 ns; + end function "mod"; + + function "rem" (L, R : TIME) return TIME is + variable lint, rint : INTEGER; + begin + lint := L / 1.0 ns; + rint := R / 1.0 ns; + return (lint rem rint) * 1.0 ns; + end function "rem"; + + function MINIMUM (L, R : TIME) return TIME is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : TIME) return TIME is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function TO_STRING (VALUE : TIME) return STRING is + begin + return TIME'image (VALUE); + end function TO_STRING; + + function MINIMUM (L, R : STRING) return STRING is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : STRING) return STRING is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function MINIMUM (L : STRING) return CHARACTER is + variable result : CHARACTER := CHARACTER'high; + begin + for i in l'range loop + result := minimum (l(i), result); + end loop; + return result; + end function MINIMUM; + + function MAXIMUM (L : STRING) return CHARACTER is + variable result : CHARACTER := CHARACTER'low; + begin + for i in l'range loop + result := maximum (l(i), result); + end loop; + return result; + end function MAXIMUM; + + -- type BOOLEAN_VECTOR is array (NATURAL range <>) of BOOLEAN; + -- The predefined operations for this type are as follows: + function "and" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "STD.""and"": " + & "arguments of overloaded 'and' operator are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := (lv(i) and rv(i)); + end loop; + end if; + return result; + end function "and"; + + function "or" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "STD.""or"": " + & "arguments of overloaded 'or' operator are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := (lv(i) or rv(i)); + end loop; + end if; + return result; + end function "or"; + + function "nand" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "STD.""nand"": " + & "arguments of overloaded 'nand' operator are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := (lv(i) nand rv(i)); + end loop; + end if; + return result; + end function "nand"; + + function "nor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "STD.""nor"": " + & "arguments of overloaded 'nor' operator are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := (lv(i) nor rv(i)); + end loop; + end if; + return result; + end function "nor"; + + function "xor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "STD.""xor"": " + & "arguments of overloaded 'xor' operator are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := (lv(i) xor rv(i)); + end loop; + end if; + return result; + end function "xor"; + + function "xnor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "STD.""xnor"": " + & "arguments of overloaded 'xnor' operator are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := (lv(i) xnor rv(i)); + end loop; + end if; + return result; + end function "xnor"; + + function "not" (L : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := not (lv(i)); + end loop; + return result; + end function "not"; + + function "and" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) and r; + end loop; + return result; + end function "and"; + + function "and" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l and rv(i); + end loop; + return result; + end function "and"; + + function "or" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) or r; + end loop; + return result; + end function "or"; + + function "or" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l or rv(i); + end loop; + return result; + end function "or"; + + function "nand" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) nand r; + end loop; + return result; + end function "nand"; + + function "nand" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l nand rv(i); + end loop; + return result; + end function "nand"; + + function "nor" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) nor r; + end loop; + return result; + end function "nor"; + + function "nor" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l nor rv(i); + end loop; + return result; + end function "nor"; + + function "xor" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) xor r; + end loop; + return result; + end function "xor"; + + function "xor" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l xor rv(i); + end loop; + return result; + end function "xor"; + + function "xnor" (L : BOOLEAN_VECTOR; R : BOOLEAN) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) xnor r; + end loop; + return result; + end function "xnor"; + + function "xnor" (L : BOOLEAN; R : BOOLEAN_VECTOR) + return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l xnor rv(i); + end loop; + return result; + end function "xnor"; + + function and_reduce (L : BOOLEAN_VECTOR) return BOOLEAN is + variable result : BOOLEAN := true; + begin + for i in l'reverse_range loop + result := l(i) and result; + end loop; + return result; + end function and_reduce; + + function or_reduce (L : BOOLEAN_VECTOR) return BOOLEAN is + variable result : BOOLEAN := false; + begin + for i in l'reverse_range loop + result := l(i) or result; + end loop; + return result; + end function or_reduce; + + function nand_reduce (L : BOOLEAN_VECTOR) return BOOLEAN is + variable result : BOOLEAN := true; + begin + for i in l'reverse_range loop + result := l(i) and result; + end loop; + return not result; + end function nand_reduce; + + function nor_reduce (L : BOOLEAN_VECTOR) return BOOLEAN is + variable result : BOOLEAN := false; + begin + for i in l'reverse_range loop + result := l(i) or result; + end loop; + return not result; + end function nor_reduce; + + function xor_reduce (L : BOOLEAN_VECTOR) return BOOLEAN is + variable result : BOOLEAN := false; + begin + for i in l'reverse_range loop + result := l(i) xor result; + end loop; + return result; + end function xor_reduce; + + function xnor_reduce (L : BOOLEAN_VECTOR) return BOOLEAN is + variable result : BOOLEAN := false; + begin + for i in l'reverse_range loop + result := l(i) xor result; + end loop; + return not result; + end function xnor_reduce; + + function "sll" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if r >= 0 then + result(1 to l'length - r) := lv(r + 1 to l'length); + else + result := l srl -r; + end if; + return result; + end function "sll"; + + function "srl" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if r >= 0 then + result(r + 1 to l'length) := lv(1 to l'length - r); + else + result := l sll -r; + end if; + return result; + end function "srl"; + + function "sla" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in L'range loop + result (i) := L(L'high); + end loop; + if r >= 0 then + result(1 to l'length - r) := lv(r + 1 to l'length); + else + result := l sra -r; + end if; + return result; + end function "sla"; + + function "sra" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in L'range loop + result (i) := L(L'low); + end loop; + if r >= 0 then + result(1 to l'length - r) := lv(r + 1 to l'length); + else + result := l sra -r; + end if; + return result; + end function "sra"; + + function "rol" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + constant rm : INTEGER := r mod l'length; + begin + if r >= 0 then + result(1 to l'length - rm) := lv(rm + 1 to l'length); + result(l'length - rm + 1 to l'length) := lv(1 to rm); + else + result := l ror -r; + end if; + return result; + end function "rol"; + + function "ror" (L : BOOLEAN_VECTOR; R : INTEGER) + return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + constant rm : INTEGER := r mod l'length; + begin + if r >= 0 then + result(rm + 1 to l'length) := lv(1 to l'length - rm); + result(1 to rm) := lv(l'length - rm + 1 to l'length); + else + result := l rol -r; + end if; + return result; + end function "ror"; +-- function "=" (L, R: BOOLEAN_VECTOR) return BOOLEAN; +-- function "/=" (L, R: BOOLEAN_VECTOR) return BOOLEAN; +-- function "<" (L, R: BOOLEAN_VECTOR) return BOOLEAN; +-- function "<=" (L, R: BOOLEAN_VECTOR) return BOOLEAN; +-- function ">" (L, R: BOOLEAN_VECTOR) return BOOLEAN; +-- function ">=" (L, R: BOOLEAN_VECTOR) return BOOLEAN; + + function \?=\ (L, R : BOOLEAN_VECTOR) return BOOLEAN is + begin + return L = R; + end function \?=\; + + function \?/=\ (L, R : BOOLEAN_VECTOR) return BOOLEAN is + begin + return L /= R; + end function \?/=\; +-- function "&" (L: BOOLEAN_VECTOR; R: BOOLEAN_VECTOR) +-- return BOOLEAN_VECTOR; +-- function "&" (L: BOOLEAN_VECTOR; R: BOOLEAN) return BOOLEAN_VECTOR; +-- function "&" (L: BOOLEAN; R: BOOLEAN_VECTOR) return BOOLEAN_VECTOR; +-- function "&" (L: BOOLEAN; R: BOOLEAN) return BOOLEAN_VECTOR; + + function MINIMUM (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function MINIMUM (L : BOOLEAN_VECTOR) return BOOLEAN is + variable result : BOOLEAN := BOOLEAN'high; + begin + for i in l'range loop + result := minimum (l(i), result); + end loop; + return result; + end function MINIMUM; + + function MAXIMUM (L : BOOLEAN_VECTOR) return BOOLEAN is + variable result : BOOLEAN := BOOLEAN'low; + begin + for i in l'range loop + result := maximum (l(i), result); + end loop; + return result; + end function MAXIMUM; + + function "and" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) and r; + end loop; + return result; + end function "and"; + + function "and" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l and rv(i); + end loop; + return result; + end function "and"; + + function "or" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) or r; + end loop; + return result; + end function "or"; + + function "or" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l or rv(i); + end loop; + return result; + end function "or"; + + function "nand" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) and r; + end loop; + return not result; + end function "nand"; + + function "nand" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l and rv(i); + end loop; + return not result; + end function "nand"; + + function "nor" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) or r; + end loop; + return not result; + end function "nor"; + + function "nor" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l or rv(i); + end loop; + return not result; + end function "nor"; + + function "xor" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) xor r; + end loop; + return result; + end function "xor"; + + function "xor" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l xor rv(i); + end loop; + return result; + end function "xor"; + + function "xnor" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) xor r; + end loop; + return not result; + end function "xnor"; + + function "xnor" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l xor rv(i); + end loop; + return not result; + end function "xnor"; + + function and_reduce (L : BIT_VECTOR) return BIT is + variable result : BIT := '1'; + begin + for i in l'reverse_range loop + result := l(i) and result; + end loop; + return result; + end function and_reduce; + + function or_reduce (L : BIT_VECTOR) return BIT is + variable result : BIT := '0'; + begin + for i in l'reverse_range loop + result := l(i) or result; + end loop; + return result; + end function or_reduce; + + function nand_reduce (L : BIT_VECTOR) return BIT is + variable result : BIT := '1'; + begin + for i in l'reverse_range loop + result := l(i) and result; + end loop; + return not result; + end function nand_reduce; + + function nor_reduce (L : BIT_VECTOR) return BIT is + variable result : BIT := '0'; + begin + for i in l'reverse_range loop + result := l(i) or result; + end loop; + return not result; + end function nor_reduce; + + function xor_reduce (L : BIT_VECTOR) return BIT is + variable result : BIT := '0'; + begin + for i in l'reverse_range loop + result := l(i) xor result; + end loop; + return result; + end function xor_reduce; + + function xnor_reduce (L : BIT_VECTOR) return BIT is + variable result : BIT := '0'; + begin + for i in l'reverse_range loop + result := l(i) xor result; + end loop; + return not result; + end function xnor_reduce; + + function \?=\ (L, R : BIT_VECTOR) return BIT is + begin + if L = R then + return '1'; + else + return '0'; + end if; + end function \?=\; + + function \?/=\ (L, R : BIT_VECTOR) return BIT is + begin + if L /= R then + return '1'; + else + return '0'; + end if; + end function \?/=\; + + function MINIMUM (L, R : BIT_VECTOR) return BIT_VECTOR is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : BIT_VECTOR) return BIT_VECTOR is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function MINIMUM (L : BIT_VECTOR) return BIT is + variable result : BIT := BIT'high; + begin + for i in l'range loop + result := minimum (l(i), result); + end loop; + return result; + end function MINIMUM; + + function MAXIMUM (L : BIT_VECTOR) return BIT is + variable result : BIT := BIT'low; + begin + for i in l'range loop + result := maximum (l(i), result); + end loop; + return result; + end function MAXIMUM; + + function TO_STRING (VALUE : BIT_VECTOR) return STRING is + alias ivalue : BIT_VECTOR(1 to value'length) is value; + variable result : STRING(1 to value'length); + begin + if value'length < 1 then + return ""; + else + for i in ivalue'range loop + if iValue(i) = '0' then + result(i) := '0'; + else + result(i) := '1'; + end if; + end loop; + return result; + end if; + end function to_string; + +-- alias TO_BSTRING is TO_STRING [BIT_VECTOR return STRING]; +-- alias TO_BINARY_STRING is TO_STRING [BIT_VECTOR return STRING]; + + function TO_OSTRING (VALUE : BIT_VECTOR) return STRING is + constant ne : INTEGER := (value'length+2)/3; + constant pad : BIT_VECTOR(0 to (ne*3 - value'length) - 1) := (others => '0'); + variable ivalue : BIT_VECTOR(0 to ne*3 - 1); + variable result : STRING(1 to ne); + variable tri : BIT_VECTOR(0 to 2); + begin + if value'length < 1 then + return ""; + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + tri := 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'; + end case; + end loop; + return result; + end function to_ostring; +-- alias TO_OCTAL_STRING is TO_OSTRING [BIT_VECTOR return STRING]; + + function TO_HSTRING (VALUE : BIT_VECTOR) return STRING is + constant ne : INTEGER := (value'length+3)/4; + constant pad : BIT_VECTOR(0 to (ne*4 - value'length) - 1) := (others => '0'); + variable ivalue : BIT_VECTOR(0 to ne*4 - 1); + variable result : STRING(1 to ne); + variable quad : BIT_VECTOR(0 to 3); + begin + if value'length < 1 then + return ""; + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + quad := 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'; + end case; + end loop; + return result; + end function to_hstring; +-- alias TO_HEX_STRING is TO_HSTRING [BIT_VECTOR return STRING]; + +-- type INTEGER_VECTOR is array (NATURAL range <>) of INTEGER; + -- The predefined operations for this type are as follows: + + function "=" (L, R : INTEGER_VECTOR) return BOOLEAN is + begin + if L'length /= R'length or L'length < 1 or R'length < 1 then + return false; + else + for i in l'range loop + if L(i) /= R(i) then + return false; + end if; + end loop; + return true; + end if; + end function "="; + + function "/=" (L, R : INTEGER_VECTOR) return BOOLEAN is + begin + return not (L = R); + end function "/="; + + function "<" (L, R : INTEGER_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length < R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) < R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return false; + end if; + end function "<"; + + function "<=" (L, R : INTEGER_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length < R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) < R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return true; + end if; + end function "<="; + + function ">" (L, R : INTEGER_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length > R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) > R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return false; + end if; + end function ">"; + + function ">=" (L, R : INTEGER_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length > R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) > R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return true; + end if; + end function ">="; +-- function "&" (L: INTEGER_VECTOR; R: INTEGER_VECTOR) +-- return INTEGER_VECTOR; +-- function "&" (L: INTEGER_VECTOR; R: INTEGER) return INTEGER_VECTOR; +-- function "&" (L: INTEGER; R: INTEGER_VECTOR) return INTEGER_VECTOR; +-- function "&" (L: INTEGER; R: INTEGER) return INTEGER_VECTOR; + + function MINIMUM (L, R : INTEGER_VECTOR) return INTEGER_VECTOR is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : INTEGER_VECTOR) return INTEGER_VECTOR is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function MINIMUM (L : INTEGER_VECTOR) return INTEGER is + variable result : INTEGER := INTEGER'high; + begin + for i in l'range loop + result := minimum (l(i), result); + end loop; + return result; + end function MINIMUM; + + function MAXIMUM (L : INTEGER_VECTOR) return INTEGER is + variable result : INTEGER := INTEGER'low; + begin + for i in l'range loop + result := maximum (l(i), result); + end loop; + return result; + end function MAXIMUM; + + -- type REAL_VECTOR is array (NATURAL range <>) of REAL; + -- The predefined operations for this type are as follows: + function "=" (L, R : REAL_VECTOR) return BOOLEAN is + begin + if L'length /= R'length or L'length < 1 or R'length < 1 then + return false; + else + for i in l'range loop + if L(i) /= R(i) then + return false; + end if; + end loop; + return true; + end if; + end function "="; + + function "/=" (L, R : REAL_VECTOR) return BOOLEAN is + begin + return not (L = R); + end function "/="; + + function "<" (L, R : REAL_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length < R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) < R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return false; + end if; + end function "<"; + + function "<=" (L, R : REAL_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length < R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) < R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return true; + end if; + end function "<="; + + function ">" (L, R : REAL_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length > R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) > R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return false; + end if; + end function ">"; + + function ">=" (L, R : REAL_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length > R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) > R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return true; + end if; + end function ">="; +-- function "&" (L: REAL_VECTOR; R: REAL_VECTOR) +-- return REAL_VECTOR; +-- function "&" (L: REAL_VECTOR; R: REAL) return REAL_VECTOR; +-- function "&" (L: REAL; R: REAL_VECTOR) return REAL_VECTOR; +-- function "&" (L: REAL; R: REAL) return REAL_VECTOR; + + function MINIMUM (L, R : REAL_VECTOR) return REAL_VECTOR is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : REAL_VECTOR) return REAL_VECTOR is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function MINIMUM (L : REAL_VECTOR) return REAL is + variable result : REAL := REAL'high; + begin + for i in l'range loop + result := minimum (l(i), result); + end loop; + return result; + end function MINIMUM; + + function MAXIMUM (L : REAL_VECTOR) return REAL is + variable result : REAL := REAL'low; + begin + for i in l'range loop + result := maximum (l(i), result); + end loop; + return result; + end function MAXIMUM; + + -- type TIME_VECTOR is array (NATURAL range <>) of TIME; + -- The predefined implicit operations for this type are as follows: + function "=" (L, R : TIME_VECTOR) return BOOLEAN is + begin + if L'length /= R'length or L'length < 1 or R'length < 1 then + return false; + else + for i in l'range loop + if L(i) /= R(i) then + return false; + end if; + end loop; + return true; + end if; + end function "="; + + function "/=" (L, R : TIME_VECTOR) return BOOLEAN is + begin + return not (L = R); + end function "/="; + + function "<" (L, R : TIME_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length < R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) < R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return false; + end if; + end function "<"; + + function "<=" (L, R : TIME_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length < R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) < R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return true; + end if; + end function "<="; + + function ">" (L, R : TIME_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length > R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) > R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return false; + end if; + end function ">"; + + function ">=" (L, R : TIME_VECTOR) return BOOLEAN is + begin + if L'length /= R'length then + return L'length > R'length; + else + for i in l'range loop + if L(i) /= R(i) then + if L(i) > R(i) then + return true; + else + return false; + end if; + end if; + end loop; + return true; + end if; + end function ">="; +-- function "&" (L: TIME_VECTOR; R: TIME_VECTOR) +-- return TIME_VECTOR; +-- function "&" (L: TIME_VECTOR; R: TIME) return TIME_VECTOR; +-- function "&" (L: TIME; R: TIME_VECTOR) return TIME_VECTOR; +-- function "&" (L: TIME; R: TIME) return TIME_VECTOR; + + function MINIMUM (L, R : TIME_VECTOR) return TIME_VECTOR is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : TIME_VECTOR) return TIME_VECTOR is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function MINIMUM (L : TIME_VECTOR) return TIME is + variable result : TIME := TIME'high; + begin + for i in l'range loop + result := minimum (l(i), result); + end loop; + return result; + end function MINIMUM; + + function MAXIMUM (L : TIME_VECTOR) return TIME is + variable result : TIME := TIME'low; + begin + for i in l'range loop + result := maximum (l(i), result); + end loop; + return result; + end function MAXIMUM; + + function MINIMUM (L, R : FILE_OPEN_KIND) return FILE_OPEN_KIND is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : FILE_OPEN_KIND) return FILE_OPEN_KIND is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function TO_STRING (VALUE : FILE_OPEN_KIND) return STRING is + begin + return FILE_OPEN_KIND'image(VALUE); + end function TO_STRING; + + function MINIMUM (L, R : FILE_OPEN_STATUS) return FILE_OPEN_STATUS is + begin + if L > R then return R; + else return L; + end if; + end function MINIMUM; + + function MAXIMUM (L, R : FILE_OPEN_STATUS) return FILE_OPEN_STATUS is + begin + if L > R then return L; + else return R; + end if; + end function MAXIMUM; + + function TO_STRING (VALUE : FILE_OPEN_STATUS) return STRING is + begin + return FILE_OPEN_STATUS'image(VALUE); + end function TO_STRING; + + -- USED INTERNALLY! + function justify ( + value : in STRING; + justified : in SIDE := right; + field : in 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_STRING (VALUE : TIME; UNIT : TIME) return STRING is + variable L : LINE; -- pointer + begin + deallocate (L); + write (L => L, + VALUE => VALUE, + UNIT => UNIT); + return L.all; + end function to_string; + + function TO_STRING (VALUE : REAL; FORMAT : STRING) return STRING is + constant czero : CHARACTER := '0'; -- zero + constant half : REAL := 0.4999999999; -- almost 0.5 + -- Log10 funciton + function log10 (arg : REAL) return INTEGER is + variable i : INTEGER := 1; + begin + if ((arg = 0.0)) then + return 0; + elsif arg >= 1.0 then + while arg >= 10.0**i loop + i := i + 1; + end loop; + return (i-1); + else + while arg < 10.0**i loop + i := i - 1; + end loop; + return i; + end if; + end function log10; + -- purpose: writes a fractional real number into a line + procedure writefrc ( + variable L : inout LINE; -- LINE + variable cdes : in CHARACTER; + variable precision : in INTEGER; -- number of decimal places + variable value : in REAL) is -- real value + variable rvar : REAL; -- temp variable + variable xint : INTEGER; + variable xreal : REAL; + begin + xreal := (10.0**(-precision)); + write (L, '.'); + rvar := value; + for i in 1 to precision loop + rvar := rvar * 10.0; + xint := INTEGER(rvar-0.49999999999); -- round + write (L, xint); + rvar := rvar - REAL(xint); + xreal := xreal * 10.0; + if (cdes = 'g') and (rvar < xreal) then + exit; + end if; + end loop; + end procedure writefrc; + -- purpose: replace the "." with a "@", and "e" with "j" to get around + -- read ("6.") and read ("2e") issues. + function subdot ( + constant format : STRING) + return STRING is + variable result : STRING (format'range); + begin + for i in format'range loop + if (format(i) = '.') then + result(i) := '@'; -- Because the parser reads 6.2 as REAL + elsif (format(i) = 'e') then + result(i) := 'j'; -- Because the parser read 2e as REAL + elsif (format(i) = 'E') then + result(i) := 'J'; -- Because the parser reads 2E as REAL + else + result(i) := format(i); + end if; + end loop; + return result; + end function subdot; + -- purpose: find a . in a STRING + function isdot ( + constant format : STRING) + return BOOLEAN is + begin + for i in format'range loop + if (format(i) = '@') then + return true; + end if; + end loop; + return false; + end function isdot; + variable exp : INTEGER; -- integer version of baseexp + variable bvalue : REAL; -- base value + variable roundvar, tvar : REAL; -- Rounding values + variable frcptr : INTEGER; -- integer version of number + variable fwidth, dwidth : INTEGER; -- field width and decimal width + variable dash, dot : BOOLEAN := false; + variable cdes, ddes : CHARACTER := ' '; + variable L : LINE; -- line type + begin + -- Perform the same function that "printf" does + -- examples "%6.2f" "%-7e" "%g" + if not (format(format'left) = '%') then + report "to_string: Illegal format string """ & format & '"' + severity error; + return ""; + end if; + L := new STRING'(subdot(format)); + read (L, ddes); -- toss the '%' + case L.all(1) is + when '-' => dash := true; + when '@' => dash := true; -- in FP, a "-" and a "." are the same + when 'f' => cdes := 'f'; + when 'F' => cdes := 'F'; + when 'g' => cdes := 'g'; + when 'G' => cdes := 'G'; + when 'j' => cdes := 'e'; -- parser reads 5e as real, thus we sub j + when 'J' => cdes := 'E'; + when '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' => null; + when others => + report "to_string: Illegal format string """ & format & '"' + severity error; + return ""; + end case; + if (dash or (cdes /= ' ')) then + read (L, ddes); -- toss the next character + end if; + if (cdes = ' ') then + if (isdot(L.all)) then -- if you see a . two numbers + read (L, fwidth); -- read field width + read (L, ddes); -- toss the next character . + read (L, dwidth); -- read decimal width + else + read (L, fwidth); -- read field width + dwidth := 6; -- the default decimal width is 6 + end if; + read (L, cdes); + if (cdes = 'j') then + cdes := 'e'; -- because 2e reads as "REAL". + elsif (cdes = 'J') then + cdes := 'E'; + end if; + else + if (cdes = 'E' or cdes = 'e') then + fwidth := 10; -- default for e and E is %10.6e + else + fwidth := 0; -- default for f and g is %0.6f + end if; + dwidth := 6; + end if; + deallocate (L); -- reclame the pointer L. +-- assert (not debug) report "Format: " & format & " " +-- & INTEGER'image(fwidth) & "." & INTEGER'image(dwidth) & cdes +-- severity note; + if (not (cdes = 'f' or cdes = 'F' or cdes = 'g' or cdes = 'G' + or cdes = 'e' or cdes = 'E')) then + report "to_string: Illegal format """ & format & '"' severity error; + return ""; + end if; + if (VALUE < 0.0) then + bvalue := -value; + write (L, '-'); + else + bvalue := value; + end if; + case cdes is + when 'e' | 'E' => -- 7.000E+01 + exp := log10(bvalue); + roundvar := half*(10.0**(exp-dwidth)); + bvalue := bvalue + roundvar; -- round + exp := log10(bvalue); -- because we CAN overflow + bvalue := bvalue * (10.0**(-exp)); -- result is D.XXXXXX + frcptr := INTEGER(bvalue-half); -- Write a single digit. + write (L, frcptr); + bvalue := bvalue - REAL(frcptr); + writefrc (-- Write out the fraction + L => L, + cdes => cdes, + precision => dwidth, + value => bvalue); + write (L, cdes); -- e or E + if (exp < 0) then + write (L, '-'); + else + write (L, '+'); + end if; + exp := abs(exp); + if (exp < 10) then -- we need another "0". + write (L, czero); + end if; + write (L, exp); + when 'f' | 'F' => -- 70.0 + exp := log10(bvalue); + roundvar := half*(10.0**(-dwidth)); + bvalue := bvalue + roundvar; -- round + exp := log10(bvalue); -- because we CAN overflow + if (exp < 0) then -- 0.X case + write (L, czero); + else -- loop because real'high > integer'high + while (exp >= 0) loop + frcptr := INTEGER(bvalue * (10.0**(-exp)) - half); + write (L, frcptr); + bvalue := bvalue - (REAL(frcptr) * (10.0**exp)); + exp := exp-1; + end loop; + end if; + writefrc ( + L => L, + cdes => cdes, + precision => dwidth, + value => bvalue); + when 'g' | 'G' => -- 70 + exp := log10(bvalue); + roundvar := half*(10.0**(exp-dwidth)); -- small number + bvalue := bvalue + roundvar; -- round + exp := log10(bvalue); -- because we CAN overflow + frcptr := INTEGER(bvalue-half); + tvar := bvalue-roundvar - REAL(frcptr); -- even smaller number + if (exp < dwidth) + and (tvar < roundvar and tvar > -roundvar) then +-- and ((bvalue-roundvar) = real(frcptr)) then + write (L, frcptr); -- Just a short integer, write it. + elsif (exp >= dwidth) or (exp < -4) then + -- in "e" format (modified) + bvalue := bvalue * (10.0**(-exp)); -- result is D.XXXXXX + frcptr := INTEGER(bvalue-half); + write (L, frcptr); + bvalue := bvalue - REAL(frcptr); + if (bvalue > (10.0**(1-dwidth))) then + dwidth := dwidth - 1; + writefrc ( + L => L, + cdes => cdes, + precision => dwidth, + value => bvalue); + end if; + if (cdes = 'G') then + write (L, 'E'); + else + write (L, 'e'); + end if; + if (exp < 0) then + write (L, '-'); + else + write (L, '+'); + end if; + exp := abs(exp); + if (exp < 10) then + write (L, czero); + end if; + write (L, exp); + else + -- in "f" format (modified) + if (exp < 0) then + write (L, czero); + dwidth := maximum (dwidth, 4); -- if exp < -4 or > precision. + bvalue := bvalue - roundvar; -- recalculate rounding + roundvar := half*(10.0**(-dwidth)); + bvalue := bvalue + roundvar; + else + write (L, frcptr); -- integer part (always small) + bvalue := bvalue - (REAL(frcptr)); + dwidth := dwidth - exp - 1; + end if; + if (bvalue > roundvar) then + writefrc ( + L => L, + cdes => cdes, + precision => dwidth, + value => bvalue); + end if; + end if; + when others => return ""; + end case; + -- You don't truncate real numbers. +-- if (dot) then -- truncate +-- if (L.all'length > fwidth) then +-- return justify (value => L.all (1 to fwidth), +-- justified => RIGHT, +-- field => fwidth); +-- else +-- return justify (value => L.all, +-- justified => RIGHT, +-- field => fwidth); +-- end if; + if (dash) then -- fill to fwidth + return justify (value => L.all, + justified => left, + field => fwidth); + else + return justify (value => L.all, + justified => right, + field => fwidth); + end if; + end function to_string; + +end package body standard_additions; diff --git a/ieee_proposed/rtl/standard_textio_additions_c.vhd b/ieee_proposed/rtl/standard_textio_additions_c.vhd new file mode 100644 index 0000000..35ed5d0 --- /dev/null +++ b/ieee_proposed/rtl/standard_textio_additions_c.vhd @@ -0,0 +1,478 @@ +------------------------------------------------------------------------------ +-- "standard_textio_additions" package contains the additions to the built in +-- "standard.textio" package. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee_proposed.standard_textio_additions.all; +-- Last Modified: $Date: 2007-03-13 14:25:58-04 $ +-- RCS ID: $Id: standard_textio_additions_c.vhdl,v 1.5 2007-03-13 14:25:58-04 l435385 Exp $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ +use std.textio.all; +package standard_textio_additions is + +-- procedure DEALLOCATE (P : inout LINE); + + procedure FLUSH (file F : TEXT); + + function MINIMUM (L, R : SIDE) return SIDE; + function MAXIMUM (L, R : SIDE) return SIDE; + + function TO_STRING (VALUE : SIDE) return STRING; + + function JUSTIFY (VALUE : STRING; JUSTIFIED : SIDE := right; FIELD : WIDTH := 0) return STRING; + + procedure SREAD (L : inout LINE; VALUE : out STRING; STRLEN : out NATURAL); + alias STRING_READ is SREAD [LINE, STRING, NATURAL]; + alias BREAD is READ [LINE, BIT_VECTOR, BOOLEAN]; + alias BREAD is READ [LINE, BIT_VECTOR]; + alias BINARY_READ is READ [LINE, BIT_VECTOR, BOOLEAN]; + alias BINARY_READ is READ [LINE, BIT_VECTOR]; + procedure OREAD (L : inout LINE; VALUE : out BIT_VECTOR; GOOD : out BOOLEAN); + procedure OREAD (L : inout LINE; VALUE : out BIT_VECTOR); + alias OCTAL_READ is OREAD [LINE, BIT_VECTOR, BOOLEAN]; + alias OCTAL_READ is OREAD [LINE, BIT_VECTOR]; + procedure HREAD (L : inout LINE; VALUE : out BIT_VECTOR; GOOD : out BOOLEAN); + procedure HREAD (L : inout LINE; VALUE : out BIT_VECTOR); + alias HEX_READ is HREAD [LINE, BIT_VECTOR, BOOLEAN]; + alias HEX_READ is HREAD [LINE, BIT_VECTOR]; + procedure TEE (file F : TEXT; L : inout LINE); + procedure WRITE (L : inout LINE; VALUE : in REAL; + FORMAT : in STRING); + alias SWRITE is WRITE [LINE, STRING, SIDE, WIDTH]; + alias STRING_WRITE is WRITE [LINE, STRING, SIDE, WIDTH]; + alias BWRITE is WRITE [LINE, BIT_VECTOR, SIDE, WIDTH]; + alias BINARY_WRITE is WRITE [LINE, BIT_VECTOR, SIDE, WIDTH]; + procedure OWRITE (L : inout LINE; VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + alias OCTAL_WRITE is OWRITE [LINE, BIT_VECTOR, SIDE, WIDTH]; + procedure HWRITE (L : inout LINE; VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + alias HEX_WRITE is HWRITE [LINE, BIT_VECTOR, SIDE, WIDTH]; + +end package standard_textio_additions; + +library ieee_proposed; +use ieee_proposed.standard_additions.all; + +package body standard_textio_additions is +-- pragma synthesis_off + constant NUS : STRING(2 to 1) := (others => ' '); -- NULL array + constant NBSP : CHARACTER := CHARACTER'val(160); -- space character + + -- Writes L to a file without modifying the contents of the line + procedure TEE (file F : TEXT; L : inout LINE) is + begin + write (OUTPUT, L.all & LF); + writeline(F, L); + end procedure TEE; + + procedure FLUSH (file F: TEXT) is -- Implicit + begin + file_close (F); + end procedure FLUSH; + + -- Read and Write procedure for strings + procedure SREAD (L : inout LINE; + VALUE : out STRING; + STRLEN : out natural) is + variable ok : BOOLEAN; + variable c : CHARACTER; + -- Result is padded with space characters + variable result : STRING (1 to VALUE'length) := (others => ' '); + begin + VALUE := result; + loop -- skip white space + read(L, c, ok); + exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + STRLEN := 0; + return; + end if; + result (1) := c; + STRLEN := 1; + for i in 2 to VALUE'length loop + read(L, c, ok); + if (ok = false) or ((c = ' ') or (c = NBSP) or (c = HT)) then + exit; + else + result (i) := c; + end if; + STRLEN := i; + end loop; + VALUE := result; + end procedure SREAD; + + -- Hex Read and Write procedures for bit_vector. + -- Procedure only visible internally. + procedure Char2QuadBits (C : CHARACTER; + RESULT : out BIT_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 others => + assert not ISSUE_ERROR report + "TEXTIO.HREAD Error: Read a '" & c & + "', expected a Hex character (0-F)." severity error; + GOOD := false; + end case; + end procedure Char2QuadBits; + + procedure HREAD (L : inout LINE; + VALUE : out BIT_VECTOR; + GOOD : out BOOLEAN) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : BIT_VECTOR (0 to ne*4 - 1) := (others => '0'); + variable s : STRING(1 to ne-1); + begin + VALUE := (VALUE'range => '0'); + loop -- skip white space + read(l, c, ok); + exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + GOOD := false; + return; + end if; + Char2QuadBits(c, sv(0 to 3), ok, false); + if not ok then + GOOD := false; + return; + end if; + read(L, s, ok); + if not ok then + GOOD := false; + return; + end if; + for i in 1 to ne-1 loop + Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, false); + if not ok then + GOOD := false; + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then + GOOD := false; -- vector was truncated. + else + GOOD := true; + VALUE := sv (pad to sv'high); + end if; + end procedure HREAD; + + procedure HREAD (L : inout LINE; + VALUE : out BIT_VECTOR) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : BIT_VECTOR(0 to ne*4 - 1) := (others => '0'); + variable s : STRING(1 to ne-1); + begin + VALUE := (VALUE'range => '0'); + loop -- skip white space + read(l, c, ok); + exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + report "TEXTIO.HREAD Error: Failed skipping white space" + severity error; + return; + end if; + Char2QuadBits(c, sv(0 to 3), ok, true); + if not ok then + return; + end if; + read(L, s, ok); + if not ok then + report "TEXTIO.HREAD Error: Failed to read the STRING" + severity error; + return; + end if; + for i in 1 to ne-1 loop + Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, true); + if not ok then + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then + report "TEXTIO.HREAD Error: Vector truncated" + severity error; + else + VALUE := sv (pad to sv'high); + end if; + end procedure HREAD; + + procedure HWRITE (L : inout LINE; + VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin + write (L => L, + VALUE => to_hstring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure HWRITE; + + -- Procedure only visible internally. + procedure Char2TriBits (C : CHARACTER; + RESULT : out BIT_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 others => + assert not ISSUE_ERROR + report + "TEXTIO.OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + GOOD := false; + end case; + end procedure Char2TriBits; + + -- Read and Write procedures for Octal values + procedure OREAD (L : inout LINE; + VALUE : out BIT_VECTOR; + GOOD : out BOOLEAN) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : BIT_VECTOR(0 to ne*3 - 1) := (others => '0'); + variable s : STRING(1 to ne-1); + begin + VALUE := (VALUE'range => '0'); + loop -- skip white space + read(l, c, ok); + exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + GOOD := false; + return; + end if; + Char2TriBits(c, sv(0 to 2), ok, false); + if not ok then + GOOD := false; + return; + end if; + read(L, s, ok); + if not ok then + GOOD := false; + return; + end if; + for i in 1 to ne-1 loop + Char2TriBits(s(i), sv(3*i to 3*i+2), ok, false); + if not ok then + GOOD := false; + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then + GOOD := false; -- vector was truncated. + else + GOOD := true; + VALUE := sv (pad to sv'high); + end if; + end procedure OREAD; + + procedure OREAD (L : inout LINE; + VALUE : out BIT_VECTOR) is + variable c : CHARACTER; + variable ok : BOOLEAN; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : BIT_VECTOR(0 to ne*3 - 1) := (others => '0'); + variable s : STRING(1 to ne-1); + begin + VALUE := (VALUE'range => '0'); + loop -- skip white space + read(l, c, ok); + exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + report "TEXTIO.OREAD Error: Failed skipping white space" + severity error; + return; + end if; + Char2TriBits(c, sv(0 to 2), ok, true); + if not ok then + return; + end if; + read(L, s, ok); + if not ok then + report "TEXTIO.OREAD Error: Failed to read the STRING" + severity error; + return; + end if; + for i in 1 to ne-1 loop + Char2TriBits(s(i), sv(3*i to 3*i+2), ok, true); + if not ok then + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then + report "TEXTIO.OREAD Error: Vector truncated" + severity error; + else + VALUE := sv (pad to sv'high); + end if; + end procedure OREAD; + + procedure OWRITE (L : inout LINE; + VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin + write (L => L, + VALUE => to_ostring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure OWRITE; + + -- read and write for vector versions + -- These versions produce "value1, value2, value3 ...." + procedure read (L : inout LINE; + VALUE : out boolean_vector; + GOOD : out BOOLEAN) is + variable dummy : CHARACTER; + variable igood : BOOLEAN := true; + begin + for i in VALUE'range loop + read (L => L, + VALUE => VALUE(i), + GOOD => igood); + if (igood) and (i /= value'right) then + read (L => L, + VALUE => dummy, -- Toss the comma or seperator + good => igood); + end if; + if (not igood) then + good := false; + return; + end if; + end loop; + good := true; + end procedure read; + + procedure read (L : inout LINE; + VALUE : out boolean_vector) is + variable dummy : CHARACTER; + variable igood : BOOLEAN; + begin + for i in VALUE'range loop + read (L => L, + VALUE => VALUE(i), + good => igood); + if (igood) and (i /= value'right) then + read (L => L, + VALUE => dummy, -- Toss the comma or seperator + good => igood); + end if; + if (not igood) then + report "STANDARD.STD_TEXTIO(BOOLEAN_VECTOR) " + & "Read error ecounted during vector read" severity error; + return; + end if; + end loop; + end procedure read; + + procedure write (L : inout LINE; + VALUE : in boolean_vector; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin + for i in VALUE'range loop + write (L => L, + VALUE => VALUE(i), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + if (i /= value'right) then + swrite (L, ", "); + end if; + end loop; + end procedure write; + + procedure WRITE (L: inout LINE; VALUE: in REAL; + FORMAT: in STRING) is + begin + swrite ( L => L, + VALUE => to_string (VALUE, FORMAT)); + end procedure WRITE; + + 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_string ( + VALUE : SIDE) return STRING is + begin + return SIDE'image(VALUE); + end function to_string; + + -- pragma synthesis_on + -- Will be implicit + function minimum (L, R : SIDE) return SIDE is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + + function maximum (L, R : SIDE) return SIDE is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + +end package body standard_textio_additions; diff --git a/ieee_proposed/rtl/std_logic_1164_additions.vhd b/ieee_proposed/rtl/std_logic_1164_additions.vhd new file mode 100644 index 0000000..0c71490 --- /dev/null +++ b/ieee_proposed/rtl/std_logic_1164_additions.vhd @@ -0,0 +1,1808 @@ +------------------------------------------------------------------------------ +-- "std_logic_1164_additions" package contains the additions to the standard +-- "std_logic_1164" package proposed by the VHDL-200X-ft working group. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee.std_logic_1164.all; +-- use ieee_proposed.std_logic_1164_additions.all; +-- Last Modified: $Date: 2007-09-11 14:52:13-04 $ +-- RCS ID: $Id: std_logic_1164_additions.vhdl,v 1.12 2007-09-11 14:52:13-04 l435385 Exp $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use std.textio.all; +package std_logic_1164_additions is + + -- NOTE that in the new std_logic_1164, STD_LOGIC_VECTOR is a resolved + -- subtype of STD_ULOGIC_VECTOR. Thus there is no need for funcitons which + -- take inputs in STD_LOGIC_VECTOR. + -- For compatability with VHDL-2002, I have replicated all of these funcitons + -- here for STD_LOGIC_VECTOR. + -- new aliases +-- alias to_bv is ieee.std_logic_1164.To_bitvector [STD_LOGIC_VECTOR, BIT return BIT_VECTOR]; +-- alias to_bv is ieee.std_logic_1164.To_bitvector [STD_ULOGIC_VECTOR, BIT return BIT_VECTOR]; +-- alias to_bit_vector is ieee.std_logic_1164.To_bitvector [STD_LOGIC_VECTOR, BIT return BIT_VECTOR]; +-- alias to_bit_vector is ieee.std_logic_1164.To_bitvector [STD_ULOGIC_VECTOR, BIT return BIT_VECTOR]; +-- alias to_slv is ieee.std_logic_1164.To_StdLogicVector [BIT_VECTOR return STD_LOGIC_VECTOR]; +-- alias to_slv is ieee.std_logic_1164.To_StdLogicVector [STD_ULOGIC_VECTOR return STD_LOGIC_VECTOR]; +-- alias to_std_logic_vector is ieee.std_logic_1164.To_StdLogicVector [BIT_VECTOR return STD_LOGIC_VECTOR]; +-- alias to_std_logic_vector is ieee.std_logic_1164.To_StdLogicVector [STD_ULOGIC_VECTOR return STD_LOGIC_VECTOR]; +-- alias to_sulv is ieee.std_logic_1164.To_StdULogicVector [BIT_VECTOR return STD_ULOGIC_VECTOR]; +-- alias to_sulv is ieee.std_logic_1164.To_StdULogicVector [STD_LOGIC_VECTOR return STD_ULOGIC_VECTOR]; +-- alias to_std_ulogic_vector is ieee.std_logic_1164.To_StdULogicVector [BIT_VECTOR return STD_ULOGIC_VECTOR]; +-- alias to_std_ulogic_vector is ieee.std_logic_1164.To_StdULogicVector [STD_LOGIC_VECTOR return STD_ULOGIC_VECTOR]; + + function TO_01 (s : STD_ULOGIC_VECTOR; xmap : STD_ULOGIC := '0') + return STD_ULOGIC_VECTOR; + function TO_01 (s : STD_ULOGIC; xmap : STD_ULOGIC := '0') + return STD_ULOGIC; + function TO_01 (s : BIT_VECTOR; xmap : STD_ULOGIC := '0') + return STD_ULOGIC_VECTOR; + function TO_01 (s : BIT; xmap : STD_ULOGIC := '0') + return STD_ULOGIC; + + ------------------------------------------------------------------- + -- overloaded shift operators + ------------------------------------------------------------------- + + function "sll" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR; + function "sll" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR; + + function "srl" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR; + function "srl" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR; + + function "rol" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR; + function "rol" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR; + + function "ror" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR; + function "ror" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR; + ------------------------------------------------------------------- + -- vector/scalar overloaded logical operators + ------------------------------------------------------------------- + function "and" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR; + function "and" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR; + function "and" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "and" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "nand" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR; + function "nand" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR; + function "nand" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "nand" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "or" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR; + function "or" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR; + function "or" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "or" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "nor" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR; + function "nor" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR; + function "nor" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "nor" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "xor" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR; + function "xor" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR; + function "xor" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "xor" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "xnor" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR; + function "xnor" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR; + function "xnor" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "xnor" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + + ------------------------------------------------------------------- + -- vector-reduction functions. + -- "and" functions default to "1", or defaults to "0" + ------------------------------------------------------------------- + ----------------------------------------------------------------------------- + -- %%% Replace the "_reduce" functions with the ones commented out below. + ----------------------------------------------------------------------------- + -- function "and" ( l : std_logic_vector ) RETURN std_ulogic; + -- function "and" ( l : std_ulogic_vector ) RETURN std_ulogic; + -- function "nand" ( l : std_logic_vector ) RETURN std_ulogic; + -- function "nand" ( l : std_ulogic_vector ) RETURN std_ulogic; + -- function "or" ( l : std_logic_vector ) RETURN std_ulogic; + -- function "or" ( l : std_ulogic_vector ) RETURN std_ulogic; + -- function "nor" ( l : std_logic_vector ) RETURN std_ulogic; + -- function "nor" ( l : std_ulogic_vector ) RETURN std_ulogic; + -- function "xor" ( l : std_logic_vector ) RETURN std_ulogic; + -- function "xor" ( l : std_ulogic_vector ) RETURN std_ulogic; + -- function "xnor" ( l : std_logic_vector ) RETURN std_ulogic; + -- function "xnor" ( l : std_ulogic_vector ) RETURN std_ulogic; + function and_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC; + function and_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC; + function nand_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC; + function nand_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC; + function or_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC; + function or_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC; + function nor_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC; + function nor_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC; + function xor_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC; + function xor_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC; + function xnor_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC; + function xnor_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC; + ------------------------------------------------------------------- + -- ?= operators, same functionality as 1076.3 1994 std_match + ------------------------------------------------------------------- +-- FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic; +-- FUNCTION "?=" ( l, r : std_logic_vector ) RETURN std_ulogic; +-- FUNCTION "?=" ( l, r : std_ulogic_vector ) RETURN std_ulogic; +-- FUNCTION "?/=" ( l, r : std_ulogic ) RETURN std_ulogic; +-- FUNCTION "?/=" ( l, r : std_logic_vector ) RETURN std_ulogic; +-- FUNCTION "?/=" ( l, r : std_ulogic_vector ) RETURN std_ulogic; +-- FUNCTION "?>" ( l, r : std_ulogic ) RETURN std_ulogic; +-- FUNCTION "?>=" ( l, r : std_ulogic ) RETURN std_ulogic; +-- FUNCTION "?<" ( l, r : std_ulogic ) RETURN std_ulogic; +-- FUNCTION "?<=" ( l, r : std_ulogic ) RETURN std_ulogic; + +-- function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC; +-- function \?=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC; +-- function \?=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC; +-- function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC; +-- function \?/=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC; +-- function \?/=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC; + function \?>\ (l, r : STD_ULOGIC) return STD_ULOGIC; + function \?>=\ (l, r : STD_ULOGIC) return STD_ULOGIC; + function \?<\ (l, r : STD_ULOGIC) return STD_ULOGIC; + function \?<=\ (l, r : STD_ULOGIC) return STD_ULOGIC; + + + -- "??" operator, converts a std_ulogic to a boolean. + --%%% Uncomment the following operators + -- FUNCTION "??" (S : STD_ULOGIC) RETURN BOOLEAN; + --%%% REMOVE the following funciton (for testing only) + function \??\ (S : STD_ULOGIC) return BOOLEAN; + + -- rtl_synthesis off +-- pragma synthesis_off + function to_string (value : STD_ULOGIC) return STRING; + function to_string (value : STD_ULOGIC_VECTOR) return STRING; + function to_string (value : STD_LOGIC_VECTOR) return STRING; + + -- explicitly defined operations + + alias TO_BSTRING is TO_STRING [STD_ULOGIC_VECTOR return STRING]; + alias TO_BINARY_STRING is TO_STRING [STD_ULOGIC_VECTOR return STRING]; + function TO_OSTRING (VALUE : STD_ULOGIC_VECTOR) return STRING; + alias TO_OCTAL_STRING is TO_OSTRING [STD_ULOGIC_VECTOR return STRING]; + function TO_HSTRING (VALUE : STD_ULOGIC_VECTOR) return STRING; + alias TO_HEX_STRING is TO_HSTRING [STD_ULOGIC_VECTOR return STRING]; + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC; GOOD : out BOOLEAN); + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC); + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); + + procedure WRITE (L : inout LINE; VALUE : in STD_ULOGIC; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + procedure WRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + alias BREAD is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN]; + alias BREAD is READ [LINE, STD_ULOGIC_VECTOR]; + alias BINARY_READ is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN]; + alias BINARY_READ is READ [LINE, STD_ULOGIC_VECTOR]; + + procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); + procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); + alias OCTAL_READ is OREAD [LINE, STD_ULOGIC_VECTOR, BOOLEAN]; + alias OCTAL_READ is OREAD [LINE, STD_ULOGIC_VECTOR]; + + procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); + procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); + alias HEX_READ is HREAD [LINE, STD_ULOGIC_VECTOR, BOOLEAN]; + alias HEX_READ is HREAD [LINE, STD_ULOGIC_VECTOR]; + + alias BWRITE is WRITE [LINE, STD_ULOGIC_VECTOR, SIDE, WIDTH]; + alias BINARY_WRITE is WRITE [LINE, STD_ULOGIC_VECTOR, SIDE, WIDTH]; + + procedure OWRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + alias OCTAL_WRITE is OWRITE [LINE, STD_ULOGIC_VECTOR, SIDE, WIDTH]; + + procedure HWRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + alias HEX_WRITE is HWRITE [LINE, STD_ULOGIC_VECTOR, SIDE, WIDTH]; + + alias TO_BSTRING is TO_STRING [STD_LOGIC_VECTOR return STRING]; + alias TO_BINARY_STRING is TO_STRING [STD_LOGIC_VECTOR return STRING]; + function TO_OSTRING (VALUE : STD_LOGIC_VECTOR) return STRING; + alias TO_OCTAL_STRING is TO_OSTRING [STD_LOGIC_VECTOR return STRING]; + function TO_HSTRING (VALUE : STD_LOGIC_VECTOR) return STRING; + alias TO_HEX_STRING is TO_HSTRING [STD_LOGIC_VECTOR return STRING]; + + procedure READ (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; GOOD : out BOOLEAN); + procedure READ (L : inout LINE; VALUE : out STD_LOGIC_VECTOR); + + procedure WRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + alias BREAD is READ [LINE, STD_LOGIC_VECTOR, BOOLEAN]; + alias BREAD is READ [LINE, STD_LOGIC_VECTOR]; + alias BINARY_READ is READ [LINE, STD_LOGIC_VECTOR, BOOLEAN]; + alias BINARY_READ is READ [LINE, STD_LOGIC_VECTOR]; + + procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; GOOD : out BOOLEAN); + procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR); + alias OCTAL_READ is OREAD [LINE, STD_LOGIC_VECTOR, BOOLEAN]; + alias OCTAL_READ is OREAD [LINE, STD_LOGIC_VECTOR]; + + procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; GOOD : out BOOLEAN); + procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR); + alias HEX_READ is HREAD [LINE, STD_LOGIC_VECTOR, BOOLEAN]; + alias HEX_READ is HREAD [LINE, STD_LOGIC_VECTOR]; + + alias BWRITE is WRITE [LINE, STD_LOGIC_VECTOR, SIDE, WIDTH]; + alias BINARY_WRITE is WRITE [LINE, STD_LOGIC_VECTOR, SIDE, WIDTH]; + + procedure OWRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + alias OCTAL_WRITE is OWRITE [LINE, STD_LOGIC_VECTOR, SIDE, WIDTH]; + + procedure HWRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + alias HEX_WRITE is HWRITE [LINE, STD_LOGIC_VECTOR, SIDE, WIDTH]; + -- rtl_synthesis on +-- pragma synthesis_on + function maximum (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function maximum (l, r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function maximum (l, r : STD_ULOGIC) return STD_ULOGIC; + function minimum (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function minimum (l, r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function minimum (l, r : STD_ULOGIC) return STD_ULOGIC; +end package std_logic_1164_additions; + +package body std_logic_1164_additions is +-- type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; + ----------------------------------------------------------------------------- + -- New/updated funcitons for VHDL-200X fast track + ----------------------------------------------------------------------------- + -- to_01 + ------------------------------------------------------------------- + function TO_01 (s : STD_ULOGIC_VECTOR; xmap : STD_ULOGIC := '0') + return STD_ULOGIC_VECTOR is + variable RESULT : STD_ULOGIC_VECTOR(s'length-1 downto 0); + variable BAD_ELEMENT : BOOLEAN := false; + alias XS : STD_ULOGIC_VECTOR(s'length-1 downto 0) is s; + begin + for I in RESULT'range loop + case XS(I) is + when '0' | 'L' => RESULT(I) := '0'; + when '1' | 'H' => RESULT(I) := '1'; + when others => BAD_ELEMENT := true; + end case; + end loop; + if BAD_ELEMENT then + for I in RESULT'range loop + RESULT(I) := XMAP; -- standard fixup + end loop; + end if; + return RESULT; + end function TO_01; + ------------------------------------------------------------------- + function TO_01 (s : STD_ULOGIC; xmap : STD_ULOGIC := '0') + return STD_ULOGIC is + begin + case s is + when '0' | 'L' => RETURN '0'; + when '1' | 'H' => RETURN '1'; + when others => return xmap; + end case; + end function TO_01; + ------------------------------------------------------------------- + function TO_01 (s : BIT_VECTOR; xmap : STD_ULOGIC := '0') + return STD_ULOGIC_VECTOR is + variable RESULT : STD_ULOGIC_VECTOR(s'length-1 downto 0); + alias XS : BIT_VECTOR(s'length-1 downto 0) is s; + begin + for I in RESULT'range loop + case XS(I) is + when '0' => RESULT(I) := '0'; + when '1' => RESULT(I) := '1'; + end case; + end loop; + return RESULT; + end function TO_01; + ------------------------------------------------------------------- + function TO_01 (s : BIT; xmap : STD_ULOGIC := '0') + return STD_ULOGIC is + begin + case s is + when '0' => RETURN '0'; + when '1' => RETURN '1'; + end case; + end function TO_01; +-- end Bugzilla issue #148 + ------------------------------------------------------------------- + + ------------------------------------------------------------------- + -- overloaded shift operators + ------------------------------------------------------------------- + + ------------------------------------------------------------------- + -- sll + ------------------------------------------------------------------- + function "sll" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR is + alias lv : STD_LOGIC_VECTOR (1 to l'length) is l; + variable result : STD_LOGIC_VECTOR (1 to l'length) := (others => '0'); + begin + if r >= 0 then + result(1 to l'length - r) := lv(r + 1 to l'length); + else + result := l srl -r; + end if; + return result; + end function "sll"; + ------------------------------------------------------------------- + function "sll" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR is + alias lv : STD_ULOGIC_VECTOR (1 to l'length) is l; + variable result : STD_ULOGIC_VECTOR (1 to l'length) := (others => '0'); + begin + if r >= 0 then + result(1 to l'length - r) := lv(r + 1 to l'length); + else + result := l srl -r; + end if; + return result; + end function "sll"; + + ------------------------------------------------------------------- + -- srl + ------------------------------------------------------------------- + function "srl" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR is + alias lv : STD_LOGIC_VECTOR (1 to l'length) is l; + variable result : STD_LOGIC_VECTOR (1 to l'length) := (others => '0'); + begin + if r >= 0 then + result(r + 1 to l'length) := lv(1 to l'length - r); + else + result := l sll -r; + end if; + return result; + end function "srl"; + ------------------------------------------------------------------- + function "srl" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR is + alias lv : STD_ULOGIC_VECTOR (1 to l'length) is l; + variable result : STD_ULOGIC_VECTOR (1 to l'length) := (others => '0'); + begin + if r >= 0 then + result(r + 1 to l'length) := lv(1 to l'length - r); + else + result := l sll -r; + end if; + return result; + end function "srl"; + + ------------------------------------------------------------------- + -- rol + ------------------------------------------------------------------- + function "rol" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR is + alias lv : STD_LOGIC_VECTOR (1 to l'length) is l; + variable result : STD_LOGIC_VECTOR (1 to l'length); + constant rm : INTEGER := r mod l'length; + begin + if r >= 0 then + result(1 to l'length - rm) := lv(rm + 1 to l'length); + result(l'length - rm + 1 to l'length) := lv(1 to rm); + else + result := l ror -r; + end if; + return result; + end function "rol"; + ------------------------------------------------------------------- + function "rol" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR is + alias lv : STD_ULOGIC_VECTOR (1 to l'length) is l; + variable result : STD_ULOGIC_VECTOR (1 to l'length); + constant rm : INTEGER := r mod l'length; + begin + if r >= 0 then + result(1 to l'length - rm) := lv(rm + 1 to l'length); + result(l'length - rm + 1 to l'length) := lv(1 to rm); + else + result := l ror -r; + end if; + return result; + end function "rol"; + + ------------------------------------------------------------------- + -- ror + ------------------------------------------------------------------- + function "ror" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR is + alias lv : STD_LOGIC_VECTOR (1 to l'length) is l; + variable result : STD_LOGIC_VECTOR (1 to l'length) := (others => '0'); + constant rm : INTEGER := r mod l'length; + begin + if r >= 0 then + result(rm + 1 to l'length) := lv(1 to l'length - rm); + result(1 to rm) := lv(l'length - rm + 1 to l'length); + else + result := l rol -r; + end if; + return result; + end function "ror"; + ------------------------------------------------------------------- + function "ror" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR is + alias lv : STD_ULOGIC_VECTOR (1 to l'length) is l; + variable result : STD_ULOGIC_VECTOR (1 to l'length) := (others => '0'); + constant rm : INTEGER := r mod l'length; + begin + if r >= 0 then + result(rm + 1 to l'length) := lv(1 to l'length - rm); + result(1 to rm) := lv(l'length - rm + 1 to l'length); + else + result := l rol -r; + end if; + return result; + end function "ror"; + ------------------------------------------------------------------- + -- vector/scalar overloaded logical operators + ------------------------------------------------------------------- + + ------------------------------------------------------------------- + -- and + ------------------------------------------------------------------- + function "and" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is + alias lv : STD_LOGIC_VECTOR (1 to l'length) is l; + variable result : STD_LOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "and" (lv(i), r); + end loop; + return result; + end function "and"; + ------------------------------------------------------------------- + function "and" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is + alias lv : STD_ULOGIC_VECTOR (1 to l'length) is l; + variable result : STD_ULOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "and" (lv(i), r); + end loop; + return result; + end function "and"; + ------------------------------------------------------------------- + function "and" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + alias rv : STD_LOGIC_VECTOR (1 to r'length) is r; + variable result : STD_LOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "and" (l, rv(i)); + end loop; + return result; + end function "and"; + ------------------------------------------------------------------- + function "and" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + alias rv : STD_ULOGIC_VECTOR (1 to r'length) is r; + variable result : STD_ULOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "and" (l, rv(i)); + end loop; + return result; + end function "and"; + + ------------------------------------------------------------------- + -- nand + ------------------------------------------------------------------- + function "nand" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is + alias lv : STD_LOGIC_VECTOR (1 to l'length) is l; + variable result : STD_LOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "not"("and" (lv(i), r)); + end loop; + return result; + end function "nand"; + ------------------------------------------------------------------- + function "nand" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is + alias lv : STD_ULOGIC_VECTOR (1 to l'length) is l; + variable result : STD_ULOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "not"("and" (lv(i), r)); + end loop; + return result; + end function "nand"; + ------------------------------------------------------------------- + function "nand" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + alias rv : STD_LOGIC_VECTOR (1 to r'length) is r; + variable result : STD_LOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "not"("and" (l, rv(i))); + end loop; + return result; + end function "nand"; + ------------------------------------------------------------------- + function "nand" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + alias rv : STD_ULOGIC_VECTOR (1 to r'length) is r; + variable result : STD_ULOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "not"("and" (l, rv(i))); + end loop; + return result; + end function "nand"; + + ------------------------------------------------------------------- + -- or + ------------------------------------------------------------------- + function "or" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is + alias lv : STD_LOGIC_VECTOR (1 to l'length) is l; + variable result : STD_LOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "or" (lv(i), r); + end loop; + return result; + end function "or"; + ------------------------------------------------------------------- + function "or" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is + alias lv : STD_ULOGIC_VECTOR (1 to l'length) is l; + variable result : STD_ULOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "or" (lv(i), r); + end loop; + return result; + end function "or"; + ------------------------------------------------------------------- + function "or" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + alias rv : STD_LOGIC_VECTOR (1 to r'length) is r; + variable result : STD_LOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "or" (l, rv(i)); + end loop; + return result; + end function "or"; + ------------------------------------------------------------------- + function "or" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + alias rv : STD_ULOGIC_VECTOR (1 to r'length) is r; + variable result : STD_ULOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "or" (l, rv(i)); + end loop; + return result; + end function "or"; + + ------------------------------------------------------------------- + -- nor + ------------------------------------------------------------------- + function "nor" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is + alias lv : STD_LOGIC_VECTOR (1 to l'length) is l; + variable result : STD_LOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "not"("or" (lv(i), r)); + end loop; + return result; + end function "nor"; + ------------------------------------------------------------------- + function "nor" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is + alias lv : STD_ULOGIC_VECTOR (1 to l'length) is l; + variable result : STD_ULOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "not"("or" (lv(i), r)); + end loop; + return result; + end function "nor"; + ------------------------------------------------------------------- + function "nor" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + alias rv : STD_LOGIC_VECTOR (1 to r'length) is r; + variable result : STD_LOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "not"("or" (l, rv(i))); + end loop; + return result; + end function "nor"; + ------------------------------------------------------------------- + function "nor" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + alias rv : STD_ULOGIC_VECTOR (1 to r'length) is r; + variable result : STD_ULOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "not"("or" (l, rv(i))); + end loop; + return result; + end function "nor"; + + ------------------------------------------------------------------- + -- xor + ------------------------------------------------------------------- + function "xor" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is + alias lv : STD_LOGIC_VECTOR (1 to l'length) is l; + variable result : STD_LOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "xor" (lv(i), r); + end loop; + return result; + end function "xor"; + ------------------------------------------------------------------- + function "xor" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is + alias lv : STD_ULOGIC_VECTOR (1 to l'length) is l; + variable result : STD_ULOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "xor" (lv(i), r); + end loop; + return result; + end function "xor"; + ------------------------------------------------------------------- + function "xor" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + alias rv : STD_LOGIC_VECTOR (1 to r'length) is r; + variable result : STD_LOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "xor" (l, rv(i)); + end loop; + return result; + end function "xor"; + ------------------------------------------------------------------- + function "xor" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + alias rv : STD_ULOGIC_VECTOR (1 to r'length) is r; + variable result : STD_ULOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "xor" (l, rv(i)); + end loop; + return result; + end function "xor"; + + ------------------------------------------------------------------- + -- xnor + ------------------------------------------------------------------- + function "xnor" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is + alias lv : STD_LOGIC_VECTOR (1 to l'length) is l; + variable result : STD_LOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "not"("xor" (lv(i), r)); + end loop; + return result; + end function "xnor"; + ------------------------------------------------------------------- + function "xnor" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is + alias lv : STD_ULOGIC_VECTOR (1 to l'length) is l; + variable result : STD_ULOGIC_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := "not"("xor" (lv(i), r)); + end loop; + return result; + end function "xnor"; + ------------------------------------------------------------------- + function "xnor" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + alias rv : STD_LOGIC_VECTOR (1 to r'length) is r; + variable result : STD_LOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "not"("xor" (l, rv(i))); + end loop; + return result; + end function "xnor"; + ------------------------------------------------------------------- + function "xnor" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + alias rv : STD_ULOGIC_VECTOR (1 to r'length) is r; + variable result : STD_ULOGIC_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := "not"("xor" (l, rv(i))); + end loop; + return result; + end function "xnor"; + + ------------------------------------------------------------------- + -- vector-reduction functions + ------------------------------------------------------------------- + + ------------------------------------------------------------------- + -- and + ------------------------------------------------------------------- + function and_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return and_reduce (to_StdULogicVector (l)); + end function and_reduce; + ------------------------------------------------------------------- + function and_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is + variable result : STD_ULOGIC := '1'; + begin + for i in l'reverse_range loop + result := (l(i) and result); + end loop; + return result; + end function and_reduce; + + ------------------------------------------------------------------- + -- nand + ------------------------------------------------------------------- + function nand_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return not (and_reduce(to_StdULogicVector(l))); + end function nand_reduce; + ------------------------------------------------------------------- + function nand_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return not (and_reduce(l)); + end function nand_reduce; + + ------------------------------------------------------------------- + -- or + ------------------------------------------------------------------- + function or_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return or_reduce (to_StdULogicVector (l)); + end function or_reduce; + ------------------------------------------------------------------- + function or_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is + variable result : STD_ULOGIC := '0'; + begin + for i in l'reverse_range loop + result := (l(i) or result); + end loop; + return result; + end function or_reduce; + + ------------------------------------------------------------------- + -- nor + ------------------------------------------------------------------- + function nor_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return "not"(or_reduce(To_StdULogicVector(l))); + end function nor_reduce; + ------------------------------------------------------------------- + function nor_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return "not"(or_reduce(l)); + end function nor_reduce; + + ------------------------------------------------------------------- + -- xor + ------------------------------------------------------------------- + function xor_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return xor_reduce (to_StdULogicVector (l)); + end function xor_reduce; + ------------------------------------------------------------------- + function xor_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is + variable result : STD_ULOGIC := '0'; + begin + for i in l'reverse_range loop + result := (l(i) xor result); + end loop; + return result; + end function xor_reduce; + + ------------------------------------------------------------------- + -- xnor + ------------------------------------------------------------------- + function xnor_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return "not"(xor_reduce(To_StdULogicVector(l))); + end function xnor_reduce; + ------------------------------------------------------------------- + function xnor_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return "not"(xor_reduce(l)); + end function xnor_reduce; + -- %%% End "remove the following functions" + + + -- The following functions are implicity in 1076-2006 + -- truth table for "?=" function +-- 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_logic_vector ) RETURN std_ulogic IS +-- function \?=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC is +-- alias lv : STD_LOGIC_VECTOR(1 to l'length) is l; +-- alias rv : STD_LOGIC_VECTOR(1 to r'length) is r; +-- variable result, result1 : STD_ULOGIC; -- result +-- begin +-- -- Logically identical to an "=" operator. +-- if ((l'length < 1) or (r'length < 1)) then +-- report "STD_LOGIC_1164.""?="": null detected, returning X" +-- severity warning; +-- return 'X'; +-- end if; +-- if lv'length /= rv'length then +-- report "STD_LOGIC_1164.""?="": L'LENGTH /= R'LENGTH, returning X" +-- severity warning; +-- return 'X'; +-- else +-- result := '1'; +-- for i in lv'low to lv'high loop +-- result1 := match_logic_table(lv(i), rv(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 : std_ulogic_vector ) RETURN std_ulogic IS +-- function \?=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is +-- alias lv : STD_ULOGIC_VECTOR(1 to l'length) is l; +-- alias rv : STD_ULOGIC_VECTOR(1 to r'length) is r; +-- variable result, result1 : STD_ULOGIC; +-- begin +-- if ((l'length < 1) or (r'length < 1)) then +-- report "STD_LOGIC_1164.""?="": null detected, returning X" +-- severity warning; +-- return 'X'; +-- end if; +-- if lv'length /= rv'length then +-- report "STD_LOGIC_1164.""?="": L'LENGTH /= R'LENGTH, returning X" +-- severity warning; +-- return 'X'; +-- else +-- result := '1'; +-- for i in lv'low to lv'high loop +-- result1 := match_logic_table(lv(i), rv(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 : std_ulogic ) RETURN std_ulogic is +-- function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is +-- begin +-- return no_match_logic_table (l, r); +-- end function \?/=\; +-- -- %%% END FUNCTION "?/="; +-- -- %%% FUNCTION "?/=" ( l, r : std_logic_vector ) RETURN std_ulogic is +-- function \?/=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC is +-- alias lv : STD_LOGIC_VECTOR(1 to l'length) is l; +-- alias rv : STD_LOGIC_VECTOR(1 to r'length) is r; +-- variable result, result1 : STD_ULOGIC; -- result +-- begin +-- if ((l'length < 1) or (r'length < 1)) then +-- report "STD_LOGIC_1164.""?/="": null detected, returning X" +-- severity warning; +-- return 'X'; +-- end if; +-- if lv'length /= rv'length then +-- report "STD_LOGIC_1164.""?/="": L'LENGTH /= R'LENGTH, returning X" +-- severity warning; +-- return 'X'; +-- else +-- result := '0'; +-- for i in lv'low to lv'high loop +-- result1 := no_match_logic_table(lv(i), rv(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 : std_ulogic_vector ) RETURN std_ulogic is +-- function \?/=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is +-- alias lv : STD_ULOGIC_VECTOR(1 to l'length) is l; +-- alias rv : STD_ULOGIC_VECTOR(1 to r'length) is r; +-- variable result, result1 : STD_ULOGIC; +-- begin +-- if ((l'length < 1) or (r'length < 1)) then +-- report "STD_LOGIC_1164.""?/="": null detected, returning X" +-- severity warning; +-- return 'X'; +-- end if; +-- if lv'length /= rv'length then +-- report "STD_LOGIC_1164.""?/="": L'LENGTH /= R'LENGTH, returning X" +-- severity warning; +-- return 'X'; +-- else +-- result := '0'; +-- for i in lv'low to lv'high loop +-- result1 := no_match_logic_table(lv(i), rv(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 : std_ulogic ) RETURN std_ulogic is + function \?>\ (l, r : STD_ULOGIC) return STD_ULOGIC is + variable lx, rx : STD_ULOGIC; + begin + if (l = '-') or (r = '-') then + report "STD_LOGIC_1164.""?>"": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01 (l); + rx := to_x01 (r); + if lx = 'X' or rx = 'X' then + return 'X'; + elsif lx > rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + -- %%% END FUNCTION "?>"; + + -- %%% FUNCTION "?>=" ( l, r : std_ulogic ) RETURN std_ulogic is + function \?>=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + variable lx, rx : STD_ULOGIC; + begin + if (l = '-') or (r = '-') then + report "STD_LOGIC_1164.""?>="": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01 (l); + rx := to_x01 (r); + if lx = 'X' or rx = 'X' then + return 'X'; + elsif lx >= rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + -- %%% END FUNCTION "?/>="; + + -- %%% FUNCTION "?<" ( l, r : std_ulogic ) RETURN std_ulogic is + function \?<\ (l, r : STD_ULOGIC) return STD_ULOGIC is + variable lx, rx : STD_ULOGIC; + begin + if (l = '-') or (r = '-') then + report "STD_LOGIC_1164.""?<"": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01 (l); + rx := to_x01 (r); + if lx = 'X' or rx = 'X' then + return 'X'; + elsif lx < rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + -- %%% END FUNCTION "?/<"; + + -- %%% FUNCTION "?<=" ( l, r : std_ulogic ) RETURN std_ulogic is + function \?<=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + variable lx, rx : STD_ULOGIC; + begin + if (l = '-') or (r = '-') then + report "STD_LOGIC_1164.""?<="": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01 (l); + rx := to_x01 (r); + if lx = 'X' or rx = 'X' then + return 'X'; + elsif lx <= rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + -- %%% END FUNCTION "?/<="; + + -- "??" operator, converts a std_ulogic to a boolean. +-- %%% FUNCTION "??" + function \??\ (S : STD_ULOGIC) return BOOLEAN is + begin + return S = '1' or S = 'H'; + end function \??\; +-- %%% END FUNCTION "??"; + + -- rtl_synthesis off +-- pragma synthesis_off + ----------------------------------------------------------------------------- + -- This section copied from "std_logic_textio" + ----------------------------------------------------------------------------- + -- Type and constant definitions used to map STD_ULOGIC values + -- into/from character values. + 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 => ' '); -- null STRING + + -- purpose: Skips white space + procedure skip_whitespace ( + L : inout LINE) is + variable readOk : BOOLEAN; + variable c : CHARACTER; + begin + while L /= null and L.all'length /= 0 loop + if (L.all(1) = ' ' or L.all(1) = NBSP or L.all(1) = HT) then + read (l, c, readOk); + else + exit; + end if; + end loop; + end procedure skip_whitespace; + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC; + GOOD : out BOOLEAN) is + variable c : CHARACTER; + variable readOk : BOOLEAN; + begin + VALUE := 'U'; -- initialize to a "U" + Skip_whitespace (L); + read (l, c, readOk); + if not readOk then + good := false; + else + if char_to_MVL9plus(c) = error then + good := false; + else + VALUE := char_to_MVL9(c); + good := true; + end if; + end if; + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable m : STD_ULOGIC; + variable c : CHARACTER; + variable mv : STD_ULOGIC_VECTOR(0 to VALUE'length-1); + variable readOk : BOOLEAN; + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, readOk); + i := 0; + good := false; + while i < VALUE'length loop + if not readOk then -- Bail out if there was a bad read + return; + elsif c = '_' then + if i = 0 then -- Begins with an "_" + return; + elsif lastu then -- "__" detected + return; + else + lastu := true; + end if; + elsif (char_to_MVL9plus(c) = error) then -- Illegal character + return; + else + mv(i) := char_to_MVL9(c); + i := i + 1; + if i > mv'high then -- reading done + good := true; + VALUE := mv; + return; + end if; + lastu := false; + end if; + read(L, c, readOk); + end loop; + else + good := true; -- read into a null array + end if; + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC) is + variable c : CHARACTER; + variable readOk : BOOLEAN; + begin + VALUE := 'U'; -- initialize to a "U" + Skip_whitespace (L); + read (l, c, readOk); + if not readOk then + report "STD_LOGIC_1164.READ(STD_ULOGIC) " + & "End of string encountered" + severity error; + return; + elsif char_to_MVL9plus(c) = error then + report + "STD_LOGIC_1164.READ(STD_ULOGIC) Error: Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + else + VALUE := char_to_MVL9(c); + end if; + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is + variable m : STD_ULOGIC; + variable c : CHARACTER; + variable readOk : BOOLEAN; + variable mv : STD_ULOGIC_VECTOR(0 to VALUE'length-1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then -- non Null input string + read (l, c, readOk); + i := 0; + while i < VALUE'length loop + if readOk = false then -- Bail out if there was a bad read + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "End of string encountered" + severity error; + return; + elsif c = '_' then + if i = 0 then + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "String begins with an ""_""" severity error; + return; + elsif lastu then + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "Two underscores detected in input string ""__""" + severity error; + return; + else + lastu := true; + end if; + elsif c = ' ' or c = NBSP or c = HT then -- reading done. + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "Short read, Space encounted in input string" + severity error; + return; + elsif char_to_MVL9plus(c) = error then + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "Error: Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + return; + else + mv(i) := char_to_MVL9(c); + i := i + 1; + if i > mv'high then + VALUE := mv; + return; + end if; + lastu := false; + end if; + read(L, c, readOk); + end loop; + end if; + end procedure READ; + + procedure WRITE (L : inout LINE; VALUE : in STD_ULOGIC; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + begin + write(l, MVL9_to_char(VALUE), justified, field); + end procedure WRITE; + + procedure WRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + variable s : STRING(1 to VALUE'length); + variable m : STD_ULOGIC_VECTOR(1 to VALUE'length) := VALUE; + begin + for i in 1 to VALUE'length loop + s(i) := MVL9_to_char(m(i)); + end loop; + write(l, s, justified, field); + end procedure WRITE; + + -- Read and Write procedures for STD_LOGIC_VECTOR + + procedure READ (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ivalue : STD_ULOGIC_VECTOR (VALUE'range); + begin + READ (L => L, VALUE => ivalue, GOOD => GOOD); + VALUE := to_stdlogicvector (ivalue); + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out STD_LOGIC_VECTOR) is + variable ivalue : STD_ULOGIC_VECTOR (VALUE'range); + begin + READ (L => L, VALUE => ivalue); + VALUE := to_stdlogicvector (ivalue); + end procedure READ; + + procedure WRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + variable s : STRING(1 to VALUE'length); + variable m : STD_LOGIC_VECTOR(1 to VALUE'length) := VALUE; + begin + for i in 1 to VALUE'length loop + s(i) := MVL9_to_char(m(i)); + end loop; + write(L, s, justified, field); + end procedure WRITE; + + ----------------------------------------------------------------------- + -- Alias for bread and bwrite are provided with call out the read and + -- write functions. + ----------------------------------------------------------------------- + + -- Hex Read and Write procedures for STD_ULOGIC_VECTOR. + -- Modified from the original to be more forgiving. + + procedure Char2QuadBits (C : CHARACTER; + RESULT : out STD_ULOGIC_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 + "STD_LOGIC_1164.HREAD Read a '" & c & + "', expected a Hex character (0-F)." + severity error; + good := false; + end case; + end procedure Char2QuadBits; + + procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : STD_ULOGIC_VECTOR(0 to ne*4 - 1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, ok); + i := 0; + while i < ne loop + -- Bail out if there was a bad read + if not ok then + good := false; + return; + elsif c = '_' then + if i = 0 then + good := false; -- Begins with an "_" + return; + elsif lastu then + good := false; -- "__" detected + return; + else + lastu := true; + end if; + else + Char2QuadBits(c, sv(4*i to 4*i+3), ok, false); + if not ok then + good := false; + return; + end if; + i := i + 1; + lastu := false; + end if; + if i < ne then + read(L, c, ok); + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + good := true; + VALUE := sv (pad to sv'high); + end if; + else + good := true; -- Null input string, skips whitespace + end if; + end procedure HREAD; + + procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : STD_ULOGIC_VECTOR(0 to ne*4 - 1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then -- non Null input string + read (l, c, ok); + i := 0; + while i < ne loop + -- Bail out if there was a bad read + if not ok then + report "STD_LOGIC_1164.HREAD " + & "End of string encountered" + severity error; + return; + end if; + if c = '_' then + if i = 0 then + report "STD_LOGIC_1164.HREAD " + & "String begins with an ""_""" severity error; + return; + elsif lastu then + report "STD_LOGIC_1164.HREAD " + & "Two underscores detected in input string ""__""" + severity error; + return; + else + lastu := true; + end if; + else + Char2QuadBits(c, sv(4*i to 4*i+3), ok, true); + if not ok then + return; + end if; + i := i + 1; + lastu := false; + end if; + if i < ne then + read(L, c, ok); + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + report "STD_LOGIC_1164.HREAD Vector truncated" + severity error; + else + VALUE := sv (pad to sv'high); + end if; + end if; + end procedure HREAD; + + procedure HWRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + begin + write (L, to_hstring (VALUE), JUSTIFIED, FIELD); + end procedure HWRITE; + + + -- Octal Read and Write procedures for STD_ULOGIC_VECTOR. + -- Modified from the original to be more forgiving. + + procedure Char2TriBits (C : CHARACTER; + RESULT : out STD_ULOGIC_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 + "STD_LOGIC_1164.OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + good := false; + end case; + end procedure Char2TriBits; + + procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : STD_ULOGIC_VECTOR(0 to ne*3 - 1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, ok); + i := 0; + while i < ne loop + -- Bail out if there was a bad read + if not ok then + good := false; + return; + elsif c = '_' then + if i = 0 then + good := false; -- Begins with an "_" + return; + elsif lastu then + good := false; -- "__" detected + return; + else + lastu := true; + end if; + else + Char2TriBits(c, sv(3*i to 3*i+2), ok, false); + if not ok then + good := false; + return; + end if; + i := i + 1; + lastu := false; + end if; + if i < ne then + read(L, c, ok); + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + good := true; + VALUE := sv (pad to sv'high); + end if; + else + good := true; -- read into a null array + end if; + end procedure OREAD; + + procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is + variable c : CHARACTER; + variable ok : BOOLEAN; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : STD_ULOGIC_VECTOR(0 to ne*3 - 1); + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + begin + VALUE := (VALUE'range => 'U'); -- initialize to a "U" + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, ok); + i := 0; + while i < ne loop + -- Bail out if there was a bad read + if not ok then + report "STD_LOGIC_1164.OREAD " + & "End of string encountered" + severity error; + return; + elsif c = '_' then + if i = 0 then + report "STD_LOGIC_1164.OREAD " + & "String begins with an ""_""" severity error; + return; + elsif lastu then + report "STD_LOGIC_1164.OREAD " + & "Two underscores detected in input string ""__""" + severity error; + return; + else + lastu := true; + end if; + else + Char2TriBits(c, sv(3*i to 3*i+2), ok, true); + if not ok then + return; + end if; + i := i + 1; + lastu := false; + end if; + if i < ne then + read(L, c, ok); + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + report "STD_LOGIC_1164.OREAD Vector truncated" + severity error; + else + VALUE := sv (pad to sv'high); + end if; + end if; + end procedure OREAD; + + procedure OWRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + begin + write (L, to_ostring(VALUE), JUSTIFIED, FIELD); + end procedure OWRITE; + + -- Hex Read and Write procedures for STD_LOGIC_VECTOR + + procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ivalue : STD_ULOGIC_VECTOR (VALUE'range); + begin + HREAD (L => L, VALUE => ivalue, GOOD => GOOD); + VALUE := to_stdlogicvector (ivalue); + end procedure HREAD; + + procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR) is + variable ivalue : STD_ULOGIC_VECTOR (VALUE'range); + begin + HREAD (L => L, VALUE => ivalue); + VALUE := to_stdlogicvector (ivalue); + end procedure HREAD; + + procedure HWRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + begin + write (L, to_hstring(VALUE), JUSTIFIED, FIELD); + end procedure HWRITE; + + -- Octal Read and Write procedures for STD_LOGIC_VECTOR + + procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ivalue : STD_ULOGIC_VECTOR (VALUE'range); + begin + OREAD (L => L, VALUE => ivalue, GOOD => GOOD); + VALUE := to_stdlogicvector (ivalue); + end procedure OREAD; + + procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR) is + variable ivalue : STD_ULOGIC_VECTOR (VALUE'range); + begin + OREAD (L => L, VALUE => ivalue); + VALUE := to_stdlogicvector (ivalue); + end procedure OREAD; + + procedure OWRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0) is + begin + write (L, to_ostring(VALUE), JUSTIFIED, FIELD); + end procedure OWRITE; + + ----------------------------------------------------------------------------- + -- New string functions for vhdl-200x fast track + ----------------------------------------------------------------------------- + function to_string (value : STD_ULOGIC) return STRING is + variable result : STRING (1 to 1); + begin + result (1) := MVL9_to_char (value); + return result; + end function to_string; + ------------------------------------------------------------------- + -- TO_STRING (an alias called "to_bstring" is provide) + ------------------------------------------------------------------- + function to_string (value : STD_ULOGIC_VECTOR) return STRING is + alias ivalue : STD_ULOGIC_VECTOR(1 to value'length) is value; + variable result : STRING(1 to value'length); + begin + if value'length < 1 then + return NUS; + else + for i in ivalue'range loop + result(i) := MVL9_to_char(iValue(i)); + end loop; + return result; + end if; + end function to_string; + + ------------------------------------------------------------------- + -- TO_HSTRING + ------------------------------------------------------------------- + function to_hstring (value : STD_ULOGIC_VECTOR) return STRING is + constant ne : INTEGER := (value'length+3)/4; + variable pad : STD_ULOGIC_VECTOR(0 to (ne*4 - value'length) - 1); + variable ivalue : STD_ULOGIC_VECTOR(0 to ne*4 - 1); + variable result : STRING(1 to ne); + variable quad : STD_ULOGIC_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 result; + end if; + end function to_hstring; + + ------------------------------------------------------------------- + -- TO_OSTRING + ------------------------------------------------------------------- + function to_ostring (value : STD_ULOGIC_VECTOR) return STRING is + constant ne : INTEGER := (value'length+2)/3; + variable pad : STD_ULOGIC_VECTOR(0 to (ne*3 - value'length) - 1); + variable ivalue : STD_ULOGIC_VECTOR(0 to ne*3 - 1); + variable result : STRING(1 to ne); + variable tri : STD_ULOGIC_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 result; + end if; + end function to_ostring; + + function to_string (value : STD_LOGIC_VECTOR) return STRING is + begin + return to_string (to_stdulogicvector (value)); + end function to_string; + + function to_hstring (value : STD_LOGIC_VECTOR) return STRING is + begin + return to_hstring (to_stdulogicvector (value)); + end function to_hstring; + + function to_ostring (value : STD_LOGIC_VECTOR) return STRING is + begin + return to_ostring (to_stdulogicvector (value)); + end function to_ostring; + + -- rtl_synthesis on +-- pragma synthesis_on + function maximum (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin -- function maximum + if L > R then return L; + else return R; + end if; + end function maximum; + + -- std_logic_vector output + function minimum (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin -- function minimum + if L > R then return R; + else return L; + end if; + end function minimum; + + function maximum (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin -- function maximum + if L > R then return L; + else return R; + end if; + end function maximum; + + -- std_logic_vector output + function minimum (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin -- function minimum + if L > R then return R; + else return L; + end if; + end function minimum; + + function maximum (L, R : STD_ULOGIC) return STD_ULOGIC is + begin -- function maximum + if L > R then return L; + else return R; + end if; + end function maximum; + + -- std_logic_vector output + function minimum (L, R : STD_ULOGIC) return STD_ULOGIC is + begin -- function minimum + if L > R then return R; + else return L; + end if; + end function minimum; +end package body std_logic_1164_additions; diff --git a/ieee_proposed/simulation/modelsim.ini b/ieee_proposed/simulation/modelsim.ini new file mode 100644 index 0000000..e1ef935 --- /dev/null +++ b/ieee_proposed/simulation/modelsim.ini @@ -0,0 +1,3 @@ +[Library] +others = $MODEL_TECH/../modelsim.ini +ieee_proposed = ./work -- cgit v1.1