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