diff --git a/dependencies.yml b/dependencies.yml index 898be38844a7f94f8f252cb83700bdfa0a5b07b7..f82c96b4991025568ba949726310fc850fcf82b2 100644 --- a/dependencies.yml +++ b/dependencies.yml @@ -31,10 +31,6 @@ sources: tclink: commit: fda0bcf url: https://gitlab.cern.ch/HPTD/tclink.git - - l1tf: - branch: tschuh - url: https://gitlab.cern.ch/cms-uk-tracktrigger/firmware/l1tf.git gbt-sc: tag: gbt_sc_4_1 @@ -43,6 +39,10 @@ sources: dtc: branch: master url: https://gitlab.cern.ch/cms-tracker-phase2-data-processing/BE_firmware/dtc.git + + dtc-stub-processing: + branch: master + url: https://gitlab.cern.ch/cms-tracker-phase2-data-processing/BE_firmware/dtc-stub-processing.git verilog-ethernet: tag: v1.0.0 diff --git a/top/firmware/cfg/settings.tcl b/top/firmware/cfg/settings.tcl new file mode 100644 index 0000000000000000000000000000000000000000..934542a3923b8b4b7e0edb3b8d648ccf7c5f31f1 --- /dev/null +++ b/top/firmware/cfg/settings.tcl @@ -0,0 +1 @@ +set_property library ieee [get_files fixed_pkg_2008.vhd] diff --git a/top/firmware/cfg/top.dep b/top/firmware/cfg/top.dep index 5d2c73409d80b9c1ae20042465e4a6038e6f3dc2..8879349e9c9571ac9d12ed2278121185444f8dfe 100644 --- a/top/firmware/cfg/top.dep +++ b/top/firmware/cfg/top.dep @@ -1,4 +1,21 @@ -include -c dtc:top/common top.dep +setup -f --cd ../cfg settings.tcl + +include -c histogram:top histogram.dep +include -c dtc:dtc-fe/2S/5G-FEC12 module.dep +include -c dtc:dtc-fe/2S/5G-FEC12 framer.dep +include -c dtc-stub-processing:common tools.dep + +src -c emp-fwk:components/payload ../ucf/emp_simple_payload.tcl +src -c ipbus-firmware:components/ipbus_slaves ipbus_dpram.vhd +src -c ipbus-firmware:components/ipbus_slaves ipbus_reg_v.vhd +src -c ipbus-firmware:components/ipbus_slaves ipbus_ctrlreg_v.vhd +src -c ipbus-firmware:components/ipbus_slaves ipbus_reg_types.vhd +src -c ipbus-firmware:components/ipbus_core ipbus_dc_node.vhd +src -c ipbus-firmware:components/ipbus_core ipbus_dc_fabric_sel.vhd +include -c emp-fwk:boards/serenity/dc_ku15p dc_ku15p_sm1_v1.dep +include -c emp-fwk:components/links/fe_mgt/interface interface_gbt.dep +include -c emp-fwk:components/links/fe_mgt/interface interface_lpgbt.dep + include -c 10gb-ethernet:eth10g emp_eth10g.dep src emp_project_decl.vhd @@ -6,6 +23,7 @@ src emp_payload.vhd src link_maps.vhd src ipbus_decode_emp_payload.vhd src LinkAggregator.vhd +src fixed_pkg_2008.vhd src --vhdl2008 TrackReconstructor.vhd src LinkCombiner.vhd diff --git a/top/firmware/hdl/fixed_pkg_2008.vhd b/top/firmware/hdl/fixed_pkg_2008.vhd new file mode 100755 index 0000000000000000000000000000000000000000..fd63956797447d082caca9eac33e64e69b07771f --- /dev/null +++ b/top/firmware/hdl/fixed_pkg_2008.vhd @@ -0,0 +1,7779 @@ +------------------------------------------------------------------------------ +-- "fixed_pkg" package contains functions for fixed point math. +-- Please see the documentation for the fixed point package. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee.std_logic_1164.all; +-- use ieee.numeric_std.all; +-- use ieee_proposed.fixed_pkg.all; +-- Last Modified: $Date: 2006/05/09 19:21:24 $ +-- RCS ID: $Id: fixed_pkg_c.vhd,v 1.1 2006/05/09 19:21:24 sandeepd Exp $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +-- +-- +-- +-- This file has some changes to allow to be able to use fixed-point in +-- conjunction with VHDL2008 +------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +-- synthesis translate_off +use std.textio.all; +-- synthesis translate_on + +package fixed_pkg is + --%%% Uncomment the Generics +-- new work.fixed_generic_pkg +-- generic map ( +-- fixed_round_style => true; -- fixed_round +-- fixed_overflow_style => true; -- fixed_saturate +-- fixed_guard_bits => 3; -- number of guard bits +-- no_warning => false -- show warnings +-- ); + --%%% REMOVE THE REST OF THIS FILE. + constant fixed_round_style : BOOLEAN := true; -- round + constant fixed_overflow_style : BOOLEAN := true; -- saturate + constant fixed_guard_bits : NATURAL := 3; -- number of guard bits + constant no_warning : BOOLEAN := false; -- issue warnings + -- Author David Bishop (dbishop@vhdl.org) + -- These 5 constants are used as defaults. + -- There is a mechanism to override them in every function + constant fixed_round : BOOLEAN := true; -- Turn on rounding routine + constant fixed_truncate : BOOLEAN := false; -- Trun off rounding routine + constant fixed_saturate : BOOLEAN := true; -- Saturate large numbers + constant fixed_wrap : BOOLEAN := false; -- Wrap large numbers + constant fixedsynth_or_real : BOOLEAN; -- differed constant + -- base Unsigned fixed point type, downto direction assumed + type ufixed is array (INTEGER range <>) of STD_LOGIC; + -- base Signed fixed point type, downto direction assumed + type sfixed is array (INTEGER range <>) of STD_LOGIC; + ----------------------------------------------------------------------------- + -- Fixed point type is defined as follows: + -- 0000000000 + -- 4321012345 + -- 4 0 -5 + -- The decimal point is assumed between the "0" and "-1" index + -- Thus "0011010000" = 6.5 and would be written as 00110.10000 + -- All types are assumed to be in the "downto" direction. + + --=========================================================================== + -- Arithmetic Operators: + --=========================================================================== + -- Modify the sign of the number, 2's complement + function "abs" (arg : sfixed) return sfixed; + function "-" (arg : sfixed)return sfixed; + + -- Convert a signed fixed to an unsigned fixed + function "abs" (arg : sfixed) return ufixed; + + -- Addition + -- ufixed(a downto b) + ufixed(c downto d) + -- = ufixed(max(a,c)+1 downto min(b,d)) + function "+" (l, r : ufixed) return ufixed; + + -- sfixed(a downto b) + sfixed(c downto d) + -- = sfixed(max(a,c)+1 downto min(b,d)) + function "+" (l, r : sfixed) return sfixed; + + -- Subtraction + -- ufixed(a downto b) - ufixed(c downto d) + -- = ufixed(max(a,c)+1 downto min(b,d)) + function "-" (l, r : ufixed) return ufixed; + + -- sfixed(a downto b) - sfixed(c downto d) + -- = sfixed(max(a,c)+1 downto min(b,d)) + function "-" (l, r : sfixed) return sfixed; + + -- Multiplication + -- ufixed(a downto b) * ufixed(c downto d) = ufixed(a+c+1 downto b+d) + function "*" (l, r : ufixed) return ufixed; + + -- sfixed(a downto b) * sfixed(c downto d) = sfixed(a+c+1 downto b+d) + function "*" (l, r : sfixed) return sfixed; + + -- Division + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) + function "/" (l, r : ufixed) return ufixed; + + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) + function "/" (l, r : sfixed) return sfixed; + + -- Remainder + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) + function "rem" (l, r : ufixed) return ufixed; + + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (min(a,c) downto min(b,d)) + function "rem" (l, r : sfixed) return sfixed; + + -- Modulo + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b, d)) + function "mod" (l, r : ufixed) return ufixed; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto min(b, d)) + function "mod" (l, r : sfixed) return sfixed; + + ---------------------------------------------------------------------------- + -- Overload routines. In these routines the "real" or "natural" (integer) + -- are converted into a fixed point number and then the operation is + -- performed. It is assumed that the array will be large enough. + -- If the input is "real" then the real number is converted into a fixed of + -- the same size as the fixed point input. If the number is an "integer" + -- then it is converted into fixed with the range (l'high downto 0). + ---------------------------------------------------------------------------- + -- ufixed(a downto b) + ufixed(a downto b) = ufixed(a+1 downto b) + function "+" (l : ufixed; r : REAL) return ufixed; + + -- ufixed(c downto d) + ufixed(c downto d) = ufixed(c+1 downto d) + function "+" (l : REAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) + ufixed(a downto 0) = ufixed(a+1 downto min(0,b)) + function "+" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto min(0,d)) + function "+" (l : NATURAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) - ufixed(a downto b) = ufixed(a+1 downto b) + function "-" (l : ufixed; r : REAL) return ufixed; + + -- ufixed(c downto d) - ufixed(c downto d) = ufixed(c+1 downto d) + function "-" (l : REAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) - ufixed(a downto 0) = ufixed(a+1 downto min(0,b)) + function "-" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto min(0,d)) + function "-" (l : NATURAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) * ufixed(a downto b) = ufixed(2a+1 downto 2b) + function "*" (l : ufixed; r : REAL) return ufixed; + + -- ufixed(c downto d) * ufixed(c downto d) = ufixed(2c+1 downto 2d) + function "*" (l : REAL; r : ufixed) return ufixed; + + -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) + function "*" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) + function "*" (l : NATURAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) + function "/" (l : ufixed; r : REAL) return ufixed; + + -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) + function "/" (l : REAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) / ufixed(a downto 0) = ufixed(a downto b-a-1) + function "/" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed(c downto 0) / ufixed(c downto d) = ufixed(c-d downto -c-1) + function "/" (l : NATURAL; r : ufixed) return ufixed; + + -- ufixed (a downto b) rem ufixed (a downto b) = ufixed (a downto b) + function "rem" (l : ufixed; r : REAL) return ufixed; + + -- ufixed (c downto d) rem ufixed (c downto d) = ufixed (c downto d) + function "rem" (l : REAL; r : ufixed) return ufixed; + + -- ufixed (a downto b) rem ufixed (a downto 0) = ufixed (a downto min(b,0)) + function "rem" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed (c downto 0) rem ufixed (c downto d) = ufixed (c downto min(d,0)) + function "rem" (l : NATURAL; r : ufixed) return ufixed; + + -- ufixed (a downto b) mod ufixed (a downto b) = ufixed (a downto b) + function "mod" (l : ufixed; r : REAL) return ufixed; + + -- ufixed (c downto d) mod ufixed (c downto d) = ufixed (c downto d) + function "mod" (l : REAL; r : ufixed) return ufixed; + + -- ufixed (a downto b) mod ufixed (a downto 0) = ufixed (a downto min(b,0)) + function "mod" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed (c downto 0) mod ufixed (c downto d) = ufixed (c downto min(d,0)) + function "mod" (l : NATURAL; r : ufixed) return ufixed; + + -- sfixed(a downto b) + sfixed(a downto b) = sfixed(a+1 downto b) + function "+" (l : sfixed; r : REAL) return sfixed; + + -- sfixed(c downto d) + sfixed(c downto d) = sfixed(c+1 downto d) + function "+" (l : REAL; r : sfixed) return sfixed; + + -- sfixed(a downto b) + sfixed(a downto 0) = sfixed(a+1 downto min(0,b)) + function "+" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed(c downto 0) + sfixed(c downto d) = sfixed(c+1 downto min(0,d)) + function "+" (l : INTEGER; r : sfixed) return sfixed; + + -- sfixed(a downto b) - sfixed(a downto b) = sfixed(a+1 downto b) + function "-" (l : sfixed; r : REAL) return sfixed; + + -- sfixed(c downto d) - sfixed(c downto d) = sfixed(c+1 downto d) + function "-" (l : REAL; r : sfixed) return sfixed; + + -- sfixed(a downto b) - sfixed(a downto 0) = sfixed(a+1 downto min(0,b)) + function "-" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed(c downto 0) - sfixed(c downto d) = sfixed(c+1 downto min(0,d)) + function "-" (l : INTEGER; r : sfixed) return sfixed; + + -- sfixed(a downto b) * sfixed(a downto b) = sfixed(2a+1 downto 2b) + function "*" (l : sfixed; r : REAL) return sfixed; + + -- sfixed(c downto d) * sfixed(c downto d) = sfixed(2c+1 downto 2d) + function "*" (l : REAL; r : sfixed) return sfixed; + + -- sfixed(a downto b) * sfixed(a downto 0) = sfixed(2a+1 downto b) + function "*" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed(c downto 0) * sfixed(c downto d) = sfixed(2c+1 downto d) + function "*" (l : INTEGER; r : sfixed) return sfixed; + + -- sfixed(a downto b) / sfixed(a downto b) = sfixed(a-b+1 downto b-a) + function "/" (l : sfixed; r : REAL) return sfixed; + + -- sfixed(c downto d) / sfixed(c downto d) = sfixed(c-d+1 downto d-c) + function "/" (l : REAL; r : sfixed) return sfixed; + + -- sfixed(a downto b) / sfixed(a downto 0) = sfixed(a+1 downto b-a) + function "/" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed(c downto 0) / sfixed(c downto d) = sfixed(c-d+1 downto -c) + function "/" (l : INTEGER; r : sfixed) return sfixed; + + -- sfixed (a downto b) rem sfixed (a downto b) = sfixed (a downto b) + function "rem" (l : sfixed; r : REAL) return sfixed; + + -- sfixed (c downto d) rem sfixed (c downto d) = sfixed (c downto d) + function "rem" (l : REAL; r : sfixed) return sfixed; + + -- sfixed (a downto b) rem sfixed (a downto 0) = sfixed (a downto min(b,0)) + function "rem" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed (c downto 0) rem sfixed (c downto d) = sfixed (c downto min(d,0)) + function "rem" (l : INTEGER; r : sfixed) return sfixed; + + -- sfixed (a downto b) mod sfixed (a downto b) = sfixed (a downto b) + function "mod" (l : sfixed; r : REAL) return sfixed; + + -- sfixed (c downto d) mod sfixed (c downto d) = sfixed (c downto d) + function "mod" (l : REAL; r : sfixed) return sfixed; + + -- sfixed (a downto b) mod sfixed (a downto 0) = sfixed (a downto min(b,0)) + function "mod" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed (c downto 0) mod sfixed (c downto d) = sfixed (c downto min(d,0)) + function "mod" (l : INTEGER; r : sfixed) return sfixed; + + -- This version of divide gives the user more control + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) + function divide ( + l, r : ufixed; + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return ufixed; + + -- This version of divide gives the user more control + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) + function divide ( + l, r : sfixed; + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return sfixed; + + -- These functions return 1/X + -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) + function reciprocal ( + arg : ufixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return ufixed; + + -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) + function reciprocal ( + arg : sfixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return sfixed; + + -- REM function + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) + function remainder ( + l, r : ufixed; + constant round_style : BOOLEAN := fixed_round_style) + return ufixed; + + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (min(a,c) downto min(b,d)) + function remainder ( + l, r : sfixed; + constant round_style : BOOLEAN := fixed_round_style) + return sfixed; + + -- mod function + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b, d)) + function modulo ( + l, r : ufixed; + constant round_style : BOOLEAN := fixed_round_style) + return ufixed; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto min(b, d)) + function modulo ( + l, r : sfixed; + constant overflow_style : BOOLEAN := fixed_overflow_style; + constant round_style : BOOLEAN := fixed_round_style) + return sfixed; + + -- Procedure for those who need an "accumulator" function. + -- add_carry (ufixed(a downto b), ufixed (c downto d)) + -- = ufixed (max(a,c) downto min(b,d)) + procedure add_carry ( + L, R : in ufixed; + c_in : in STD_ULOGIC; + result : out ufixed; + c_out : out STD_ULOGIC); + + -- add_carry (sfixed(a downto b), sfixed (c downto d)) + -- = sfixed (max(a,c) downto min(b,d)) + procedure add_carry ( + L, R : in sfixed; + c_in : in STD_ULOGIC; + result : out sfixed; + c_out : out STD_ULOGIC); + + -- Scales the result by a power of 2. Width of input = width of output with + -- the decimal point moved. + function scalb (y : ufixed; N : integer) return ufixed; + function scalb (y : ufixed; N : SIGNED) return ufixed; + function scalb (y : sfixed; N : integer) return sfixed; + function scalb (y : sfixed; N : SIGNED) return sfixed; + + function Is_Negative (arg : sfixed) return BOOLEAN; + --=========================================================================== + -- Comparison Operators + --=========================================================================== + function ">" (l, r : ufixed) return BOOLEAN; + function ">" (l, r : sfixed) return BOOLEAN; + function "<" (l, r : ufixed) return BOOLEAN; + function "<" (l, r : sfixed) return BOOLEAN; + function "<=" (l, r : ufixed) return BOOLEAN; + function "<=" (l, r : sfixed) return BOOLEAN; + function ">=" (l, r : ufixed) return BOOLEAN; + function ">=" (l, r : sfixed) return BOOLEAN; + function "=" (l, r : ufixed) return BOOLEAN; + function "=" (l, r : sfixed) return BOOLEAN; + function "/=" (l, r : ufixed) return BOOLEAN; + function "/=" (l, r : sfixed) return BOOLEAN; + --%%% Uncomment the following (new syntax) +-- function "?=" (L, R : ufixed) return BOOLEAN; +-- function "?=" (L, R : sfixed) return BOOLEAN; +-- --%%% remove the following (old syntax) + function \?=\ (L, R : ufixed) return STD_ULOGIC; + function \?=\ (L, R : sfixed) return STD_ULOGIC; + -- These need to be overloaded for sfixed and ufixed + function \?/=\ (L, R : ufixed) return STD_ULOGIC; + function \?>\ (L, R : ufixed) return STD_ULOGIC; + function \?>=\ (L, R : ufixed) return STD_ULOGIC; + function \?<\ (L, R : ufixed) return STD_ULOGIC; + function \?<=\ (L, R : ufixed) return STD_ULOGIC; + function \?/=\ (L, R : sfixed) return STD_ULOGIC; + function \?>\ (L, R : sfixed) return STD_ULOGIC; + function \?>=\ (L, R : sfixed) return STD_ULOGIC; + function \?<\ (L, R : sfixed) return STD_ULOGIC; + function \?<=\ (L, R : sfixed) return STD_ULOGIC; + -- %%% Replace with the following (new syntax) +-- function "?=" (L, R : ufixed) return STD_ULOGIC; +-- function "?/=" (L, R : ufixed) return STD_ULOGIC; +-- function "?>" (L, R : ufixed) return STD_ULOGIC; +-- function "?>=" (L, R : ufixed) return STD_ULOGIC; +-- function "?<" (L, R : ufixed) return STD_ULOGIC; +-- function "?<=" (L, R : ufixed) return STD_ULOGIC; +-- function "?=" (L, R : sfixed) return STD_ULOGIC; +-- function "?/=" (L, R : sfixed) return STD_ULOGIC; +-- function "?>" (L, R : sfixed) return STD_ULOGIC; +-- function "?>=" (L, R : sfixed) return STD_ULOGIC; +-- function "?<" (L, R : sfixed) return STD_ULOGIC; +-- function "?<=" (L, R : sfixed) return STD_ULOGIC; + + function std_match (L, R : ufixed) return BOOLEAN; + function std_match (L, R : sfixed) return BOOLEAN; + + -- Overloads the default "maximum" and "minimum" function + function maximum (l, r : ufixed) return ufixed; + function minimum (l, r : ufixed) return ufixed; + function maximum (l, r : sfixed) return sfixed; + function minimum (l, r : sfixed) return sfixed; + + ---------------------------------------------------------------------------- + -- In these compare functions a natural is converted into a + -- fixed point number of the bounds "max(l'high,0) downto 0" + ---------------------------------------------------------------------------- + function "=" (l : ufixed; r : NATURAL) return BOOLEAN; + function "/=" (l : ufixed; r : NATURAL) return BOOLEAN; + function ">=" (l : ufixed; r : NATURAL) return BOOLEAN; + function "<=" (l : ufixed; r : NATURAL) return BOOLEAN; + function ">" (l : ufixed; r : NATURAL) return BOOLEAN; + function "<" (l : ufixed; r : NATURAL) return BOOLEAN; + + function "=" (l : NATURAL; r : ufixed) return BOOLEAN; + function "/=" (l : NATURAL; r : ufixed) return BOOLEAN; + function ">=" (l : NATURAL; r : ufixed) return BOOLEAN; + function "<=" (l : NATURAL; r : ufixed) return BOOLEAN; + function ">" (l : NATURAL; r : ufixed) return BOOLEAN; + function "<" (l : NATURAL; r : ufixed) return BOOLEAN; + + ---------------------------------------------------------------------------- + -- In these compare functions a real is converted into a + -- fixed point number of the bounds "l'high+1 downto l'low" + ---------------------------------------------------------------------------- + function "=" (l : ufixed; r : REAL) return BOOLEAN; + function "/=" (l : ufixed; r : REAL) return BOOLEAN; + function ">=" (l : ufixed; r : REAL) return BOOLEAN; + function "<=" (l : ufixed; r : REAL) return BOOLEAN; + function ">" (l : ufixed; r : REAL) return BOOLEAN; + function "<" (l : ufixed; r : REAL) return BOOLEAN; + + function "=" (l : REAL; r : ufixed) return BOOLEAN; + function "/=" (l : REAL; r : ufixed) return BOOLEAN; + function ">=" (l : REAL; r : ufixed) return BOOLEAN; + function "<=" (l : REAL; r : ufixed) return BOOLEAN; + function ">" (l : REAL; r : ufixed) return BOOLEAN; + function "<" (l : REAL; r : ufixed) return BOOLEAN; + + ---------------------------------------------------------------------------- + -- In these compare functions an integer is converted into a + -- fixed point number of the bounds "max(l'high,1) downto 0" + ---------------------------------------------------------------------------- + function "=" (l : sfixed; r : INTEGER) return BOOLEAN; + function "/=" (l : sfixed; r : INTEGER) return BOOLEAN; + function ">=" (l : sfixed; r : INTEGER) return BOOLEAN; + function "<=" (l : sfixed; r : INTEGER) return BOOLEAN; + function ">" (l : sfixed; r : INTEGER) return BOOLEAN; + function "<" (l : sfixed; r : INTEGER) return BOOLEAN; + + function "=" (l : INTEGER; r : sfixed) return BOOLEAN; + function "/=" (l : INTEGER; r : sfixed) return BOOLEAN; + function ">=" (l : INTEGER; r : sfixed) return BOOLEAN; + function "<=" (l : INTEGER; r : sfixed) return BOOLEAN; + function ">" (l : INTEGER; r : sfixed) return BOOLEAN; + function "<" (l : INTEGER; r : sfixed) return BOOLEAN; + + ---------------------------------------------------------------------------- + -- In these compare functions a real is converted into a + -- fixed point number of the bounds "l'high+1 downto l'low" + ---------------------------------------------------------------------------- + function "=" (l : sfixed; r : REAL) return BOOLEAN; + function "/=" (l : sfixed; r : REAL) return BOOLEAN; + function ">=" (l : sfixed; r : REAL) return BOOLEAN; + function "<=" (l : sfixed; r : REAL) return BOOLEAN; + function ">" (l : sfixed; r : REAL) return BOOLEAN; + function "<" (l : sfixed; r : REAL) return BOOLEAN; + + function "=" (l : REAL; r : sfixed) return BOOLEAN; + function "/=" (l : REAL; r : sfixed) return BOOLEAN; + function ">=" (l : REAL; r : sfixed) return BOOLEAN; + function "<=" (l : REAL; r : sfixed) return BOOLEAN; + function ">" (l : REAL; r : sfixed) return BOOLEAN; + function "<" (l : REAL; r : sfixed) return BOOLEAN; + + --=========================================================================== + -- Shift and Rotate Functions. + -- Note that sra and sla are not the same as the BIT_VECTOR version + --=========================================================================== + function "sll" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "srl" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "rol" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "ror" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "sla" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "sra" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "sll" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function "srl" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function "rol" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function "ror" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function "sla" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function "sra" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function SHIFT_LEFT (ARG : ufixed; COUNT : NATURAL) return ufixed; + function SHIFT_RIGHT (ARG : ufixed; COUNT : NATURAL) return ufixed; + function SHIFT_LEFT (ARG : sfixed; COUNT : NATURAL) return sfixed; + function SHIFT_RIGHT (ARG : sfixed; COUNT : NATURAL) return sfixed; + + ---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + function "not" (L : ufixed) return ufixed; + function "and" (L, R : ufixed) return ufixed; + function "or" (L, R : ufixed) return ufixed; + function "nand" (L, R : ufixed) return ufixed; + function "nor" (L, R : ufixed) return ufixed; + function "xor" (L, R : ufixed) return ufixed; + function "xnor" (L, R : ufixed) return ufixed; + function "not" (L : sfixed) return sfixed; + function "and" (L, R : sfixed) return sfixed; + function "or" (L, R : sfixed) return sfixed; + function "nand" (L, R : sfixed) return sfixed; + function "nor" (L, R : sfixed) return sfixed; + function "xor" (L, R : sfixed) return sfixed; + function "xnor" (L, R : sfixed) return sfixed; + + -- Vector and std_ulogic functions, same as functions in numeric_std + function "and" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "and" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "or" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "or" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "nand" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "nand" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "nor" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "nor" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "xor" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "xor" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "xnor" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "xnor" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "and" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "and" (L : sfixed; R : STD_ULOGIC) return sfixed; + function "or" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "or" (L : sfixed; R : STD_ULOGIC) return sfixed; + function "nand" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "nand" (L : sfixed; R : STD_ULOGIC) return sfixed; + function "nor" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "nor" (L : sfixed; R : STD_ULOGIC) return sfixed; + function "xor" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "xor" (L : sfixed; R : STD_ULOGIC) return sfixed; + function "xnor" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "xnor" (L : sfixed; R : STD_ULOGIC) return sfixed; + + -- Reduction operators, same as numeric_std functions + -- %%% remove 12 functions (old syntax) + function and_reduce(arg : ufixed) return STD_ULOGIC; + function nand_reduce(arg : ufixed) return STD_ULOGIC; + function or_reduce(arg : ufixed) return STD_ULOGIC; + function nor_reduce(arg : ufixed) return STD_ULOGIC; + function xor_reduce(arg : ufixed) return STD_ULOGIC; + function xnor_reduce(arg : ufixed) return STD_ULOGIC; + function and_reduce(arg : sfixed) return STD_ULOGIC; + function nand_reduce(arg : sfixed) return STD_ULOGIC; + function or_reduce(arg : sfixed) return STD_ULOGIC; + function nor_reduce(arg : sfixed) return STD_ULOGIC; + function xor_reduce(arg : sfixed) return STD_ULOGIC; + function xnor_reduce(arg : sfixed) return STD_ULOGIC; + -- %%% Uncomment the following 12 functions (new syntax) + -- function "and" ( arg : ufixed ) RETURN std_ulogic; + -- function "nand" ( arg : ufixed ) RETURN std_ulogic; + -- function "or" ( arg : ufixed ) RETURN std_ulogic; + -- function "nor" ( arg : ufixed ) RETURN std_ulogic; + -- function "xor" ( arg : ufixed ) RETURN std_ulogic; + -- function "xnor" ( arg : ufixed ) RETURN std_ulogic; + -- function "and" ( arg : sfixed ) RETURN std_ulogic; + -- function "nand" ( arg : sfixed ) RETURN std_ulogic; + -- function "or" ( arg : sfixed ) RETURN std_ulogic; + -- function "nor" ( arg : sfixed ) RETURN std_ulogic; + -- function "xor" ( arg : sfixed ) RETURN std_ulogic; + -- function "xnor" ( arg : sfixed ) RETURN std_ulogic; + + -- returns arg'low-1 if not found + function find_msb (arg : ufixed; y : STD_ULOGIC) return INTEGER; + function find_msb (arg : sfixed; y : STD_ULOGIC) return INTEGER; + + -- returns arg'high+1 if not found + function find_lsb (arg : ufixed; y : STD_ULOGIC) return INTEGER; + function find_lsb (arg : sfixed; y : STD_ULOGIC) return INTEGER; + + --=========================================================================== + -- RESIZE Functions + --=========================================================================== + -- resizes the number (larger or smaller) + -- The returned result will be ufixed (left_index downto right_index) + -- If "round_style" is true, then the result will be rounded. If the MSB + -- of the remainder is a "1" AND the LSB of the unround result is a '1' or + -- the lower bits of the remainder include a '1' then the result will be + -- increased by the smallest representable number for that type. + -- The default is "true" for round_style. + -- "overflow_style" can be "true" (saturate mode) or "false" (wrap mode). + -- In saturate mode, if the number overflows then the largest possible + -- representable number is returned. If wrap mode, then the upper bits + -- of the number are truncated. + function resize ( + arg : ufixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return ufixed; + + -- "size_res" functions create the size of the output from the length + -- of the "size_res" input. The actual value of "size_res" is not used. + function resize ( + arg : ufixed; -- input + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return ufixed; + + -- Note that in "wrap" mode the sign bit is not replicated. Thus the + -- resize of a negative number can have a positive result in wrap mode. + function resize ( + arg : sfixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + function resize ( + arg : sfixed; -- input + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + --=========================================================================== + -- Conversion Functions + --=========================================================================== + -- integer (natural) to unsigned fixed point. + -- arguments are the upper and lower bounds of the number, thus + -- ufixed (7 downto -3) <= to_ufixed (int, 7, -3); + function to_ufixed ( + arg : NATURAL; -- integer + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding + return ufixed; + + function to_ufixed ( + arg : NATURAL; -- integer + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding + return ufixed; + + -- real to unsigned fixed point + function to_ufixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return ufixed; + + function to_ufixed ( + arg : REAL; -- real + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return ufixed; + + -- unsigned to unsigned fixed point + function to_ufixed ( + arg : UNSIGNED; -- unsigned + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return ufixed; + + function to_ufixed ( + arg : UNSIGNED; -- unsigned + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return ufixed; + + -- Performs a casting. ufixed (arg'range) is returned + function to_ufixed ( + arg : UNSIGNED) -- unsigned + return ufixed; + + -- unsigned fixed point to unsigned + function to_unsigned ( + arg : ufixed; -- fixed point input + constant size : NATURAL; -- length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return UNSIGNED; + + -- unsigned fixed point to unsigned + function to_unsigned ( + arg : ufixed; -- fixed point input + size_res : UNSIGNED; -- used for length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return UNSIGNED; + + -- unsigned fixed point to real + function to_real ( + arg : ufixed) -- fixed point input + return REAL; + + -- unsigned fixed point to integer + function to_integer ( + arg : ufixed; -- fixed point input + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return NATURAL; + + -- Integer to sfixed + function to_sfixed ( + arg : INTEGER; -- integer + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + function to_sfixed ( + arg : INTEGER; -- integer + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + -- Real to sfixed + function to_sfixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return sfixed; + + function to_sfixed ( + arg : REAL; -- real + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return sfixed; + + -- signed to sfixed + function to_sfixed ( + arg : SIGNED; -- signed + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + function to_sfixed ( + arg : SIGNED; -- signed + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + -- signed to sfixed (output assumed to be size of signed input) + function to_sfixed ( + arg : SIGNED) -- signed + return sfixed; + + -- unsigned fixed point to signed fixed point (adds a "0" sign bit) + function add_sign ( + arg : ufixed) -- unsigned fixed point + return sfixed; + + -- signed fixed point to signed + function to_signed ( + arg : sfixed; -- fixed point input + constant size : NATURAL; -- length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return SIGNED; + + -- signed fixed point to signed + function to_signed ( + arg : sfixed; -- fixed point input + size_res : SIGNED; -- used for length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return SIGNED; + + -- signed fixed point to real + function to_real ( + arg : sfixed) -- fixed point input + return REAL; + + -- signed fixed point to integer + function to_integer ( + arg : sfixed; -- fixed point input + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return INTEGER; + + -- Because of the farily complicated sizing rules in the fixed point + -- packages these functions are provided to compute the result ranges + -- Example: + -- signal uf1 : ufixed (3 downto -3); + -- signal uf2 : ufixed (4 downto -2); + -- signal uf1multuf2 : ufixed (ufixed_high (3, -3, '*', 4, -2) downto + -- ufixed_low (3, -3, '*', 4, -2)); + -- uf1multuf2 <= uf1 * uf2; + -- Valid characters: '+', '-', '*', '/', 'r' or 'R' (rem), 'm' or 'M' (mod) + function ufixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + function ufixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + function sfixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + function sfixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + -- Same as above, but using the "size_res" input only for their ranges: + -- signal uf1multuf2 : ufixed (ufixed_high (uf1, '*', uf2) downto + -- ufixed_low (uf1, '*', uf2)); + -- uf1multuf2 <= uf1 * uf2; + function ufixed_high (size_res : ufixed; + operation : CHARACTER := 'X'; + size_res2 : ufixed) + return INTEGER; + function ufixed_low (size_res : ufixed; + operation : CHARACTER := 'X'; + size_res2 : ufixed) + return INTEGER; + function sfixed_high (size_res : sfixed; + operation : CHARACTER := 'X'; + size_res2 : sfixed) + return INTEGER; + function sfixed_low (size_res : sfixed; + operation : CHARACTER := 'X'; + size_res2 : sfixed) + return INTEGER; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed; + + function saturate ( + size_res : ufixed) -- only the size of this is used + return ufixed; + + function saturate ( + size_res : sfixed) -- only the size of this is used + return sfixed; + + --=========================================================================== + -- Translation Functions + --=========================================================================== + -- Maps meta-logical values + function to_01 ( + s : ufixed; -- fixed point input + constant XMAP : STD_LOGIC := '0') -- Map x to + return ufixed; + + -- maps meta-logical values + function to_01 ( + s : sfixed; -- fixed point input + constant XMAP : STD_LOGIC := '0') -- Map x to + return sfixed; + + function Is_X (arg : ufixed) return BOOLEAN; + function Is_X (arg : sfixed) return BOOLEAN; + function to_X01 (arg : ufixed) return ufixed; + function to_X01 (arg : sfixed) return sfixed; + function to_X01Z (arg : ufixed) return ufixed; + function to_X01Z (arg : sfixed) return sfixed; + function to_UX01 (arg : ufixed) return ufixed; + function to_UX01 (arg : sfixed) return sfixed; + + -- straight vector conversion routines, needed for synthesis. + -- These functions are here so that a std_logic_vector can be + -- converted to and from sfixed and ufixed. Note that you can + -- not cast these vectors because of their negative index. + function to_slv ( + arg : ufixed) -- fp vector + return STD_LOGIC_VECTOR; +-- alias to_StdLogicVector is to_slv [ufixed return STD_LOGIC_VECTOR]; +-- alias to_Std_Logic_Vector is to_slv [ufixed return STD_LOGIC_VECTOR]; + + function to_slv ( + arg : sfixed) -- fp vector + return STD_LOGIC_VECTOR; +-- alias to_StdLogicVector is to_slv [sfixed return STD_LOGIC_VECTOR]; +-- alias to_Std_Logic_Vector is to_slv [sfixed return STD_LOGIC_VECTOR]; + + function to_sulv ( + arg : ufixed) -- fp vector + return STD_ULOGIC_VECTOR; +-- alias to_StdULogicVector is to_sulv [ufixed return STD_ULOGIC_VECTOR]; +-- alias to_Std_ULogic_Vector is to_sulv [ufixed return STD_ULOGIC_VECTOR]; + + function to_sulv ( + arg : sfixed) -- fp vector + return STD_ULOGIC_VECTOR; +-- alias to_StdULogicVector is to_sulv [sfixed return STD_ULOGIC_VECTOR]; +-- alias to_Std_ULogic_Vector is to_sulv [sfixed return STD_ULOGIC_VECTOR]; + + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed; + + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : ufixed) -- for size only + return ufixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : sfixed) -- for size only + return sfixed; + + + -- As a concession to those who use a graphical DSP environment, + -- these functions take parameters in those tools format and create + -- fixed point numbers. These functions are designed to convert from + -- a std_logic_vector to the VHDL fixed point format using the conventions + -- of these packages. In a pure VHDL environment you should use the + -- "to_ufixed" and "to_sfixed" routines. + -- Unsigned fixed point + function to_UFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return ufixed; + -- signed fixed point + function to_SFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return sfixed; + -- finding the bounds of a number. These functions can be used like this: + -- signal xxx : ufixed (7 downto -3); + -- -- Which is the same as "ufixed (UFix_high (11,3) downto UFix_low(11,3))" + -- signal yyy : ufixed (UFix_high (11, 3, "+", 11, 3) + -- downto UFix_low(11, 3, "+", 11, 3)); + -- Where "11" is the width of xxx (xxx'length), + -- and 3 is the lower bound (abs (xxx'low)) + -- In a pure VHDL environment use "ufixed_high" and "ufixed_low" + function UFix_high (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + function UFix_low (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + -- Same as above but for signed fixed point. Note that the width + -- of a signed fixed point number ignores the sign bit, thus + -- width = sxxx'length-1 + function SFix_high (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + function SFix_low (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + --=========================================================================== + -- string and textio Functions + --=========================================================================== +-- rtl_synthesis off +-- synthesis translate_off + -- purpose: writes fixed point into a line + procedure WRITE ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + -- purpose: writes fixed point into a line + procedure WRITE ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure READ(L : inout LINE; + VALUE : out ufixed); + + procedure READ(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN); + + procedure READ(L : inout LINE; + VALUE : out sfixed); + + procedure READ(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN); + + alias bwrite is WRITE [LINE, ufixed, SIDE, width]; + alias bwrite is WRITE [LINE, sfixed, SIDE, width]; + alias bread is READ [LINE, ufixed]; + alias bread is READ [LINE, ufixed, BOOLEAN]; + alias bread is READ [LINE, sfixed]; + alias bread is READ [LINE, sfixed, BOOLEAN]; + + -- octal read and write + procedure OWRITE ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure OWRITE ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure OREAD(L : inout LINE; + VALUE : out ufixed); + + procedure OREAD(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN); + + procedure OREAD(L : inout LINE; + VALUE : out sfixed); + + procedure OREAD(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN); + + -- hex read and write + procedure HWRITE ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + -- purpose: writes fixed point into a line + procedure HWRITE ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure HREAD(L : inout LINE; + VALUE : out ufixed); + + procedure HREAD(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN); + + procedure HREAD(L : inout LINE; + VALUE : out sfixed); + + procedure HREAD(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN); + + -- returns a string, useful for: + -- assert (x = y) report "error found " & to_string(x) severity error; + function to_string ( + value : ufixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + alias to_bstring is to_string [ufixed, SIDE, width return STRING]; + + function to_ostring ( + value : ufixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + function to_hstring ( + value : ufixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + function to_string ( + value : sfixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + alias to_bstring is to_string [sfixed, SIDE, width return STRING]; + + function to_ostring ( + value : sfixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + function to_hstring ( + value : sfixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + -- From string functions allow you to convert a string into a fixed + -- point number. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100", uf1'high, uf1'low); -- 6.5 + -- The "." is optional in this syntax, however it exist and is + -- in the wrong location an error is produced. Overflow will + -- result in saturation. + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed; + alias from_bstring is from_string [STRING, INTEGER, INTEGER return ufixed]; + + -- Octal and hex conversions work as follows: + -- uf1 <= from_hstring ("6.8", 3, -3); -- 6.5 (bottom zeros dropped) + -- uf1 <= from_ostring ("06.4", 3, -3); -- 6.5 (top zeros dropped) + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed; + + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed; + alias from_bstring is from_string [STRING, INTEGER, INTEGER return sfixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed; + + -- Same as above, "size_res" is used for it's range only. + function from_string ( + bstring : STRING; -- binary string + size_res : ufixed) + return ufixed; + alias from_bstring is from_string [STRING, ufixed return ufixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : ufixed) + return ufixed; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : ufixed) + return ufixed; + + function from_string ( + bstring : STRING; -- binary string + size_res : sfixed) + return sfixed; + alias from_bstring is from_string [STRING, sfixed return sfixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : sfixed) + return sfixed; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : sfixed) + return sfixed; + + -- Direct converstion functions. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100"); -- 6.5 + -- In this case the "." is not optional, and the size of + -- the output must match exactly. + function from_string ( + bstring : STRING) -- binary string + return ufixed; + alias from_bstring is from_string [STRING return ufixed]; + + -- Direct octal and hex converstion functions. In this case + -- the string lengths must match. Example: + -- signal sf1 := sfixed (5 downto -3); + -- sf1 <= from_ostring ("71.4") -- -6.5 + function from_ostring ( + ostring : STRING) -- Octal string + return ufixed; + + function from_hstring ( + hstring : STRING) -- hex string + return ufixed; + + function from_string ( + bstring : STRING) -- binary string + return sfixed; + alias from_bstring is from_string [STRING return sfixed]; + + function from_ostring ( + ostring : STRING) -- Octal string + return sfixed; + + function from_hstring ( + hstring : STRING) -- hex string + return sfixed; + +-- synthesis translate_on +-- rtl_synthesis on + -- This type is here for the floating point package. + type round_type is (round_nearest, -- Default, nearest LSB '0' + round_inf, -- Round to positive + round_neginf, -- Round to negate + round_zero); -- Round towards zero + -- These are the same as the C FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, + -- and FE_TOWARDZERO floating point rounding macros. + function to_StdLogicVector ( + arg : ufixed) -- fp vector + return STD_LOGIC_VECTOR; + function to_Std_Logic_Vector ( + arg : ufixed) -- fp vector + return STD_LOGIC_VECTOR; + function to_StdLogicVector ( + arg : sfixed) -- fp vector + return STD_LOGIC_VECTOR; + function to_Std_Logic_Vector ( + arg : sfixed) -- fp vector + return STD_LOGIC_VECTOR; +end package fixed_pkg; +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; +use std.textio.all; +use ieee.std_logic_textio.all; -- %%% for testing only +package body fixed_pkg is + -- Author David Bishop (dbishop@vhdl.org) + -- Other contributers: Jim Lewis, Yannick Grugni, Ryan W. Hilton + -- null array constants + constant NAUF : ufixed (0 downto 1) := (others => '0'); + constant NASF : sfixed (0 downto 1) := (others => '0'); + constant NSLV : STD_LOGIC_VECTOR (0 downto 1) := (others => '0'); + + -- This differed constant will tell you if the package body is synthesizable + -- or implemented as real numbers, set to "true" if synthesizable. + constant fixedsynth_or_real : BOOLEAN := true; + + --%%% Can be removed in vhdl-200x, will be implicit. + -- purpose: To find the largest of 2 numbers + function maximum (l, r : INTEGER) + return INTEGER is + begin -- function maximum + if L > R then return L; + else return R; + end if; + end function maximum; + + function minimum (l, r : INTEGER) + return INTEGER is + begin -- function minimum + if L > R then return R; + else return L; + end if; + end function minimum; + + -- %%% Remove the following function (duplicates of new numeric_std) + function "sra" (arg : SIGNED; count : INTEGER) + return SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(arg, count); + else + return SHIFT_LEFT(arg, -count); + end if; + end function "sra"; + + -- %%% Replace or_reducex with "or", and_reducex with "and", and + -- %%% xor_reducex with "xor", then remove the following 3 functions + -- purpose: OR all of the bits in a vector together + -- This is a copy of the proposed "or_reduce" from 1076.3 + function or_reducex (arg : STD_LOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_LOGIC; + variable Half : INTEGER; + variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_LOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '0'; + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) or BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := or_reducex (BUS_int (BUS_int'left downto Half)); + Lower := or_reducex (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper or Lower; + end if; + end if; + return Result; + end function or_reducex; + + -- purpose: AND all of the bits in a vector together + -- This is a copy of the proposed "and_reduce" from 1076.3 + function and_reducex (arg : STD_LOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_LOGIC; + variable Half : INTEGER; + variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_LOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '1'; + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) and BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := and_reducex (BUS_int (BUS_int'left downto Half)); + Lower := and_reducex (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper and Lower; + end if; + end if; + return Result; + end function and_reducex; + + function xor_reducex (arg : STD_LOGIC_VECTOR) return STD_ULOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range + begin + if (arg'length >= 1) then + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := xor_reducex (BUS_int (BUS_int'left downto Half)); + Lower := xor_reducex (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper xor Lower; + end if; + end if; + return Result; + end function xor_reducex; + + --%%% remove the following function and table + -- Match table, copied form new std_logic_1164 + type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; + constant match_logic_table : stdlogic_table := ( + ----------------------------------------------------- + -- U X 0 1 Z W L H - | | + ----------------------------------------------------- + ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1'), -- | U | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | X | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | 0 | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | 1 | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | Z | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | W | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | L | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | H | + ('1', '1', '1', '1', '1', '1', '1', '1', '1') -- | - | + ); + + constant no_match_logic_table : stdlogic_table := ( + ----------------------------------------------------- + -- U X 0 1 Z W L H - | | + ----------------------------------------------------- + ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '0'), -- | U | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | X | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | 0 | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | 1 | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | Z | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | W | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | L | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | H | + ('0', '0', '0', '0', '0', '0', '0', '0', '0') -- | - | + ); + + ------------------------------------------------------------------- + -- ?= functions, Similar to "std_match", but returns "std_ulogic". + ------------------------------------------------------------------- + -- %%% FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic IS + function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + begin + return match_logic_table (l, r); + end function \?=\; + -- %%% END FUNCTION "?="; + -- %%% FUNCTION "?/=" ( l, r : std_ulogic ) RETURN std_ulogic is + function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + begin + return no_match_logic_table (l, r); + end function \?/=\; + -- %%% END FUNCTION "?/="; + -- %%% end remove + + -- Special version of "minimum" to do some boundary checking without errors + function mins (l, r : INTEGER) + return INTEGER is + begin -- function mins + if (L = INTEGER'low or R = INTEGER'low) then + return 0; -- error condition + end if; + return minimum (L, R); + end function mins; + + -- Special version of "minimum" to do some boundary checking with errors + function mine (l, r : INTEGER) + return INTEGER is + begin -- function mine + if (L = INTEGER'low or R = INTEGER'low) then + report "FIXED_GENERIC_PKG: Unbounded number passed, was a literal used?" + severity error; + return 0; + end if; + return minimum (L, R); + end function mine; + + -- The following functions are used only internally. Every function + -- calls "cleanvec" either directly or indirectly. + -- purpose: Fixes "downto" problem and resolves meta states + function cleanvec ( + arg : sfixed) -- input + return sfixed is + constant left_index : INTEGER := maximum(arg'left, arg'right); + constant right_index : INTEGER := mins(arg'left, arg'right); + variable result : sfixed (arg'range); + begin -- function cleanvec + assert not ((arg'left < arg'right) and (arg'low /= INTEGER'low)) + report "FIXED_GENERIC_PKG: Vector passed using a ""to"" range, expected is ""downto""" + severity error; + return arg; + end function cleanvec; + + -- purpose: Fixes "downto" problem and resolves meta states + function cleanvec ( + arg : ufixed) -- input + return ufixed is + constant left_index : INTEGER := maximum(arg'left, arg'right); + constant right_index : INTEGER := mins(arg'left, arg'right); + variable result : ufixed (arg'range); + begin -- function cleanvec + assert not ((arg'left < arg'right) and (arg'low /= INTEGER'low)) + report "FIXED_GENERIC_PKG: Vector passed using a ""to"" range, expected is ""downto""" + severity error; + return arg; + end function cleanvec; + + -- Type cast a "unsigned" into a "ufixed", used internally + function to_fixed ( + arg : UNSIGNED; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + variable result : ufixed (left_index downto right_index); +-- variable j : INTEGER := arg'high; -- index for arg + begin -- function to_fixed + result := ufixed(arg); +-- floop : for i in result'range loop +-- result(i) := arg(j); -- res(4) := arg (4 + 3) +-- j := j - 1; +-- end loop floop; + return result; + end function to_fixed; + + -- Type cast a "signed" into an "sfixed", used internally + function to_fixed ( + arg : SIGNED; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable result : sfixed (left_index downto right_index); +-- variable j : INTEGER := arg'high; -- index for arg + begin -- function to_fixed + result := sfixed(arg); +-- floop : for i in result'range loop +-- result(i) := arg(j); -- res(4) := arg (4 + 3) +-- j := j - 1; +-- end loop floop; + return result; + end function to_fixed; + + -- Type cast a "ufixed" into an "unsigned", used internally + function to_uns ( + arg : ufixed) -- fp vector + return UNSIGNED is + subtype t is UNSIGNED(arg'high - arg'low downto 0); + variable slv : t; + begin -- function to_uns + slv := t(arg); +-- floop : for i in slv'range loop +-- slv(i) := arg(i + arg'low); -- slv(7) := arg (7 - 3) +-- end loop floop; + return UNSIGNED(to_X01(std_logic_vector(slv))); + end function to_uns; + + -- Type cast an "sfixed" into a "signed", used internally + function to_s ( + arg : sfixed) -- fp vector + return SIGNED is + subtype t is SIGNED(arg'high - arg'low downto 0); + variable slv : t; + begin -- function to_s + slv := t(arg); +-- floop : for i in slv'range loop +-- slv(i) := arg(i + arg'low); -- slv(7) := arg (7 - 3) +-- end loop floop; + return SIGNED(to_X01(std_logic_vector(slv))); + end function to_s; + + -- adds 1 to the LSB of the number + procedure round_up (arg : in ufixed; + result : out ufixed; + overflowx : out BOOLEAN) is + variable arguns, resuns : UNSIGNED (arg'high-arg'low+1 downto 0) := + (others => '0'); + begin -- round_up + arguns (arguns'high-1 downto 0) := to_uns (arg); + resuns := arguns + 1; + result := to_fixed(resuns(arg'high-arg'low + downto 0), arg'high, arg'low); + overflowx := (resuns(resuns'high) = '1'); + end procedure round_up; + + -- adds 1 to the LSB of the number + procedure round_up (arg : in sfixed; + result : out sfixed; + overflowx : out BOOLEAN) is + variable args, ress : SIGNED (arg'high-arg'low+1 downto 0); + begin -- round_up + args (args'high-1 downto 0) := to_s (arg); + args(args'high) := arg(arg'high); -- sign extend + ress := args + 1; + result := to_fixed(ress (ress'high-1 + downto 0), arg'high, arg'low); + overflowx := ((arg(arg'high) /= ress(ress'high-1)) + and (or_reducex (STD_LOGIC_VECTOR(ress)) /= '0')); + end procedure round_up; + + -- Rounding - Performs a "round_nearest" (IEEE 754) which rounds up + -- when the remainder is > 0.5. If the remainder IS 0.5 then if the + -- bottom bit is a "1" it is rounded, otherwise it remains the same. + function round_fixed (arg : ufixed; + remainder : ufixed; + overflow_style : BOOLEAN := fixed_overflow_style) + return ufixed is + variable rounds : BOOLEAN; + variable round_overflow : BOOLEAN; + variable result : ufixed (arg'range); + begin + rounds := false; + if (remainder'length > 1) then + if (remainder (remainder'high) = '1') then + rounds := (arg(arg'low) = '1') + or (or_reducex (to_slv(remainder(remainder'high-1 downto + remainder'low))) = '1'); + end if; + else + rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); + end if; + if rounds then + round_up(arg => arg, + result => result, + overflowx => round_overflow); + else + result := arg; + end if; + if (overflow_style = fixed_saturate) and round_overflow then + result := saturate (result'high, result'low); + end if; + return result; + end function round_fixed; + + -- Rounding case statement + function round_fixed (arg : sfixed; + remainder : sfixed; + overflow_style : BOOLEAN := fixed_overflow_style) + return sfixed is + variable rounds : BOOLEAN; + variable round_overflow : BOOLEAN; + variable result : sfixed (arg'range); + begin + rounds := false; + if (remainder'length > 1) then + if (remainder (remainder'high) = '1') then + rounds := (arg(arg'low) = '1') + or (or_reducex (to_slv(remainder(remainder'high-1 downto + remainder'low))) = '1'); + end if; + else + rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); + end if; + if rounds then + round_up(arg => arg, + result => result, + overflowx => round_overflow); + else + result := arg; + end if; + if round_overflow then + if (overflow_style = fixed_saturate) then + if arg(arg'high) = '0' then + result := saturate (result'high, result'low); + else + result := not saturate (result'high, result'low); + end if; +-- else +-- result(result'high) := arg(arg'high); -- fix sign bit in wrap + end if; + end if; + return result; + end function round_fixed; + +----------------------------------------------------------------------------- +-- Visible functions +----------------------------------------------------------------------------- + + -- casting functions. These are needed for synthesis where typically + -- the only input and output type is a std_logic_vector. + function to_slv ( + arg : ufixed) -- fixed point vector + return STD_LOGIC_VECTOR is + subtype t is STD_LOGIC_VECTOR (arg'high - arg'low downto 0); + variable slv : t; + begin + if arg'length < 1 then + return NSLV; + end if; + slv := t (arg); + return slv; + end function to_slv; + + function to_slv ( + arg : sfixed) -- fixed point vector + return STD_LOGIC_VECTOR is + subtype t is STD_LOGIC_VECTOR (arg'high - arg'low downto 0); + variable slv : t; + begin + if arg'length < 1 then + return NSLV; + end if; + slv := t (arg); + return slv; + end function to_slv; + + function to_sulv ( + arg : ufixed) -- fixed point vector + return STD_ULOGIC_VECTOR is + begin + return to_stdulogicvector (to_slv(arg)); + end function to_sulv; + + function to_sulv ( + arg : sfixed) -- fixed point vector + return STD_ULOGIC_VECTOR is + begin + return to_stdulogicvector (to_slv(arg)); + end function to_sulv; + + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + variable result : ufixed (left_index downto right_index); + begin + if (arg'length < 1 or right_index > left_index) then + return NAUF; + end if; + if (arg'length /= result'length) then + report "FIXED_GENERIC_PKG.TO_UFIXED (STD_LOGIC_VECTOR) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NAUF; + else + result := to_fixed (arg => UNSIGNED(arg), + left_index => left_index, + right_index => right_index); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable result : sfixed (left_index downto right_index); + begin + if (arg'length < 1 or right_index > left_index) then + return NASF; + end if; + if (arg'length /= result'length) then + report "FIXED_GENERIC_PKG.TO_SFIXED (STD_LOGIC_VECTOR) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NASF; + else + result := to_fixed (arg => SIGNED(arg), + left_index => left_index, + right_index => right_index); + return result; + end if; + end function to_sfixed; + + -- Two's complement number, Grows the vector by 1 bit. + -- because "abs (1000.000) = 01000.000" or abs(-16) = 16. + function "abs" ( + arg : sfixed) -- fixed point input + return sfixed is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable ressns : SIGNED (arg'length downto 0); + variable result : sfixed (left_index+1 downto right_index); + begin + if (arg'length < 1 or result'length < 1) then + return NASF; + end if; + ressns (arg'length-1 downto 0) := to_s (cleanvec (arg)); + ressns (arg'length) := ressns (arg'length-1); -- expand sign bit + result := to_fixed (abs(ressns), left_index+1, right_index); + return result; + end function "abs"; + + -- also grows the vector by 1 bit. + function "-" ( + arg : sfixed) -- fixed point input + return sfixed is + constant left_index : INTEGER := arg'high+1; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable ressns : SIGNED (arg'length downto 0); + variable result : sfixed (left_index downto right_index); + begin + if (arg'length < 1 or result'length < 1) then + return NASF; + end if; + ressns (arg'length-1 downto 0) := to_s (cleanvec(arg)); + ressns (arg'length) := ressns (arg'length-1); -- expand sign bit + result := to_fixed (-ressns, left_index, right_index); + return result; + end function "-"; + + function "abs" (arg : sfixed) return ufixed is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable xarg : sfixed(left_index+1 downto right_index); + variable result : ufixed(left_index downto right_index); + begin + if arg'length < 1 then + return NAUF; + end if; + xarg := abs(arg); + result := ufixed (xarg (left_index downto right_index)); + return result; + end function "abs"; + + -- Addition + function "+" ( + l, r : ufixed) -- ufixed(a downto b) + ufixed(c downto d) = + return ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable result : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + begin + if (l'length < 1 or r'length < 1) then + return NAUF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv + rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "+"; + + function "+" ( + l, r : sfixed) -- sfixed(a downto b) + sfixed(c downto d) = + return sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable result : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index downto 0); + variable result_slv : SIGNED (left_index-right_index downto 0); + begin + if (l'length < 1 or r'length < 1) then + return NASF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv + rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "+"; + + -- Subtraction + function "-" ( + l, r : ufixed) -- ufixed(a downto b) - ufixed(c downto d) = + return ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable result : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + begin + if (l'length < 1 or r'length < 1) then + return NAUF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv - rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "-"; + + function "-" ( + l, r : sfixed) -- sfixed(a downto b) - sfixed(c downto d) = + return sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable result : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index downto 0); + variable result_slv : SIGNED (left_index-right_index downto 0); + begin + if (l'length < 1 or r'length < 1) then + return NASF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv - rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "-"; + + function "*" ( + l, r : ufixed) -- ufixed(a downto b) * ufixed(c downto d) = + return ufixed is -- ufixed(a+c+1 downto b+d) + variable lslv : UNSIGNED (l'length-1 downto 0); + variable rslv : UNSIGNED (r'length-1 downto 0); + variable result_slv : UNSIGNED (r'length+l'length-1 downto 0); + variable result : ufixed (l'high + r'high+1 downto + mine(l'low, l'low) + mine(r'low, r'low)); + begin + if (l'length < 1 or r'length < 1 or + result'length /= result_slv'length) then + return NAUF; + end if; + lslv := to_uns (cleanvec(l)); + rslv := to_uns (cleanvec(r)); + result_slv := lslv * rslv; + result := to_fixed (result_slv, result'high, result'low); + return result; + end function "*"; + + function "*" ( + l, r : sfixed) -- sfixed(a downto b) * sfixed(c downto d) = + return sfixed is -- sfixed(a+c+1 downto b+d) + variable lslv : SIGNED (l'length-1 downto 0); + variable rslv : SIGNED (r'length-1 downto 0); + variable result_slv : SIGNED (r'length+l'length-1 downto 0); + variable result : sfixed (l'high + r'high+1 downto + mine(l'low, l'low) + mine(r'low, r'low)); + begin + if (l'length < 1 or r'length < 1 or + result'length /= result_slv'length) then + return NASF; + end if; + lslv := to_s (cleanvec(l)); + rslv := to_s (cleanvec(r)); + result_slv := lslv * rslv; + result := to_fixed (result_slv, result'high, result'low); + return result; + end function "*"; + + function "/" ( + l, r : ufixed) -- ufixed(a downto b) / ufixed(c downto d) = + return ufixed is -- ufixed(a-d downto b-c-1) + begin + return divide (l, r); + end function "/"; + + function "/" ( + l, r : sfixed) -- sfixed(a downto b) / sfixed(c downto d) = + return sfixed is -- sfixed(a-d+1 downto b-c) + begin + return divide (l, r); + end function "/"; + + -- This version of divide gives the user more control + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) + function divide ( + l, r : ufixed; + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return ufixed is + variable result : ufixed (l'high - mine(r'low, r'low) + downto mine (l'low, l'low) - r'high -1); + variable dresult : ufixed (result'high downto result'low -guard_bits); + variable lresize : ufixed (l'high downto l'high - dresult'length+1); + variable lslv : UNSIGNED (lresize'length-1 downto 0); + variable rslv : UNSIGNED (r'length-1 downto 0); + variable result_slv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1 or + mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then + return NAUF; + end if; + lresize := resize (l, lresize'high, lresize'low); + lslv := to_uns (cleanvec (lresize)); + rslv := to_uns (cleanvec (r)); + if (rslv = 0) then + report "FIXED_GENERIC_PKG.DIVIDE uFixed point Division by zero" severity error; + result := saturate (result'high, result'low); -- saturate + else + result_slv := lslv / rslv; + dresult := to_fixed (result_slv, dresult'high, dresult'low); + result := resize (arg => dresult, + left_index => result'high, + right_index => result'low, + round_style => round_style, + overflow_style => fixed_wrap); -- overflow impossible + end if; + return result; + end function divide; + + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) + function divide ( + l, r : sfixed; + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return sfixed is + variable result : sfixed (l'high - mine(r'low, r'low)+1 + downto mine (l'low, l'low) - r'high); + variable dresult : sfixed (result'high downto result'low-guard_bits); + variable lresize : sfixed (l'high+1 downto l'high+1 -dresult'length+1); + variable lslv : SIGNED (lresize'length-1 downto 0); + variable rslv : SIGNED (r'length-1 downto 0); + variable result_slv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1 or + mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then + return NASF; + end if; + lresize := resize (l, lresize'high, lresize'low); + lslv := to_s (cleanvec (lresize)); + rslv := to_s (cleanvec (r)); + if (rslv = 0) then + report "FIXED_GENERIC_PKG.DIVIDE uFixed point Division by zero" severity error; + result := saturate (result'high, result'low); + else + result_slv := lslv / rslv; + dresult := to_fixed (result_slv, dresult'high, dresult'low); + result := resize (arg => dresult, + left_index => result'high, + right_index => result'low, + round_style => round_style, + overflow_style => fixed_wrap); -- overflow impossible + end if; + return result; + end function divide; + + -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) + function reciprocal ( + arg : ufixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return ufixed is + constant one : ufixed (0 downto 0) := "1"; + begin + return divide(l => one, + r => arg, + round_style => round_style, + guard_bits => guard_bits); + end function reciprocal; + + -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) + function reciprocal ( + arg : sfixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return sfixed is + constant one : sfixed (1 downto 0) := "01"; -- extra bit. + variable resultx : sfixed (-mine(arg'low, arg'low)+2 downto -arg'high); + begin + if (arg'length < 1 or resultx'length < 1) then + return NASF; + else + resultx := divide(l => one, + r => arg, + round_style => round_style, + guard_bits => guard_bits); + return resultx (resultx'high-1 downto resultx'low); -- remove extra bit + end if; + end function reciprocal; + + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) + function "rem" ( + l, r : ufixed) -- fixed point input + return ufixed is + begin + return remainder (l => l, + r => r, + round_style => fixed_round_style); + end function "rem"; + + -- remainder + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (min(a,c) downto min(b,d)) + function "rem" ( + l, r : sfixed) -- fixed point input + return sfixed is + begin + return remainder (l => l, + r => r, + round_style => fixed_round_style); + end function "rem"; + + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) + function remainder ( + l, r : ufixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style) + return ufixed is + variable result : ufixed (minimum(l'high, r'high) downto mine(l'low, r'low)); + variable dresult : ufixed (r'high downto r'low); + variable lresize : ufixed (maximum(l'high, r'low) downto mins(r'low, r'low)); + variable lslv : UNSIGNED (lresize'length-1 downto 0); + variable rslv : UNSIGNED (r'length-1 downto 0); + variable result_slv : UNSIGNED (rslv'range); + begin + if (l'length < 1 or r'length < 1 or + mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then + return NAUF; + end if; + lresize := resize (arg => l, + left_index => lresize'high, + right_index => lresize'low, + overflow_style => fixed_wrap, -- vector only grows + round_style => fixed_truncate); + lslv := to_uns (lresize); + rslv := to_uns (cleanvec(r)); + if (rslv = 0) then + report "FIXED_GENERIC_PKG.rem uFixed point Division by zero" severity error; + result := saturate (result'high, result'low); -- saturate + else + if (r'low <= l'high) then + result_slv := lslv rem rslv; + dresult := to_fixed (result_slv, dresult'high, dresult'low); + result := resize (arg => dresult, + left_index => result'high, + right_index => result'low, + overflow_style => fixed_wrap, + round_style => round_style); +-- result(result'high downto r'low) := dresult(result'high downto r'low); + end if; + if l'low < r'low then + result(mins(r'low-1, l'high) downto l'low) := + cleanvec(l(mins(r'low-1, l'high) downto l'low)); + end if; + end if; + return result; + end function remainder; + + -- remainder + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (min(a,c) downto min(b,d)) + function remainder ( + l, r : sfixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style) + return sfixed is + variable l_abs : ufixed (l'range); + variable r_abs : ufixed (r'range); + variable result : sfixed (minimum(r'high, l'high) downto mine(r'low, l'low)); + variable neg_result : sfixed (minimum(r'high, l'high)+1 downto mins(r'low, l'low)); + begin + if (l'length < 1 or r'length < 1 or + mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then + return NASF; + end if; + l_abs := abs(l); + r_abs := abs(r); + result := sfixed(remainder (l => l_abs, + r => r_abs, + round_style => round_style)); + neg_result := -result; + if l(l'high) = '1' then + result := neg_result(result'range); + end if; + return result; + end function remainder; + + -- modulo + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b, d)) + function "mod" ( + l, r : ufixed) -- fixed point input + return ufixed is + begin + return modulo (l => l, + r => r, + round_style => fixed_round_style); + end function "mod"; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto min(b, d)) + function "mod" ( + l, r : sfixed) -- fixed point input + return sfixed is + begin + return modulo(l => l, + r => r, + round_style => fixed_round_style); + end function "mod"; + + -- modulo + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b, d)) + function modulo ( + l, r : ufixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style) + return ufixed is + begin + return remainder(l => l, + r => r, + round_style => round_style); + end function modulo; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto min(b, d)) + function modulo ( + l, r : sfixed; -- fixed point input + constant overflow_style : BOOLEAN := fixed_overflow_style; + constant round_style : BOOLEAN := fixed_round_style) + return sfixed is + variable l_abs : ufixed (l'range); + variable r_abs : ufixed (r'range); + variable result : sfixed (r'high downto + mine(r'low, l'low)); + variable dresult : sfixed (minimum(r'high, l'high)+1 downto + mins(r'low, l'low)); + variable dresult_not_zero : BOOLEAN; + begin + if (l'length < 1 or r'length < 1 or + mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then + return NASF; + end if; + l_abs := abs(l); + r_abs := abs(r); + dresult := "0" & sfixed(remainder (l => l_abs, + r => r_abs, + round_style => round_style)); + if (to_s(dresult) = 0) then + dresult_not_zero := false; + else + dresult_not_zero := true; + end if; + if to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '0' + and dresult_not_zero then + result := resize (arg => r - dresult, + left_index => result'high, + right_index => result'low, + overflow_style => overflow_style, + round_style => round_style); + elsif to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '1' then + result := resize (arg => -dresult, + left_index => result'high, + right_index => result'low, + overflow_style => overflow_style, + round_style => round_style); + elsif to_x01(l(l'high)) = '0' and to_x01(r(r'high)) = '1' + and dresult_not_zero then + result := resize (arg => dresult + r, + left_index => result'high, + right_index => result'low, + overflow_style => overflow_style, + round_style => round_style); + else + result := resize (arg => dresult, + left_index => result'high, + right_index => result'low, + overflow_style => overflow_style, + round_style => round_style); + end if; + return result; + end function modulo; + + -- Procedure for those who need an "accumulator" function + procedure add_carry ( + L, R : in ufixed; + c_in : in STD_ULOGIC; + result : out ufixed; + c_out : out STD_ULOGIC) is + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + variable cx : UNSIGNED (0 downto 0); -- Carry in + begin + if (l'length < 1 or r'length < 1) then + result := NAUF; + c_out := '0'; + else + cx (0) := c_in; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv + rslv + cx; + c_out := result_slv(left_index); + result := to_fixed(result_slv (left_index-right_index-1 downto 0), + left_index-1, right_index); + end if; + end procedure add_carry; + + procedure add_carry ( + L, R : in sfixed; + c_in : in STD_ULOGIC; + result : out sfixed; + c_out : out STD_ULOGIC) is + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index + downto 0); + variable result_slv : SIGNED (left_index-right_index + downto 0); + variable cx : SIGNED (1 downto 0); -- Carry in + begin + if (l'length < 1 or r'length < 1) then + result := NASF; + c_out := '0'; + else + cx (1) := '0'; + cx (0) := c_in; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv + rslv + cx; + c_out := result_slv(left_index); + result := to_fixed(result_slv (left_index-right_index-1 downto 0), + left_index-1, right_index); + end if; + end procedure add_carry; + + -- Scales the result by a power of 2. Width of input = width of output with + -- the decimal point moved. + function scalb (y : ufixed; N : integer) return ufixed is + variable result : ufixed (y'high+N downto y'low+N); + begin + if y'length < 1 then + return NAUF; + else + result := y; + return result; + end if; + end function scalb; + + function scalb (y : ufixed; N : SIGNED) return ufixed is + begin + return scalb (y => y, + N => to_integer(N)); + end function scalb; + + function scalb (y : sfixed; N : integer) return sfixed is + variable result : sfixed (y'high+N downto y'low+N); + begin + if y'length < 1 then + return NASF; + else + result := y; + return result; + end if; + end function scalb; + + function scalb (y : sfixed; N : SIGNED) return sfixed is + begin + return scalb (y => y, + N => to_integer(N)); + end function scalb; + + function Is_Negative (arg : sfixed) return BOOLEAN is + begin + if to_X01(arg(arg'high)) = '1' then + return true; + else + return false; + end if; + end function Is_Negative; + + function find_lsb (arg : ufixed; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'low to arg'high loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'high+1; -- return out of bounds 'high + end function find_lsb; + + function find_msb (arg : ufixed; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'high downto arg'low loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'low-1; -- return out of bounds 'low + end function find_msb; + + function find_lsb (arg : sfixed; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'low to arg'high loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'high+1; -- return out of bounds 'high + end function find_lsb; + + function find_msb (arg : sfixed; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'high downto arg'low loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'low-1; -- return out of bounds 'low + end function find_msb; + + function "sll" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sll"; + + function "srl" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "srl"; + + function "rol" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv rol COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "rol"; + + function "ror" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv ror COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "ror"; + + function "sla" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + -- Arithmetic shift on an unsigned is a logical shift + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sla"; + + function "sra" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + -- Arithmetic shift on an unsigned is a logical shift + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sra"; + + function "sll" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sll"; + + function "srl" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "srl"; + + function "rol" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv rol COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "rol"; + + function "ror" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv ror COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "ror"; + + function "sla" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + if COUNT > 0 then + -- Arithmetic shift left on a 2's complement number is a logic shift + argslv := argslv sll COUNT; + else + argslv := argslv sra -COUNT; + end if; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sla"; + + function "sra" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + if COUNT > 0 then + argslv := argslv sra COUNT; + else + -- Arithmetic shift left on a 2's complement number is a logic shift + argslv := argslv sll -COUNT; + end if; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sra"; + + -- Because some people want the older functions. + function SHIFT_LEFT (ARG : ufixed; COUNT : NATURAL) return ufixed is + begin + if (ARG'length < 1) then + return NAUF; + end if; + return ARG sla COUNT; + end function SHIFT_LEFT; + function SHIFT_RIGHT (ARG : ufixed; COUNT : NATURAL) return ufixed is + begin + if (ARG'length < 1) then + return NAUF; + end if; + return ARG sra COUNT; + end function SHIFT_RIGHT; + function SHIFT_LEFT (ARG : sfixed; COUNT : NATURAL) return sfixed is + begin + if (ARG'length < 1) then + return NASF; + end if; + return ARG sla COUNT; + end function SHIFT_LEFT; + function SHIFT_RIGHT (ARG : sfixed; COUNT : NATURAL) return sfixed is + begin + if (ARG'length < 1) then + return NASF; + end if; + return ARG sra COUNT; + end function SHIFT_RIGHT; + + ---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + function "not" (L : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + RESULT := not to_slv(L); + return to_ufixed(RESULT, L'high, L'low); + end function "not"; + + function "and" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) and to_slv(R); + else + report "FIXED_GENERIC_PKG.""and"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "and"; + + function "or" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) or to_slv(R); + else + report "FIXED_GENERIC_PKG.""or"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "or"; + + function "nand" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) nand to_slv(R); + else + report "FIXED_GENERIC_PKG.""nand"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "nand"; + + function "nor" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) nor to_slv(R); + else + report "FIXED_GENERIC_PKG.""nor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "nor"; + + function "xor" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) xor to_slv(R); + else + report "FIXED_GENERIC_PKG.""xor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "xor"; + + function "xnor" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) xnor to_slv(R); + else + report "FIXED_GENERIC_PKG.""xnor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "xnor"; + + function "not" (L : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + RESULT := not to_slv(L); + return to_sfixed(RESULT, L'high, L'low); + end function "not"; + + function "and" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) and to_slv(R); + else + report "FIXED_GENERIC_PKG.""and"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "and"; + + function "or" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) or to_slv(R); + else + report "FIXED_GENERIC_PKG.""or"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "or"; + + function "nand" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) nand to_slv(R); + else + report "FIXED_GENERIC_PKG.""nand"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "nand"; + + function "nor" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) nor to_slv(R); + else + report "FIXED_GENERIC_PKG.""nor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "nor"; + + function "xor" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) xor to_slv(R); + else + report "FIXED_GENERIC_PKG.""xor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "xor"; + + function "xnor" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) xnor to_slv(R); + else + report "FIXED_GENERIC_PKG.""xnor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "xnor"; + + -- Vector and std_ulogic functions, same as functions in numeric_std + function "and" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L and R(i); + end loop; + return result; + end function "and"; + + function "and" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) and R; + end loop; + return result; + end function "and"; + + function "or" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L or R(i); + end loop; + return result; + end function "or"; + + function "or" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) or R; + end loop; + return result; + end function "or"; + + function "nand" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L nand R(i); + end loop; + return result; + end function "nand"; + + function "nand" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nand R; + end loop; + return result; + end function "nand"; + + function "nor" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L nor R(i); + end loop; + return result; + end function "nor"; + + function "nor" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nor R; + end loop; + return result; + end function "nor"; + + function "xor" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L xor R(i); + end loop; + return result; + end function "xor"; + + function "xor" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xor R; + end loop; + return result; + end function "xor"; + + function "xnor" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L xnor R(i); + end loop; + return result; + end function "xnor"; + + function "xnor" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xnor R; + end loop; + return result; + end function "xnor"; + + function "and" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L and R(i); + end loop; + return result; + end function "and"; + + function "and" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) and R; + end loop; + return result; + end function "and"; + + function "or" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L or R(i); + end loop; + return result; + end function "or"; + + function "or" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) or R; + end loop; + return result; + end function "or"; + + function "nand" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L nand R(i); + end loop; + return result; + end function "nand"; + + function "nand" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nand R; + end loop; + return result; + end function "nand"; + + function "nor" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L nor R(i); + end loop; + return result; + end function "nor"; + + function "nor" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nor R; + end loop; + return result; + end function "nor"; + + function "xor" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L xor R(i); + end loop; + return result; + end function "xor"; + + function "xor" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xor R; + end loop; + return result; + end function "xor"; + + function "xnor" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L xnor R(i); + end loop; + return result; + end function "xnor"; + + function "xnor" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xnor R; + end loop; + return result; + end function "xnor"; + + -- Reduction operators, same as numeric_std functions + -- %%% remove 12 functions (old syntax) + function and_reduce(arg : ufixed) return STD_ULOGIC is + begin + return and_reducex (to_slv(arg)); + end function and_reduce; + + function nand_reduce(arg : ufixed) return STD_ULOGIC is + begin + return not and_reducex (to_slv(arg)); + end function nand_reduce; + + function or_reduce(arg : ufixed) return STD_ULOGIC is + begin + return or_reducex (to_slv(arg)); + end function or_reduce; + + function nor_reduce(arg : ufixed) return STD_ULOGIC is + begin + return not or_reducex (to_slv(arg)); + end function nor_reduce; + + function xor_reduce(arg : ufixed) return STD_ULOGIC is + begin + return xor_reducex (to_slv(arg)); + end function xor_reduce; + + function xnor_reduce(arg : ufixed) return STD_ULOGIC is + begin + return not xor_reducex (to_slv(arg)); + end function xnor_reduce; + + function and_reduce(arg : sfixed) return STD_ULOGIC is + begin + return and_reducex (to_slv(arg)); + end function and_reduce; + + function nand_reduce(arg : sfixed) return STD_ULOGIC is + begin + return not and_reducex (to_slv(arg)); + end function nand_reduce; + + function or_reduce(arg : sfixed) return STD_ULOGIC is + begin + return or_reducex (to_slv(arg)); + end function or_reduce; + + function nor_reduce(arg : sfixed) return STD_ULOGIC is + begin + return not or_reducex (to_slv(arg)); + end function nor_reduce; + + function xor_reduce(arg : sfixed) return STD_ULOGIC is + begin + return xor_reducex (to_slv(arg)); + end function xor_reduce; + + function xnor_reduce(arg : sfixed) return STD_ULOGIC is + begin + return not xor_reducex (to_slv(arg)); + end function xnor_reduce; + -- %%% Uncomment the following 12 functions (new syntax) + -- function "and" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return and to_slv(arg); + -- end function "and"; + -- function "nand" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return nand to_slv(arg); + -- end function "nand";; + -- function "or" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return or to_slv(arg); + -- end function "or"; + -- function "nor" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return nor to_slv(arg); + -- end function "nor"; + -- function "xor" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return xor to_slv(arg); + -- end function "xor"; + -- function "xnor" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return xnor to_slv(arg); + -- end function "xnor"; + -- function "and" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return and to_slv(arg); + -- end function "and";; + -- function "nand" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return nand to_slv(arg); + -- end function "nand";; + -- function "or" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return or to_slv(arg); + -- end function "or"; + -- function "nor" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return nor to_slv(arg); + -- end function "nor"; + -- function "xor" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return xor to_slv(arg); + -- end function "xor"; + -- function "xnor" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return xnor to_slv(arg); + -- end function "xnor"; + + -- %%% Replace with the following (new syntax) +-- function "?=" (L, R : ufixed) return STD_ULOGIC is + function \?=\ (L, R : ufixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + result := '1'; + for i in lresize'reverse_range loop + result1 := \?=\(lresize(i), rresize(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; +-- end function "?="; + +-- function "?/=" (L, R : ufixed) return STD_ULOGIC is + function \?/=\ (L, R : ufixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?/= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?/="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + result := '0'; + for i in lresize'reverse_range loop + result1 := \?/=\ (lresize(i), rresize(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; +-- end function "?/="; + +-- function "?>" (L, R : ufixed) return STD_ULOGIC is + function \?>\ (L, R : ufixed) return STD_ULOGIC is + begin -- ?> + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?>"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?>"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; +-- end function "?>"; + +-- function "?>=" (L, R : ufixed) return STD_ULOGIC is + function \?>=\ (L, R : ufixed) return STD_ULOGIC is + begin -- ?>= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?>="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?>="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; +-- end function "?>="; + +-- function "?<" (L, R : ufixed) return STD_ULOGIC is + function \?<\ (L, R : ufixed) return STD_ULOGIC is + begin -- ?< + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?<"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?<"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; +-- end function "?<"; + +-- function "?<=" (L, R : ufixed) return STD_ULOGIC is + function \?<=\ (L, R : ufixed) return STD_ULOGIC is + begin -- ?<= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?<="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?<="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; +-- end function "?<="; + + -- function "?=" (L, R : sfixed) return STD_ULOGIC is + function \?=\ (L, R : sfixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + result := '1'; + for i in lresize'reverse_range loop + result1 := \?=\ (lresize(i), rresize(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; +-- end function "?="; + +-- function "?/=" (L, R : sfixed) return STD_ULOGIC is + function \?/=\ (L, R : sfixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?/= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?/="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + result := '0'; + for i in lresize'reverse_range loop + result1 := \?/=\ (lresize(i), rresize(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; +-- end function "?/="; + +-- function "?>" (L, R : sfixed) return STD_ULOGIC is + function \?>\ (L, R : sfixed) return STD_ULOGIC is + begin -- ?> + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?>"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?>"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; +-- end function "?>"; + +-- function "?>=" (L, R : sfixed) return STD_ULOGIC is + function \?>=\ (L, R : sfixed) return STD_ULOGIC is + begin -- ?>= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?>="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?>="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; +-- end function "?>="; + +-- function "?<" (L, R : sfixed) return STD_ULOGIC is + function \?<\ (L, R : sfixed) return STD_ULOGIC is + begin -- ?< + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?<"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?<"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; +-- end function "?<"; + +-- function "?<=" (L, R : sfixed) return STD_ULOGIC is + function \?<=\ (L, R : sfixed) return STD_ULOGIC is + begin -- ?<= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?<="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?<="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; +-- end function "?<="; + + -- %%% end replace + -- Match function, similar to "std_match" from numeric_std + function std_match (L, R : ufixed) return BOOLEAN is + begin + if (L'high = R'high and L'low = R'low) then + return std_match(to_slv(L), to_slv(R)); + else + report "FIXED_GENERIC_PKG.STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" + severity warning; + return false; + end if; + end function std_match; + + function std_match (L, R : sfixed) return BOOLEAN is + begin + if (L'high = R'high and L'low = R'low) then + return std_match(to_slv(L), to_slv(R)); + else + report "FIXED_GENERIC_PKG.STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" + severity warning; + return false; + end if; + end function std_match; + --%%% end remove + + -- compare functions + function "=" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv = rslv; + end function "="; + + function "=" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv = rslv; + end function "="; + + function "/=" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""/="": null argument detected, returning TRUE" + severity warning; + return true; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""/="": metavalue detected, returning TRUE" + severity warning; + return true; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv /= rslv; + end function "/="; + + function "/=" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""/="": null argument detected, returning TRUE" + severity warning; + return true; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""/="": metavalue detected, returning TRUE" + severity warning; + return true; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv /= rslv; + end function "/="; + + function ">" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv > rslv; + end function ">"; + + function ">" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv > rslv; + end function ">"; + + function "<" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv < rslv; + end function "<"; + + function "<" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv < rslv; + end function "<"; + + function ">=" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv >= rslv; + end function ">="; + + function ">=" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv >= rslv; + end function ">="; + + function "<=" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv <= rslv; + end function "<="; + + function "<=" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv <= rslv; + end function "<="; + + -- overloads of the default maximum and minimum functions + function maximum (l, r : ufixed) return ufixed is + begin + if l > r then return l; + else return r; + end if; + end function maximum; + + function maximum (l, r : sfixed) return sfixed is + begin + if l > r then return l; + else return r; + end if; + end function maximum; + + function minimum (l, r : ufixed) return ufixed is + begin + if l > r then return r; + else return l; + end if; + end function minimum; + + function minimum (l, r : sfixed) return sfixed is + begin + if l > r then return r; + else return l; + end if; + end function minimum; + + function to_ufixed ( + arg : NATURAL; -- integer + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return ufixed is + variable argx : INTEGER; + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : ufixed (left_index downto fw) := (others => '0'); + variable sresult : UNSIGNED (left_index downto 0); -- integer portion + variable bound : NATURAL; -- find the numerical bounds + begin + if (left_index < fw) then + return NAUF; + end if; + if left_index >= 0 then + if (left_index < 30) then + bound := 2**(left_index+1); + else + bound := INTEGER'high; + end if; + end if; + if (arg /= 0) then + if arg >= bound or left_index < 0 then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_UFIXED(NATURAL): vector truncated" + severity warning; + if (overflow_style = fixed_wrap) then -- wrap + if bound = 0 then + argx := 0; + else + argx := arg mod bound; + end if; + else -- saturate + return saturate (result'high, result'low); + end if; + else + argx := arg; + end if; + else + return result; -- return zero + end if; + sresult := to_unsigned (argx, sresult'high+1); + result := resize (arg => ufixed (sresult), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_ufixed; + + function to_sfixed ( + arg : INTEGER; -- integer + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return sfixed is + variable argx : INTEGER; + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : sfixed (left_index downto fw) := (others => '0'); + variable sresult : SIGNED (left_index+1 downto 0); -- integer portion + variable bound : NATURAL := 0; + begin + if (left_index < fw) then -- null range + return NASF; + end if; + if left_index >= 0 then + if (left_index < 30) then + bound := 2**(left_index); + else + bound := INTEGER'high; + end if; + end if; + if (arg /= 0) then + if (arg >= bound or arg < -bound or left_index < 0) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_SFIXED(INTEGER): vector truncated" + severity warning; + if overflow_style = fixed_wrap then -- wrap + if bound = 0 then -- negative integer_range trap + argx := 0; + else -- shift off the top bits + argx := arg rem (bound*2); + end if; + else -- saturate + if arg < 0 then + result := not saturate (result'high, result'low); -- underflow + else + result := saturate (result'high, result'low); -- overflow + end if; + return result; + end if; + else + argx := arg; + end if; + else + return result; -- return zero + end if; + sresult := to_signed (argx, sresult'length); + result := resize (arg => sfixed (sresult), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_sfixed; + + function to_ufixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return ufixed is + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : ufixed (left_index downto fw) := (others => '0'); + variable Xresult : ufixed (left_index downto fw-guard_bits) := (others => '0'); + variable presult : REAL; + variable overflow_needed : BOOLEAN; + begin + -- If negative or null range, return. + if (left_index < fw) then + return NAUF; + end if; + if (arg < 0.0) then + report "FIXED_GENERIC_PKG.TO_UFIXED: Negative argument passed " + & REAL'image(arg) severity error; + return result; + end if; + presult := arg; + if presult >= (2.0**(left_index+1)) then + assert NO_WARNING report "FIXED_GENERIC_PKG.TO_UFIXED(REAL): vector truncated" + severity warning; + overflow_needed := (overflow_style = fixed_saturate); + if overflow_style = fixed_wrap then + presult := presult mod (2.0**(left_index+1)); -- wrap + else + return saturate (result'high, result'low); + end if; + end if; + for i in Xresult'range loop + if presult >= 2.0**i then + Xresult(i) := '1'; + presult := presult - 2.0**i; + else + Xresult(i) := '0'; + end if; + end loop; + if guard_bits > 0 and round_style = fixed_round then + result := round_fixed (arg => Xresult (left_index + downto right_index), + remainder => Xresult (right_index-1 downto + right_index-guard_bits), + overflow_style => overflow_style); + else + result := Xresult (result'range); + end if; + return result; + end function to_ufixed; + + function to_sfixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return sfixed is + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : sfixed (left_index downto fw) := (others => '0'); + variable Xresult : sfixed (left_index+1 downto fw-guard_bits) := (others => '0'); + variable presult : REAL; + begin + if (left_index < fw) then -- null range + return NASF; + end if; + if (arg >= (2.0**left_index) or arg < -(2.0**left_index)) then + assert NO_WARNING report "FIXED_GENERIC_PKG.TO_SFIXED(REAL): vector truncated" + severity warning; + if overflow_style = fixed_saturate then + if arg < 0.0 then -- saturate + result := not saturate (result'high, result'low); -- underflow + else + result := saturate (result'high, result'low); -- overflow + end if; + return result; + else + presult := abs(arg) mod (2.0**(left_index+1)); -- wrap + end if; + else + presult := abs(arg); + end if; + for i in Xresult'range loop + if presult >= 2.0**i then + Xresult(i) := '1'; + presult := presult - 2.0**i; + else + Xresult(i) := '0'; + end if; + end loop; + if arg < 0.0 then + Xresult := to_fixed(-to_s(Xresult), Xresult'high, Xresult'low); + end if; + if guard_bits > 0 and round_style then + result := round_fixed (arg => Xresult (left_index + downto right_index), + remainder => Xresult (right_index-1 downto + right_index-guard_bits), + overflow_style => overflow_style); + else + result := Xresult (result'range); + end if; + return result; + end function to_sfixed; + + function to_ufixed ( + arg : UNSIGNED; -- unsigned + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return ufixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : ufixed (left_index downto fw); + begin + if arg'length < 1 or (left_index < fw) then + return NAUF; + end if; + result := resize (arg => ufixed (XARG), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_ufixed; + + -- casted version + function to_ufixed ( + arg : UNSIGNED) -- unsigned + return ufixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; + begin + if arg'length < 1 then + return NAUF; + end if; + return ufixed(xarg); + end function to_ufixed; + + function to_sfixed ( + arg : SIGNED; -- signed + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return sfixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : sfixed (left_index downto fw); + begin + if arg'length < 1 or (left_index < fw) then + return NASF; + end if; + result := resize (arg => sfixed (XARG), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_sfixed; + + -- casted version + function to_sfixed ( + arg : SIGNED) -- signed + return sfixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; + begin + if arg'length < 1 then + return NASF; + end if; + return sfixed(xarg); + end function to_sfixed; + + function add_sign (arg : ufixed) return sfixed is + variable result : sfixed (arg'high+1 downto arg'low); + begin + if arg'length < 1 then + return NASF; + end if; + result (arg'high downto arg'low) := sfixed(cleanvec(arg)); + result (arg'high+1) := '0'; + return result; + end function add_sign; + + -- Because of the farily complicated sizing rules in the fixed point + -- packages these functions are provided to compute the result ranges + -- Example: + -- signal uf1 : ufixed (3 downto -3); + -- signal uf2 : ufixed (4 downto -2); + -- signal uf1multuf2 : ufixed (ufixed_high (3, -3, '*', 4, -2) downto + -- ufixed_low (3, -3, '*', 4, -2)); + -- uf1multuf2 <= uf1 * uf2; + -- Valid characters: '+', '-', '*', '/', 'r' or 'R' (rem), 'm' or 'M' (mod), + -- '1' (reciprocal), 'A', 'a' (abs), 'N', 'n' (-sfixed) + function ufixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return maximum (left_index, left_index2) + 1; + when '*' => return left_index + left_index2 + 1; + when '/' => return left_index - right_index2; + when '1' => return -right_index; -- reciprocal + when 'R'|'r' => return mins (left_index, left_index2); -- "rem" + when 'M'|'m' => return mins (left_index, left_index2); -- "mod" + when others => return left_index; -- For abs and default + end case; + end function ufixed_high; + + function ufixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return mins (right_index, right_index2); + when '*' => return right_index + right_index2; + when '/' => return right_index - left_index2 - 1; + when '1' => return -left_index - 1; -- reciprocal + when 'R'|'r' => return mins (right_index, right_index2); -- "rem" + when 'M'|'m' => return mins (right_index, right_index2); -- "mod" + when others => return right_index; -- for abs and default + end case; + end function ufixed_low; + + function sfixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return maximum (left_index, left_index2) + 1; + when '*' => return left_index + left_index2 + 1; + when '/' => return left_index - right_index2 + 1; + when '1' => return -right_index + 1; -- reciprocal + when 'R'|'r' => return mins (left_index, left_index2); -- "rem" + when 'M'|'m' => return left_index2; -- "mod" + when 'A'|'a' => return left_index + 1; -- "abs" + when 'N'|'n' => return left_index + 1; -- -sfixed + when others => return left_index; + end case; + end function sfixed_high; + + function sfixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return mins (right_index, right_index2); + when '*' => return right_index + right_index2; + when '/' => return right_index - left_index2; + when '1' => return -left_index; -- reciprocal + when 'R'|'r' => return mins (right_index, right_index2); -- "rem" + when 'M'|'m' => return mins (right_index, right_index2); -- "mod" + when others => return right_index; -- default for abs, neg and default + end case; + end function sfixed_low; + -- Same as above, but using the "size_res" input only for their ranges: + -- signal uf1multuf2 : ufixed (ufixed_high (uf1, '*', uf2) downto + -- ufixed_low (uf1, '*', uf2)); + -- uf1multuf2 <= uf1 * uf2; + function ufixed_high (size_res : ufixed; + operation : CHARACTER := 'X'; + size_res2 : ufixed) + return INTEGER is + begin + return ufixed_high (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function ufixed_high; + function ufixed_low (size_res : ufixed; + operation : CHARACTER := 'X'; + size_res2 : ufixed) + return INTEGER is + begin + return ufixed_low (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function ufixed_low; + function sfixed_high (size_res : sfixed; + operation : CHARACTER := 'X'; + size_res2 : sfixed) + return INTEGER is + begin + return sfixed_high (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function sfixed_high; + function sfixed_low (size_res : sfixed; + operation : CHARACTER := 'X'; + size_res2 : sfixed) + return INTEGER is + begin + return sfixed_low (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function sfixed_low; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + constant sat : ufixed (left_index downto right_index) := (others => '1'); + begin + return sat; + end function saturate; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable sat : sfixed (left_index downto right_index) := (others => '1'); + begin + -- saturate positive, to saturate negative, just do "not saturate()" + sat (left_index) := '0'; + return sat; + end function saturate; + + function saturate ( + size_res : ufixed) -- only the size of this is used + return ufixed is + begin + return saturate (size_res'high, size_res'low); + end function saturate; + + function saturate ( + size_res : sfixed) -- only the size of this is used + return sfixed is + begin + return saturate (size_res'high, size_res'low); + end function saturate; + + -- As a concession to those who use a graphical DSP environment, + -- these functions take parameters in those tools format and create + -- fixed point numbers. These functions are designed to convert from + -- a std_logic_vector to the VHDL fixed point format using the conventions + -- of these packages. In a pure VHDL environment you should use the + -- "to_ufixed" and "to_sfixed" routines. + -- Unsigned fixed point + function to_UFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return ufixed is + variable result : ufixed (width-fraction-1 downto -fraction); + begin + if (arg'length /= result'length) then + report "FIXED_GENERIC_PKG.TO_UFIX (STD_LOGIC_VECTOR) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NAUF; + else + result := to_ufixed (arg, result'high, result'low); + return result; + end if; + end function to_UFix; + + -- signed fixed point + function to_SFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return sfixed is + variable result : sfixed (width-fraction-1 downto -fraction); + begin + if (arg'length /= result'length) then + report "FIXED_GENERIC_PKG.TO_SFIX (STD_LOGIC_VECTOR) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NASF; + else + result := to_sfixed (arg, result'high, result'low); + return result; + end if; + end function to_SFix; + + -- finding the bounds of a number. These functions can be used like this: + -- signal xxx : ufixed (7 downto -3); + -- -- Which is the same as "ufixed (UFix_high (11,3) downto UFix_low(11,3))" + -- signal yyy : ufixed (UFix_high (11, 3, "+", 11, 3) + -- downto UFix_low(11, 3, "+", 11, 3)); + -- Where "11" is the width of xxx (xxx'length), + -- and 3 is the lower bound (abs (xxx'low)) + -- In a pure VHDL environment use "ufixed_high" and "ufixed_low" + function ufix_high ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return ufixed_high (left_index => width - 1 - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - 1 - fraction2, + right_index2 => -fraction2); + end function ufix_high; + function ufix_low ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return ufixed_low (left_index => width - 1 - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - 1 - fraction2, + right_index2 => -fraction2); + end function ufix_low; + function sfix_high ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return sfixed_high (left_index => width - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - fraction2, + right_index2 => -fraction2); + end function sfix_high; + function sfix_low ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return sfixed_low (left_index => width - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - fraction2, + right_index2 => -fraction2); + end function sfix_low; + + function to_unsigned ( + arg : ufixed; -- ufixed point input + constant size : NATURAL; -- length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return UNSIGNED is + begin + return to_uns(resize (arg => arg, + left_index => size-1, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + end function to_unsigned; + + function to_unsigned ( + arg : ufixed; -- ufixed point input + size_res : UNSIGNED; -- length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return UNSIGNED is + begin + return to_unsigned (arg => arg, + size => size_res'length, + round_style => round_style, + overflow_style => overflow_style); + end function to_unsigned; + + function to_signed ( + arg : sfixed; -- ufixed point input + constant size : NATURAL; -- length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return SIGNED is + begin + return to_s(resize (arg => arg, + left_index => size-1, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + end function to_signed; + + function to_signed ( + arg : sfixed; -- ufixed point input + size_res : SIGNED; -- used for length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return SIGNED is + begin + return to_signed (arg => arg, + size => size_res'length, + round_style => round_style, + overflow_style => overflow_style); + end function to_signed; + + function to_real ( + arg : ufixed) -- ufixed point input + return REAL is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := arg'low; + variable result : REAL; -- result + variable arg_int : ufixed (left_index downto right_index); + begin + if (arg'length < 1) then + return 0.0; + end if; + arg_int := cleanvec(arg); + if (Is_X(arg_int)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_REAL: metavalue detected, returning 0.0" + severity warning; + return 0.0; + end if; + result := 0.0; + for i in arg_int'range loop + if (arg_int(i) = '1') then + result := result + (2.0**i); + end if; + end loop; + return result; + end function to_real; + + function to_real ( + arg : sfixed) -- ufixed point input + return REAL is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := arg'low; + variable result : REAL; -- result + variable arg_int : sfixed (left_index downto right_index); + -- unsigned version of argument + variable arg_uns : ufixed (left_index downto right_index); + -- absolute of argument + begin + if (arg'length < 1) then + return 0.0; + end if; + arg_int := cleanvec(arg); + if (Is_X(arg_int)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_REAL: metavalue detected, returning 0.0" + severity warning; + return 0.0; + end if; + arg_uns := abs(arg_int); + result := to_real (arg_uns); + if (arg_int(arg_int'high) = '1') then + result := -result; + end if; + return result; + end function to_real; + + function to_integer ( + arg : ufixed; -- fixed point input + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return NATURAL is + constant left_index : INTEGER := arg'high; + variable arg_uns : UNSIGNED (minimum(31, left_index+1) downto 0) + := (others => '0'); + begin + if (arg'length < 1) then + return 0; + end if; + if (Is_X (arg)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_INTEGER: metavalue detected, returning 0" + severity warning; + return 0; + end if; + if (left_index < -1) then + return 0; + end if; + arg_uns := to_uns(resize (arg => arg, + left_index => arg_uns'high, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + return to_integer (arg_uns); + end function to_integer; + + function to_integer ( + arg : sfixed; -- fixed point input + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return INTEGER is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := arg'low; + variable arg_s : SIGNED (minimum(31, left_index+1) downto 0); + begin + if (arg'length < 1) then + return 0; + end if; + if (Is_X (arg)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_INTEGER: metavalue detected, returning 0" + severity warning; + return 0; + end if; + if (left_index < -1) then + return 0; + end if; + arg_s := to_s(resize (arg => arg, + left_index => arg_s'high, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + return to_integer (arg_s); + end function to_integer; + + function to_01 ( + s : ufixed; -- ufixed point input + constant XMAP : STD_LOGIC := '0') -- Map x to + return ufixed is + variable result : ufixed (s'range); -- result + begin + for i in s'range loop + case s(i) is + when '0' | 'L' => result(i) := '0'; + when '1' | 'H' => result(i) := '1'; + when others => result(i) := XMAP; + end case; + end loop; + return result; + end function to_01; + + function to_01 ( + s : sfixed; -- ufixed point input + constant XMAP : STD_LOGIC := '0') -- Map x to + return sfixed is + variable result : sfixed (s'range); + begin + for i in s'range loop + case s(i) is + when '0' | 'L' => result(i) := '0'; + when '1' | 'H' => result(i) := '1'; + when others => result(i) := XMAP; + end case; + end loop; + return result; + end function to_01; + + function Is_X ( + arg : ufixed) + return BOOLEAN is + variable argslv : STD_LOGIC_VECTOR (arg'length-1 downto 0); -- slv + begin + argslv := to_slv(arg); + return Is_X(argslv); + end function Is_X; + + function Is_X ( + arg : sfixed) + return BOOLEAN is + variable argslv : STD_LOGIC_VECTOR (arg'length-1 downto 0); -- slv + begin + argslv := to_slv(arg); + return Is_X(argslv); + end function Is_X; + + function To_X01 ( + arg : ufixed) + return ufixed is + begin + return to_ufixed (To_X01(to_slv(arg)), arg'high, arg'low); + end function To_X01; + + function to_X01 ( + arg : sfixed) + return sfixed is + begin + return to_sfixed (To_X01(to_slv(arg)), arg'high, arg'low); + end function To_X01; + + function To_X01Z ( + arg : ufixed) + return ufixed is + begin + return to_ufixed (To_X01Z(to_slv(arg)), arg'high, arg'low); + end function To_X01Z; + + function to_X01Z ( + arg : sfixed) + return sfixed is + begin + return to_sfixed (To_X01Z(to_slv(arg)), arg'high, arg'low); + end function To_X01Z; + + function To_UX01 ( + arg : ufixed) + return ufixed is + begin + return to_ufixed (To_UX01(to_slv(arg)), arg'high, arg'low); + end function To_UX01; + + function to_UX01 ( + arg : sfixed) + return sfixed is + begin + return to_sfixed (To_UX01(to_slv(arg)), arg'high, arg'low); + end function To_UX01; + + + function resize ( + arg : ufixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return ufixed is + constant arghigh : INTEGER := maximum (arg'high, arg'low); + constant arglow : INTEGER := mine (arg'high, arg'low); + variable invec : ufixed (arghigh downto arglow); + variable result : ufixed(left_index downto right_index) := + (others => '0'); + variable needs_rounding : BOOLEAN := false; + begin -- resize + if (arg'length < 1) or (result'length < 1) then + return NAUF; + elsif (invec'length < 1) then + return result; -- string literal value + else + invec := cleanvec(arg); + if (right_index > arghigh) then -- return top zeros + needs_rounding := (round_style = fixed_round) and + (right_index = arghigh+1); + elsif (left_index < arglow) then -- return overflow + if (overflow_style = fixed_saturate) and + (or_reducex(to_slv(invec)) = '1') then + result := saturate (result'high, result'low); -- saturate + end if; + elsif (arghigh > left_index) then + -- wrap or saturate? + if (overflow_style and + or_reducex(to_slv(invec(arghigh downto left_index+1))) = '1') + then + result := saturate (result'high, result'low); -- saturate + else + if (arglow >= right_index) then + result (left_index downto arglow) := + invec(left_index downto arglow); + else + result (left_index downto right_index) := + invec (left_index downto right_index); + needs_rounding := (round_style = fixed_round); -- round + end if; + end if; + else -- arghigh <= integer width + if (arglow >= right_index) then + result (arghigh downto arglow) := invec; + else + result (arghigh downto right_index) := + invec (arghigh downto right_index); + needs_rounding := (round_style = fixed_round); -- round + end if; + end if; + -- Round result + if needs_rounding then + result := round_fixed (arg => result, + remainder => invec (right_index-1 + downto arglow), + overflow_style => overflow_style); + end if; + return result; + end if; + end function resize; + + function resize ( + arg : sfixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return sfixed is + constant arghigh : INTEGER := maximum (arg'high, arg'low); + constant arglow : INTEGER := mine (arg'high, arg'low); + variable invec : sfixed (arghigh downto arglow); + variable result : sfixed(left_index downto right_index) := + (others => '0'); + variable reduced : STD_ULOGIC; + variable needs_rounding : BOOLEAN := false; -- rounding + begin -- resize + if (arg'length < 1) or (result'length < 1) then + return NASF; + elsif (invec'length < 1) then + return result; -- string literal value + else + invec := cleanvec(arg); + if (right_index > arghigh) then -- return top zeros + if (arg'low /= INTEGER'low) then -- check for a literal + result := (others => arg(arghigh)); -- sign extend + end if; + needs_rounding := (round_style = fixed_round) and + (right_index = arghigh+1); + elsif (left_index < arglow) then -- return overflow + if (overflow_style) then + reduced := or_reducex(to_slv(invec)); + if (reduced = '1') then + if (invec(arghigh) = '0') then + -- saturate POSITIVE + result := saturate (result'high, result'low); + else + -- saturate negative + result := not saturate (result'high, result'low); + end if; + -- else return 0 (input was 0) + end if; + -- else return 0 (wrap) + end if; + elsif (arghigh > left_index) then + if (invec(arghigh) = '0') then + reduced := or_reducex(to_slv(invec(arghigh-1 downto + left_index))); + if overflow_style and reduced = '1' then + -- saturate positive + result := saturate (result'high, result'low); + else + if (right_index > arglow) then + result := invec (left_index downto right_index); + needs_rounding := (round_style = fixed_round); + else + result (left_index downto arglow) := + invec (left_index downto arglow); + end if; + end if; + else + reduced := and_reducex(to_slv(invec(arghigh-1 downto + left_index))); + if overflow_style and reduced = '0' then + result := not saturate (result'high, result'low); + else + if (right_index > arglow) then + result := invec (left_index downto right_index); + needs_rounding := (round_style = fixed_round); + else + result (left_index downto arglow) := + invec (left_index downto arglow); + end if; + end if; + end if; + else -- arghigh <= integer width + if (arglow >= right_index) then + result (arghigh downto arglow) := invec; + else + result (arghigh downto right_index) := + invec (arghigh downto right_index); + needs_rounding := (round_style = fixed_round); -- round + end if; + if (left_index > arghigh) then -- sign extend + result(left_index downto arghigh+1) := (others => invec(arghigh)); + end if; + end if; + -- Round result + if (needs_rounding) then + result := round_fixed (arg => result, + remainder => invec (right_index-1 + downto arglow), + overflow_style => overflow_style); + end if; + return result; + end if; + end function resize; + + -- size_res functions + -- These functions compute the size from a passed variable named "size_res" + -- The only part of this variable used it it's size, it is never passed + -- to a lower level routine. + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : ufixed) -- for size only + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : sfixed) -- for size only + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low); + return result; + end if; + end function to_sfixed; + + + function to_ufixed ( + arg : NATURAL; -- integer + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : INTEGER; -- integer + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_sfixed; + + function to_ufixed ( + arg : REAL; -- real + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + guard_bits => guard_bits, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : REAL; -- real + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + guard_bits => guard_bits, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_sfixed; + + function to_ufixed ( + arg : UNSIGNED; -- unsigned + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : SIGNED; -- signed + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_sfixed; + + function resize ( + arg : ufixed; -- input + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := resize (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function resize; + + function resize ( + arg : sfixed; -- input + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := resize (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function resize; + + -- Overloaded functions + function "+" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l + + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "+"; + + function "+" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + + r); + end function "+"; + + function "+" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l + + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "+"; + + function "+" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + + r); + end function "+"; + + -- Overloaded functions + function "-" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l - + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "-"; + + function "-" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + - r); + end function "-"; + + function "-" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l - + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "-"; + + function "-" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + - r); + end function "-"; + + -- Overloaded functions + function "*" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l * + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "*"; + + function "*" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + * r); + end function "*"; + + function "*" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l * + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "*"; + + function "*" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + * r); + end function "*"; + + -- Overloaded functions + function "/" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l / + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "/"; + + function "/" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + / r); + end function "/"; + + function "/" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l / + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "/"; + + function "/" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + / r); + end function "/"; + + -- Overloaded functions + function "rem" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l rem + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "rem"; + + function "rem" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + rem r); + end function "rem"; + + function "rem" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l rem + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "rem"; + + function "rem" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + rem r); + end function "rem"; + + function "mod" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l mod + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "mod"; + + function "mod" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + mod r); + end function "mod"; + + function "mod" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l mod + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "mod"; + + function "mod" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + mod r); + end function "mod"; + + -- Overloaded functions for integers + function "+" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); -- rounding not needed + end function "+"; + + function "+" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + + r); + end function "+"; + + function "+" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "+"; + + function "+" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + + r); + end function "+"; + + -- Overloaded functions + function "-" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l - to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "-"; + + function "-" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + - r); + end function "-"; + + function "-" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l - to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "-"; + + function "-" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + - r); + end function "-"; + + -- Overloaded functions + function "*" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l * to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "*"; + + function "*" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + * r); + end function "*"; + + function "*" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l * to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "*"; + + function "*" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + * r); + end function "*"; + + -- Overloaded functions + function "/" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l / to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "/"; + + function "/" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + / r); + end function "/"; + + function "/" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l / to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "/"; + + function "/" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + / r); + end function "/"; + + -- Overloaded functions + function "rem" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l rem to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "rem"; + + function "rem" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + rem r); + end function "rem"; + + function "rem" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l rem to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "rem"; + + function "rem" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + rem r); + end function "rem"; + + function "mod" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l mod to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "mod"; + + function "mod" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + mod r); + end function "mod"; + + function "mod" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l mod to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "mod"; + + function "mod" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + mod r); + end function "mod"; + + -- overloaded compare functions + function "=" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l = to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "="; + + function "/=" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l /= to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "/="; + + function ">=" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l >= to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function ">="; + + function "<=" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l <= to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "<="; + + function ">" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l > to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function ">"; + + function "<" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l < to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "<"; + + function "=" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + = r); + end function "="; + + function "/=" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + /= r); + end function "/="; + + function ">=" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + >= r); + end function ">="; + + function "<=" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + <= r); + end function "<="; + + function ">" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + > r); + end function ">"; + + function "<" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + < r); + end function "<"; + + function "=" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l = + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "="; + + function "/=" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l /= + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "/="; + + function ">=" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l >= + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function ">="; + + function "<=" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l <= + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "<="; + + function ">" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l > + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function ">"; + + function "<" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l < + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "<"; + + function "=" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + = r); + end function "="; + + function "/=" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + /= r); + end function "/="; + + function ">=" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + >= r); + end function ">="; + + function "<=" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + <= r); + end function "<="; + + function ">" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + > r); + end function ">"; + + function "<" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + < r); + end function "<"; + + function "=" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l = to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "="; + + function "/=" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l /= to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "/="; + + function ">=" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l >= to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function ">="; + + function "<=" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l <= to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "<="; + + function ">" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l > to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function ">"; + + function "<" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l < to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "<"; + + function "=" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + = r); + end function "="; + + function "/=" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + /= r); + end function "/="; + + function ">=" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + >= r); + end function ">="; + + function "<=" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + <= r); + end function "<="; + + function ">" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + > r); + end function ">"; + + function "<" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + < r); + end function "<"; + + function "=" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l = + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "="; + + function "/=" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l /= + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "/="; + + function ">=" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l >= + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function ">="; + + function "<=" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l <= + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "<="; + + function ">" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l > + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function ">"; + + function "<" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l < + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "<"; + + function "=" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + = r); + end function "="; + + function "/=" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + /= r); + end function "/="; + + function ">=" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + >= r); + end function ">="; + + function "<=" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + <= r); + end function "<="; + + function ">" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + > r); + end function ">"; + + function "<" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + < r); + end function "<"; + + -- rtl_synthesis off + -- synthesis translate_off + -- copied from std_logic_textio + type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', error); + type char_indexed_by_MVL9 is array (STD_ULOGIC) of CHARACTER; + type MVL9_indexed_by_char is array (CHARACTER) of STD_ULOGIC; + type MVL9plus_indexed_by_char is array (CHARACTER) of MVL9plus; + + constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-"; + constant char_to_MVL9 : MVL9_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); + constant char_to_MVL9plus : MVL9plus_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => error); + constant NBSP : CHARACTER := CHARACTER'val(160); -- space character + constant NUS : STRING(2 to 1) := (others => ' '); + + -- purpose: writes fixed point into a line + procedure write ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + variable s : STRING(1 to value'length +1) := (others => ' '); + variable sindx : INTEGER; + begin -- function write Example: 0011.1100 + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx +1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx +1; + end loop; + write(l, s, justified, field); + end procedure write; + + -- purpose: writes fixed point into a line + procedure write ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + variable s : STRING(1 to value'length +1); + variable sindx : INTEGER; + begin -- function write Example: 0011.1100 + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx +1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx +1; + end loop; + write(l, s, justified, field); + end procedure write; + + procedure READ(L : inout LINE; + VALUE : out ufixed) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable s : STRING(1 to value'length-1); + variable readOk : BOOLEAN; + variable i : INTEGER; -- index variable + begin -- READ + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + i := value'high; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + report "FIXED_GENERIC_PKG.READ(ufixed) " + & "Error: end of string encountered" + severity error; + return; + elsif c = ' ' or c = NBSP or c = HT then -- reading done. + assert i = value'low + report "FIXED_GENERIC_PKG.READ(ufixed) " + & "Warning: Value truncated " severity warning; + return; + elsif c = '.' then -- separator, ignore + assert (i = -1) + report "FIXED_GENERIC_PKG.READ(ufixed) " + & "Warning: Decimal point does not match number format " + severity warning; + elsif (char_to_MVL9plus(c) = error) then + report "FIXED_GENERIC_PKG.READ(ufixed) " + & "Error: Character '" & c & "' read, expected STD_ULOGIC literal." + severity error; + return; + else + value (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + return; + end if; + end if; + read(l, c, readOk); + end loop readloop; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable i : INTEGER; -- index variable + variable readOk : BOOLEAN; + begin -- READ + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + i := value'high; + good := true; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + good := false; + return; + elsif c = ' ' or c = NBSP or c = HT then -- reading done + good := false; + return; + elsif c = '.' then -- separator, ignore + good := (i = -1); + elsif (char_to_MVL9plus(c) = error) then + good := false; + return; + else + value (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + return; + end if; + end if; + read(l, c, readOk); + end loop readloop; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out sfixed) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable readOk : BOOLEAN; + variable i : INTEGER; -- index variable + begin -- READ + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + i := value'high; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + report "FIXED_GENERIC_PKG.READ(sfixed) " + & "Error end of string encountered" + severity error; + return; + elsif c = ' ' or c = NBSP or c = HT then -- reading done. + assert i = value'low + report "FIXED_GENERIC_PKG.READ(sfixed) " + & "Warning: Value truncated " severity warning; + return; + elsif c = '.' then -- separator, ignore + assert (i = -1) + report "FIXED_GENERIC_PKG.READ(sfixed) " + & "Warning: Decimal point does not match number format " + severity warning; + elsif (char_to_MVL9plus(c) = error) then + report "FIXED_GENERIC_PKG.READ(sfixed) " + & "Error: Character '" & c & "' read, expected STD_ULOGIC literal." + severity error; + return; + else + value (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + return; + end if; + end if; + read(l, c, readOk); + end loop readloop; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable i : INTEGER; -- index variable + variable readOk : BOOLEAN; + begin -- READ + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + i := value'high; + good := true; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + good := false; + return; + elsif c = ' ' or c = NBSP or c = HT then -- reading done + good := false; + return; + elsif c = '.' then -- separator, ignore + good := (i = -1); + elsif (char_to_MVL9plus(c) = error) then + good := false; + return; + else + value (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + return; + end if; + end if; + read(l, c, readOk); + end loop readloop; + end procedure READ; + + -- octal read and write + procedure owrite ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_ostring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure owrite; + + procedure owrite ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_ostring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure owrite; + + procedure Char2TriBits (C : CHARACTER; + RESULT : out STD_LOGIC_VECTOR(2 downto 0); + GOOD : out BOOLEAN; + ISSUE_ERROR : in BOOLEAN) is + begin + case c is + when '0' => result := o"0"; good := true; + when '1' => result := o"1"; good := true; + when '2' => result := o"2"; good := true; + when '3' => result := o"3"; good := true; + when '4' => result := o"4"; good := true; + when '5' => result := o"5"; good := true; + when '6' => result := o"6"; good := true; + when '7' => result := o"7"; good := true; + when 'Z' => result := "ZZZ"; good := true; + when 'X' => result := "XXX"; good := true; + when others => + assert not ISSUE_ERROR + report + "FIXED_GENERIC_PKG.OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + result := "UUU"; + good := false; + end case; + end procedure Char2TriBits; + + -- Note that for Octal and Hex read, you can not start with a ".", + -- the read is for numbers formatted "A.BC". These routines go to + -- the nearest bounds, so "F.E" will fit into an sfixed (2 downto -3). + procedure OREAD(L : inout LINE; + VALUE : out ufixed) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + report "FIXED_GENERIC_PKG.OREAD(ufixed): " + & "Error end of string encountered" + severity error; + return; + else + Char2triBits(c, nybble, igood, true); + i := hbv-lbv - 3; -- Top - 3 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood = false then + report "FIXED_GENERIC_PKG.OREAD(ufixed): " + & "Error end of string encountered" + severity error; + elsif (c = '.') then + if (i + 1 /= -lbv) then + igood := false; + report "FIXED_GENERIC_PKG.OREAD(ufixed): " + & "encountered ""."" at wrong index" + severity error; + end if; + else + Char2TriBits(c, nybble, igood, true); + slv (i downto i-2) := nybble; + i := i - 3; + end if; + end loop; + if igood then -- We did not get another error + assert (i = -1) and -- We read everything, and high bits 0 + (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') + report "FIXED_GENERIC_PKG.OREAD(ufixed): Vector truncated." + severity error; + if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "FIXED_GENERIC_PKG.OREAD(ufixed): Vector truncated" + severity warning; + end if; + end if; + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + return; + else + Char2triBits(c, nybble, igood, false); + i := hbv-lbv - 3; -- Top - 3 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood then + if (c = '.') then + igood := igood and (i + 1 = -lbv); + else + Char2TriBits(c, nybble, igood, false); + slv (i downto i-2) := nybble; + i := i - 3; + end if; + end if; + end loop; + good := igood and -- We did not get another error + (i = -1) and -- We read everything, and high bits 0 + (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0'); + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out sfixed) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + report "FIXED_GENERIC_PKG.OREAD(sfixed): " + & "Error end of string encountered" + severity error; + return; + else + Char2triBits(c, nybble, igood, true); + i := hbv-lbv - 3; -- Top - 3 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood = false then + report "FIXED_GENERIC_PKG.OREAD(sfixed): " + & "Error end of string encountered" + severity error; + elsif (c = '.') then + if (i + 1 /= -lbv) then + igood := false; + report "FIXED_GENERIC_PKG.OREAD(sfixed): " + & "encountered ""."" at wrong index" + severity error; + end if; + else + Char2TriBits(c, nybble, igood, true); + slv (i downto i-2) := nybble; + i := i - 3; + end if; + end loop; + if igood then -- We did not get another error + assert (i = -1) and -- We read everything + ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')) + report "FIXED_GENERIC_PKG.OREAD(sfixed): Vector truncated." + severity error; + if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "FIXED_GENERIC_PKG.OREAD(sfixed): Vector truncated" + severity warning; + end if; + end if; + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + return; + else + Char2triBits(c, nybble, igood, false); + i := hbv-lbv - 3; -- Top - 3 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood then + if (c = '.') then + igood := igood and (i + 1 = -lbv); + else + Char2TriBits(c, nybble, igood, false); + slv (i downto i-2) := nybble; + i := i - 3; + end if; + end if; + end loop; + good := igood -- We did not get another error + and (i = -1) -- We read everything + and ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')); + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure OREAD; + + -- hex read and write + procedure hwrite ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_hstring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure hwrite; + + -- purpose: writes fixed point into a line + procedure hwrite ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_hstring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure hwrite; + + -- Hex Read and Write procedures for STD_ULOGIC_VECTOR. + -- Modified from the original to be more forgiving. + + procedure Char2QuadBits (C : CHARACTER; + RESULT : out STD_LOGIC_VECTOR(3 downto 0); + GOOD : out BOOLEAN; + ISSUE_ERROR : in BOOLEAN) is + begin + case c is + when '0' => result := x"0"; good := true; + when '1' => result := x"1"; good := true; + when '2' => result := x"2"; good := true; + when '3' => result := x"3"; good := true; + when '4' => result := x"4"; good := true; + when '5' => result := x"5"; good := true; + when '6' => result := x"6"; good := true; + when '7' => result := x"7"; good := true; + when '8' => result := x"8"; good := true; + when '9' => result := x"9"; good := true; + when 'A' | 'a' => result := x"A"; good := true; + when 'B' | 'b' => result := x"B"; good := true; + when 'C' | 'c' => result := x"C"; good := true; + when 'D' | 'd' => result := x"D"; good := true; + when 'E' | 'e' => result := x"E"; good := true; + when 'F' | 'f' => result := x"F"; good := true; + when 'Z' => result := "ZZZZ"; good := true; + when 'X' => result := "XXXX"; good := true; + when others => + assert not ISSUE_ERROR + report + "FIXED_GENERIC_PKG.HREAD Error: Read a '" & c & + "', expected a Hex character (0-F)." + severity error; + result := "UUUU"; + good := false; + end case; + end procedure Char2QuadBits; + + procedure HREAD(L : inout LINE; + VALUE : out ufixed) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + report "FIXED_GENERIC_PKG.HREAD(ufixed): " + & "Error end of string encountered" + severity error; + return; + else + Char2QuadBits(c, nybble, igood, true); + i := hbv-lbv - 4; -- Top - 4 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood = false then + report "FIXED_GENERIC_PKG.HREAD(ufixed): " + & "Error end of string encountered" + severity error; + elsif (c = '.') then + if (i + 1 /= -lbv) then + igood := false; + report "FIXED_GENERIC_PKG.HREAD(ufixed): " + & "encountered ""."" at wrong index" + severity error; + end if; + else + Char2QuadBits(c, nybble, igood, true); + slv (i downto i-3) := nybble; + i := i - 4; + end if; + end loop; + if igood then -- We did not get another error + assert (i = -1) and -- We read everything, and high bits 0 + (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') + report "FIXED_GENERIC_PKG.HREAD(ufixed): Vector truncated." + severity error; + if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "FIXED_GENERIC_PKG.HREAD(ufixed): Vector truncated" + severity warning; + end if; + end if; + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + return; + else + Char2QuadBits(c, nybble, igood, false); + i := hbv-lbv - 4; -- Top - 4 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood then + if (c = '.') then + igood := igood and (i + 1 = -lbv); + else + Char2QuadBits(c, nybble, igood, false); + slv (i downto i-3) := nybble; + i := i - 4; + end if; + end if; + end loop; + good := igood and -- We did not get another error + (i = -1) and -- We read everything, and high bits 0 + (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0'); + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out sfixed) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + report "FIXED_GENERIC_PKG.HREAD(sfixed): " + & "Error end of string encountered" + severity error; + return; + else + Char2QuadBits(c, nybble, igood, true); + i := hbv-lbv - 4; -- Top - 4 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood = false then + report "FIXED_GENERIC_PKG.HREAD(sfixed): " + & "Error end of string encountered" + severity error; + elsif (c = '.') then + if (i + 1 /= -lbv) then + igood := false; + report "FIXED_GENERIC_PKG.HREAD(sfixed): " + & "encountered ""."" at wrong index" + severity error; + end if; + else + Char2QuadBits(c, nybble, igood, true); + slv (i downto i-3) := nybble; + i := i - 4; + end if; + end loop; + if igood then -- We did not get another error + assert (i = -1) -- We read everything + and ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')) + report "FIXED_GENERIC_PKG.HREAD(sfixed): Vector truncated." + severity error; + if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "FIXED_GENERIC_PKG.HREAD(sfixed): Vector truncated" + severity warning; + end if; + end if; + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + return; + else + Char2QuadBits(c, nybble, igood, false); + i := hbv-lbv - 4; -- Top - 4 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood then + if (c = '.') then + igood := igood and (i + 1 = -lbv); + else + Char2QuadBits(c, nybble, igood, false); + slv (i downto i-3) := nybble; + i := i - 4; + end if; + end if; + end loop; + good := igood and -- We did not get another error + (i = -1) and -- We read everything + ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')); + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure HREAD; + + ----------------------------------------------------------------------------- + -- %%% Remove the following 3 functions. They are a duplicate needed for + -- testing + ----------------------------------------------------------------------------- + -- purpose: Justify a string to the right + function justify ( + value : STRING; + justified : SIDE := right; + field : width := 0) + return STRING is + constant VAL_LEN : INTEGER := value'length; + variable result : STRING (1 to field) := (others => ' '); + begin -- function justify + -- return value if field is too small + if VAL_LEN >= field then + return value; + end if; + if justified = left then + result(1 to VAL_LEN) := value; + elsif justified = right then + result(field - VAL_LEN + 1 to field) := value; + end if; + return result; + end function justify; + + function to_ostring ( + value : STD_LOGIC_VECTOR; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant ne : INTEGER := (value'length+2)/3; + variable pad : STD_LOGIC_VECTOR(0 to (ne*3 - value'length) - 1); + variable ivalue : STD_LOGIC_VECTOR(0 to ne*3 - 1); + variable result : STRING(1 to ne); + variable tri : STD_LOGIC_VECTOR(0 to 2); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + tri := To_X01Z(ivalue(3*i to 3*i+2)); + case tri is + when o"0" => result(i+1) := '0'; + when o"1" => result(i+1) := '1'; + when o"2" => result(i+1) := '2'; + when o"3" => result(i+1) := '3'; + when o"4" => result(i+1) := '4'; + when o"5" => result(i+1) := '5'; + when o"6" => result(i+1) := '6'; + when o"7" => result(i+1) := '7'; + when "ZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_ostring; + ------------------------------------------------------------------- + function to_hstring ( + value : STD_LOGIC_VECTOR; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant ne : INTEGER := (value'length+3)/4; + variable pad : STD_LOGIC_VECTOR(0 to (ne*4 - value'length) - 1); + variable ivalue : STD_LOGIC_VECTOR(0 to ne*4 - 1); + variable result : STRING(1 to ne); + variable quad : STD_LOGIC_VECTOR(0 to 3); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + quad := To_X01Z(ivalue(4*i to 4*i+3)); + case quad is + when x"0" => result(i+1) := '0'; + when x"1" => result(i+1) := '1'; + when x"2" => result(i+1) := '2'; + when x"3" => result(i+1) := '3'; + when x"4" => result(i+1) := '4'; + when x"5" => result(i+1) := '5'; + when x"6" => result(i+1) := '6'; + when x"7" => result(i+1) := '7'; + when x"8" => result(i+1) := '8'; + when x"9" => result(i+1) := '9'; + when x"A" => result(i+1) := 'A'; + when x"B" => result(i+1) := 'B'; + when x"C" => result(i+1) := 'C'; + when x"D" => result(i+1) := 'D'; + when x"E" => result(i+1) := 'E'; + when x"F" => result(i+1) := 'F'; + when "ZZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_hstring; + -- %%% End remove here + + function to_string ( + value : ufixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + variable s : STRING(1 to value'length +1) := (others => ' '); + variable sindx : INTEGER; + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_string (resize (value, 0, value'low), justified, field); + elsif value'low > 0 then + return to_string (resize (value, value'high, -1), justified, field); + else + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx +1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx +1; + end loop; + return justify(s, justified, field); + end if; + end if; + end function to_string; + + function to_string ( + value : sfixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + variable s : STRING(1 to value'length +1) := (others => ' '); + variable sindx : INTEGER; + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_string (resize (value, 0, value'low), justified, field); + elsif value'low > 0 then + return to_string (resize (value, value'high, -1), justified, field); + else + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx +1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx +1; + end loop; + return justify(s, justified, field); + end if; + end if; + end function to_string; + + function to_ostring ( + value : ufixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant lne : INTEGER := (-VALUE'low+2)/3; + constant lpad : STD_LOGIC_VECTOR (0 to (lne*3 + VALUE'low) -1) := + (others => '0'); + variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_ostring (resize (value, 2, value'low), justified, field); + elsif value'low > 0 then + return to_ostring (resize (value, value'high, -3), justified, field); + else + slv := to_slv (value); + return justify(to_ostring(slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_ostring(slv(slv'high-VALUE'high-1 downto 0)&lpad), + justified, field); + end if; + end if; + end function to_ostring; + + function to_hstring ( + value : ufixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant lne : INTEGER := (-VALUE'low+3)/4; + constant lpad : STD_LOGIC_VECTOR (0 to (lne*4 + VALUE'low) -1) := + (others => '0'); + variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_hstring (resize (value, 3, value'low), justified, field); + elsif value'low > 0 then + return to_hstring (resize (value, value'high, -4), justified, field); + else + slv := to_slv (value); + return justify(to_hstring(slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_hstring(slv(slv'high-VALUE'high-1 downto 0)&lpad), + justified, field); + end if; + end if; + end function to_hstring; + + function to_ostring ( + value : sfixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant ne : INTEGER := ((value'high+1)+2)/3; + variable pad : STD_LOGIC_VECTOR(0 to (ne*3 - (value'high+1)) - 1); + constant lne : INTEGER := (-VALUE'low+2)/3; + constant lpad : STD_LOGIC_VECTOR (0 to (lne*3 + VALUE'low) -1) := + (others => '0'); + variable slv : STD_LOGIC_VECTOR (VALUE'high - VALUE'low downto 0); + begin + if value'length < 1 then + return NUS; + else + pad := (others => value(value'high)); + if value'high < 0 then + return to_ostring (resize (value, 2, value'low), justified, field); + elsif value'low > 0 then + return to_ostring (resize (value, value'high, -3), justified, field); + else + slv := to_slv (value); + return justify(to_ostring(pad + & slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_ostring(slv(slv'high-VALUE'high-1 downto 0) + & lpad), + justified, field); + end if; + end if; + end function to_ostring; + + function to_hstring ( + value : sfixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant ne : INTEGER := ((value'high+1)+3)/4; + variable pad : STD_LOGIC_VECTOR(0 to (ne*4 - (value'high+1)) - 1); + constant lne : INTEGER := (-VALUE'low+3)/4; + constant lpad : STD_LOGIC_VECTOR (0 to (lne*4 + VALUE'low) -1) := + (others => '0'); + variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); + begin + if value'length < 1 then + return NUS; + else + pad := (others => value(value'high)); + if value'high < 0 then + return to_hstring (resize (value, 3, value'low), justified, field); + elsif value'low > 0 then + return to_hstring (resize (value, value'high, -4), justified, field); + else + slv := to_slv (value); + return justify(to_hstring(pad&slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_hstring(slv(slv'high-VALUE'high-1 downto 0)&lpad), + justified, field); + end if; + end if; + end function to_hstring; + + -- From string functions allow you to convert a string into a fixed + -- point number. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100", uf1'high, uf1'low); -- 6.5 + -- The "." is optional in this syntax, however it exist and is + -- in the wrong location an error is produced. Overflow will + -- result in saturation. + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + variable result : ufixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + read (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + return result; + end function from_string; + + -- Octal and hex conversions work as follows: + -- uf1 <= from_hstring ("6.8", 3, -3); -- 6.5 (bottom zeros dropped) + -- uf1 <= from_ostring ("06.4", 3, -3); -- 6.5 (top zeros dropped) + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + variable result : ufixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + oread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + variable result : ufixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + hread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + return result; + end function from_hstring; + + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable result : sfixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + read (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + return result; + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable result : sfixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + oread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable result : sfixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + hread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + return result; + end function from_hstring; + + -- Same as above, "size_res" is used for it's range only. + function from_string ( + bstring : STRING; -- binary string + size_res : ufixed) + return ufixed is + variable result : ufixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + read (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + return result; + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : ufixed) + return ufixed is + variable result : ufixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + oread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : ufixed) + return ufixed is + variable result : ufixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + hread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + return result; + end function from_hstring; + + function from_string ( + bstring : STRING; -- binary string + size_res : sfixed) + return sfixed is + variable result : sfixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + read (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + return result; + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : sfixed) + return sfixed is + variable result : sfixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + oread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : sfixed) + return sfixed is + variable result : sfixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + hread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + return result; + end function from_hstring; + + -- purpose: find a dot in a string, return -1 if no dot (internal function) + function finddot ( + arg : STRING) + return INTEGER is + alias xarg : STRING (arg'length downto 1) is arg; -- make it a downto + begin + for i in xarg'reverse_range loop + if (xarg(i) = '.') then + return i-1; + end if; + end loop; + return -1; + end function finddot; + + -- Direct converstion functions. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100"); -- 6.5 + -- In this case the "." is not optional, and the size of + -- the output must match exactly. + function from_string ( + bstring : STRING) -- binary string + return ufixed is + variable result : ufixed (bstring'length-2 downto 0); + variable result_nodot : ufixed (bstring'length-1 downto 0); + variable bstring_nodot : STRING (1 to bstring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(bstring); + if (dot = -1) then + L := new STRING'(bstring); + read (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + deallocate (L); + return result_nodot; + else + j := 1; + for i in 1 to bstring'high loop + if (bstring(i) /= '.') then + bstring_nodot(j) := bstring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(bstring_nodot); + read (L, result, good); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + deallocate (L); + return to_ufixed(to_slv(result), bstring'length-dot-2, -dot); + end if; + end function from_string; + + -- Direct octal and hex converstion functions. In this case + -- the string lengths must match. Example: + -- signal sf1 := sfixed (5 downto -3); + -- sf1 <= from_ostring ("71.4") -- -6.5 + function from_ostring ( + ostring : STRING) -- Octal string + return ufixed is + variable result : STD_LOGIC_VECTOR((ostring'length-1)*3-1 downto 0); + variable result_nodot : STD_LOGIC_VECTOR((ostring'length)*3-1 downto 0); + variable ostring_nodot : STRING (1 to ostring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(ostring); + if (dot = -1) then + L := new STRING'(ostring); + oread (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + deallocate (L); + return to_ufixed(UNSIGNED(result_nodot)); + else + j := 1; + for i in 1 to ostring'high loop + if (ostring(i) /= '.') then + ostring_nodot(j) := ostring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(ostring_nodot); + oread (L, result, good); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + deallocate (L); + return to_ufixed(result, (ostring'length-1-dot)*3-1, -dot*3); + end if; + end function from_ostring; + + function from_hstring ( + hstring : STRING) -- hex string + return ufixed is + variable result : STD_LOGIC_VECTOR((hstring'length-1)*4-1 downto 0); + variable result_nodot : STD_LOGIC_VECTOR((hstring'length)*4-1 downto 0); + variable hstring_nodot : STRING (1 to hstring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(hstring); + if (dot = -1) then + L := new STRING'(hstring); + hread (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + deallocate (L); + return to_ufixed(UNSIGNED(result_nodot)); + else + j := 1; + for i in 1 to hstring'high loop + if (hstring(i) /= '.') then + hstring_nodot(j) := hstring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(hstring_nodot); + hread (L, result, good); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + deallocate (L); + return to_ufixed(result, (hstring'length-1-dot)*4-1, -dot*4); + end if; + end function from_hstring; + + function from_string ( + bstring : STRING) -- binary string + return sfixed is + variable result : sfixed (bstring'length-2 downto 0); + variable result_nodot : sfixed (bstring'length-1 downto 0); + variable bstring_nodot : STRING (1 to bstring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(bstring); + if (dot = -1) then + L := new STRING'(bstring); + read (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + deallocate (L); + return result_nodot; + else + j := 1; + for i in 1 to bstring'high loop + if (bstring(i) /= '.') then + bstring_nodot(j) := bstring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(bstring_nodot); + read (L, result, good); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + deallocate (L); + return to_sfixed(to_slv(result), bstring'length-dot-2, -dot); + end if; + end function from_string; + + function from_ostring ( + ostring : STRING) -- Octal string + return sfixed is + variable result : STD_LOGIC_VECTOR((ostring'length-1)*3-1 downto 0); + variable result_nodot : STD_LOGIC_VECTOR((ostring'length)*3-1 downto 0); + variable ostring_nodot : STRING (1 to ostring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(ostring); + if (dot = -1) then + L := new STRING'(ostring); + oread (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + deallocate (L); + return to_sfixed(SIGNED(result_nodot)); + else + j := 1; + for i in 1 to ostring'high loop + if (ostring(i) /= '.') then + ostring_nodot(j) := ostring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(ostring_nodot); + oread (L, result, good); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + deallocate (L); + return to_sfixed(result, (ostring'length-1-dot)*3-1, -dot*3); + end if; + end function from_ostring; + + function from_hstring ( + hstring : STRING) -- hex string + return sfixed is + variable result : STD_LOGIC_VECTOR((hstring'length-1)*4-1 downto 0); + variable result_nodot : STD_LOGIC_VECTOR((hstring'length)*4-1 downto 0); + variable hstring_nodot : STRING (1 to hstring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(hstring); + if (dot = -1) then + L := new STRING'(hstring); + hread (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + deallocate (L); + return sfixed(SIGNED(result_nodot)); + else + j := 1; + for i in 1 to hstring'high loop + if (hstring(i) /= '.') then + hstring_nodot(j) := hstring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(hstring_nodot); + hread (L, result, good); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + deallocate (L); + return to_sfixed(result, (hstring'length-1-dot)*4-1, -dot*4); + end if; + end function from_hstring; + +-- synthesis translate_on +-- rtl_synthesis on + function to_StdLogicVector ( + arg : ufixed) -- fp vector + return STD_LOGIC_VECTOR is + begin + return to_slv (arg); + end function to_StdLogicVector; + function to_Std_Logic_Vector ( + arg : ufixed) -- fp vector + return STD_LOGIC_VECTOR is + begin + return to_slv (arg); + end function to_Std_Logic_Vector; + function to_StdLogicVector ( + arg : sfixed) -- fp vector + return STD_LOGIC_VECTOR is + begin + return to_slv (arg); + end function to_StdLogicVector; + function to_Std_Logic_Vector ( + arg : sfixed) -- fp vector + return STD_LOGIC_VECTOR is + begin + return to_slv (arg); + end function to_Std_Logic_Vector; + function to_StdULogicVector ( + arg : ufixed) -- fp vector + return STD_ULOGIC_VECTOR is + begin + return to_sulv (arg); + end function to_StdULogicVector; + function to_Std_ULogic_Vector ( + arg : ufixed) -- fp vector + return STD_ULOGIC_VECTOR is + begin + return to_sulv (arg); + end function to_Std_ULogic_Vector; + function to_StdULogicVector ( + arg : sfixed) -- fp vector + return STD_ULOGIC_VECTOR is + begin + return to_sulv (arg); + end function to_StdULogicVector; + function to_Std_ULogic_Vector ( + arg : sfixed) -- fp vector + return STD_ULOGIC_VECTOR is + begin + return to_sulv (arg); + end function to_Std_ULogic_Vector; +end package body fixed_pkg; + +