OpenCores
URL https://opencores.org/ocsvn/fixed_extensions/fixed_extensions/trunk

Subversion Repositories fixed_extensions

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /fixed_extensions
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/bench/vhdl/testrounding_tb.vhd
0,0 → 1,66
-- File automatically generated by "cdfg2hdl".
-- Filename: testrounding_tb.vhd
-- Date: 28 April 2011 02:50:35 PM
-- Author: Nikolaos Kavvadias (C) 2009, 2010
 
library IEEE, STD;
use STD.textio.all;
use IEEE.numeric_std.all;
use WORK.fixed_float_types.all;
use WORK.fixed_pkg.all;
use WORK.fixed_extensions_pkg.all;
use IEEE.std_logic_1164.all;
 
entity testrounding_tb is
end testrounding_tb;
 
architecture tb_arch of testrounding_tb is
component testrounding
port (
clk : in std_logic;
reset : in std_logic;
start : in std_logic;
ok : out sfixed(3 downto -4)
);
end component;
signal clk : std_logic;
signal reset : std_logic;
signal start : std_logic;
signal ok : sfixed(3 downto -4);
-- Profiling signals
signal ncycles : integer;
-- Constant declarations
constant CLK_PERIOD : time := 10 ns;
begin
uut : testrounding
port map (
clk => clk,
reset => reset,
start => start,
ok => ok
);
CLK_GEN_PROC: process(clk)
begin
if (clk = 'U') then
clk <= '1';
else
clk <= not clk after CLK_PERIOD/2;
end if;
end process CLK_GEN_PROC;
 
RESET_START_STIM: process
begin
reset <= '1';
start <= '0';
wait for CLK_PERIOD;
reset <= '0';
start <= '1';
wait for 2000*CLK_PERIOD;
-- Automatic end of the current simulation.
assert false
report "NONE. End simulation time reached"
severity failure;
end process RESET_START_STIM;
 
end tb_arch;
trunk/bench/vhdl/testrounding_tb.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/rtl/vhdl/fixed_extensions_pkg_sim.vhd =================================================================== --- trunk/rtl/vhdl/fixed_extensions_pkg_sim.vhd (nonexistent) +++ trunk/rtl/vhdl/fixed_extensions_pkg_sim.vhd (revision 2) @@ -0,0 +1,456 @@ +-------------------------------------------------------------------------------- +-- Filename: fixed_extensions_pkg_sim.vhd +-- Purpose : Package adding various extensions to the VHDL-2008 (VHDL'93, 2002 +-- compatibility versions) fixed-point arithmetic package by David +-- Bishop. +-- Supported operators: +-- * ceil : round towards plus infinity. +-- * fix : round towards zero. +-- * floor : round towards minus infinity. +-- * round : round to nearest; ties to greatest absolute value. +-- * nearest : round to nearest; ties to plus infinity. +-- * convergent: round to nearest; ties to closest even. +-- * bitinsert : bit-field insertion to word +-- * bitextract: bit-field extraction from word +-- +-- Author : Nikolaos Kavvadias (C) 2011 +-- Date : 25-Jul-2011 +-- Revision: 0.0.0 (01/05/11) +-- Initial version. Supports ceil, fix, floor, round, nearest, +-- convergent based on their MATLAB documentation. +-- 0.0.1 (03/05/11) +-- Added bitinsert. +-- 0.0.2 (16/07/11) +-- Added bitextract (sfixed, ufixed), bitinsert (ufixed). Commented +-- non-synthesizable part (assertions) of bitinsert. +-- 0.0.3 (19/07/11) +-- Fixed ceil bug with rounding integral (zero fractional part) +-- values. +-- 0.0.4 (21/07/11) +-- Fixed more bugs regarding fix, round and convergent. +-- 0.0.5 (25/07/11) +-- Design edited for simulation-oriented use. +-------------------------------------------------------------------------------- + +use STD.TEXTIO.all; +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.all; +--library IEEE_PROPOSED; +--use IEEE_PROPOSED.fixed_float_types.all; +--use IEEE_PROPOSED.fixed_pkg.all; +--use WORK.fixed_float_types.all; +use WORK.fixed_pkg.all; + +package fixed_extensions_pkg is + + function ceil (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function ceil (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function fix (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function fix (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function floor (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function floor (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function round (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function round (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function nearest (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function nearest (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function convergent (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function convergent (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function bitinsert (a, y0 : UNRESOLVED_sfixed; bhi, blo : std_logic_vector) return UNRESOLVED_sfixed; + function bitinsert (a, y0 : UNRESOLVED_ufixed; bhi, blo : std_logic_vector) return UNRESOLVED_ufixed; + function bitextract (a : UNRESOLVED_sfixed; bhi, blo : std_logic_vector) return UNRESOLVED_sfixed; + function bitextract (a : UNRESOLVED_ufixed; bhi, blo : std_logic_vector) return UNRESOLVED_ufixed; + +end package fixed_extensions_pkg; + +--library IEEE; +--use IEEE.MATH_REAL.all; +--use WORK.MATH_REAL.all; + +package body fixed_extensions_pkg is + + -- ceil: round towards plus infinity. + function ceil ( + arg : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (arg'high downto arg'low); + variable fract_zero : std_logic_vector(-arg'low-1 downto 0) := (others => '0'); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + if (to_slv(arg(-1 downto arg'low)) = fract_zero) then + result := arg; + else + result := arg + 1; + end if; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function ceil; + + -- ceil: round towards plus infinity. + function ceil ( + arg : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (arg'high downto arg'low); + variable fract_zero : std_logic_vector(-arg'low-1 downto 0) := (others => '0'); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + if (to_slv(arg(-1 downto arg'low)) = fract_zero) then + result := arg; + else + result := arg + 1; + end if; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function ceil; + + -- fix: round towards zero. + function fix ( + arg : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (arg'high downto arg'low); + variable fract_zero : std_logic_vector(-arg'low-1 downto 0) := (others => '0'); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + if (is_negative(arg)) then + if (to_slv(arg(-1 downto arg'low)) = fract_zero) then + result := arg; + else + result := arg + 1; + end if; + else + result := arg; + end if; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function fix; + + -- fix: round towards zero. + function fix ( + arg : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (arg'high downto arg'low); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + result := arg; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function fix; + + -- floor: round towards minus infinity. + function floor ( + arg : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (arg'high downto arg'low); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + result := arg; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function floor; + + -- floor: round towards plus infinity. + function floor ( + arg : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (arg'high downto arg'low); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + result := arg; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function floor; + + -- round: round to nearest; ties to greatest absolute value. + function round ( + arg : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (arg'high downto arg'low); + variable onehalf_vec : std_logic_vector(-arg'low-1 downto 0) := (others => '0'); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + onehalf_vec(-arg'low-1) := '1'; + if (is_negative(arg)) then + if (to_slv(arg(-1 downto arg'low)) > onehalf_vec) then + result := arg + 1; + else + result := arg; + end if; + else + if (to_slv(arg(-1 downto arg'low)) >= onehalf_vec) then + result := arg + 1; + else + result := arg; + end if; + end if; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function round; + + -- round: round to nearest; ties to greatest absolute value. + function round ( + arg : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (arg'high downto arg'low); + variable onehalf_vec : std_logic_vector(-arg'low-1 downto 0) := (others => '0'); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + onehalf_vec(-arg'low-1) := '1'; + if (to_slv(arg(-1 downto arg'low)) >= onehalf_vec) then + result := arg + 1; + else + result := arg; + end if; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function round; + + -- nearest: round to nearest; ties to plus infinity. + function nearest ( + arg : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (arg'high downto arg'low); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + if (arg(-1) = '1') then + result := arg + 1; + else + result := arg; + end if; + result(-1 downto arg'low) := (others => '0'); + else + result := arg; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function nearest; + + -- nearest: round to nearest; ties to plus infinity. + function nearest ( + arg : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (arg'high downto arg'low); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + if (arg(-1) = '1') then + result := arg + 1; + else + result := arg; + end if; + result(-1 downto arg'low) := (others => '0'); + else + result := arg; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function nearest; + + -- convergent: round to nearest; ties to closest even. + function convergent ( + arg : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (arg'high downto arg'low); + variable onehalf_vec : std_logic_vector(-arg'low-1 downto 0) := (others => '0'); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + onehalf_vec(-arg'low-1) := '1'; + if (arg(0) = '1') then + if (to_slv(arg(-1 downto arg'low)) >= onehalf_vec) then + result := arg + 1; + else + result := arg; + end if; + else + if (to_slv(arg(-1 downto arg'low)) > onehalf_vec) then + result := arg + 1; + else + result := arg; + end if; + end if; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function convergent; + + -- convergent: round to nearest; ties to closest even. + function convergent ( + arg : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (arg'high downto arg'low); + variable onehalf_vec : std_logic_vector(-arg'low-1 downto 0) := (others => '0'); + begin + if (arg'high <= 0) then + result := (others => '0'); + return result; + end if; + if (arg'low > 0) then + result := arg; + return result; + end if; + if (arg'low < 0) then + onehalf_vec(-arg'low-1) := '1'; + if (arg(0) = '1') then + if (to_slv(arg(-1 downto arg'low)) >= onehalf_vec) then + result := arg + 1; + else + result := arg; + end if; + else + if (to_slv(arg(-1 downto arg'low)) > onehalf_vec) then + result := arg + 1; + else + result := arg; + end if; + end if; + result(-1 downto arg'low) := (others => '0'); + end if; + return result; + end function convergent; + + function bitinsert (a, y0 : UNRESOLVED_sfixed; bhi, blo : std_logic_vector) return UNRESOLVED_sfixed is + variable y : UNRESOLVED_sfixed(a'RANGE); + begin +-- if (bhi < blo) then +-- assert false +-- report "Error: Invalid range for bitfield insert." +-- severity failure; +-- end if; +-- if (to_integer(signed(bhi)) > y'HIGH) then +-- assert false +-- report "Error: High bound (bhi) is out of result range." +-- severity failure; +-- end if; +-- if (to_integer(signed(blo)) < y'LOW) then +-- assert false +-- report "Error: Low bound (blo) is out of result range." +-- severity failure; +-- end if; + y := y0; + y(to_integer(signed(bhi)) downto to_integer(signed(blo))) := + a(to_integer(signed(bhi))-to_integer(signed(blo)) downto a'LOW); + return (y); + end bitinsert; + + function bitinsert (a, y0 : UNRESOLVED_ufixed; bhi, blo : std_logic_vector) return UNRESOLVED_ufixed is + variable y : UNRESOLVED_ufixed(a'RANGE); + begin + y := y0; + y(to_integer(signed(bhi)) downto to_integer(signed(blo))) := + a(to_integer(signed(bhi))-to_integer(signed(blo)) downto a'LOW); + return (y); + end bitinsert; + + function bitextract (a : UNRESOLVED_sfixed; bhi, blo : std_logic_vector) return UNRESOLVED_sfixed is + variable y : sfixed(a'HIGH downto a'LOW); + begin + y := a; + y(to_integer(signed(bhi))-to_integer(signed(blo)) downto a'LOW) := + a(to_integer(signed(bhi)) downto to_integer(signed(blo))); + return (y); + end bitextract; + + function bitextract (a : UNRESOLVED_ufixed; bhi, blo : std_logic_vector) return UNRESOLVED_ufixed is + variable y : ufixed(a'HIGH downto a'LOW); + begin + y := a; + y(to_integer(signed(bhi))-to_integer(signed(blo)) downto a'LOW) := + a(to_integer(signed(bhi)) downto to_integer(signed(blo))); + return (y); + end bitextract; + +end package body fixed_extensions_pkg;
trunk/rtl/vhdl/fixed_extensions_pkg_sim.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/doc/COPYING.BSD =================================================================== --- trunk/doc/COPYING.BSD (nonexistent) +++ trunk/doc/COPYING.BSD (revision 2) @@ -0,0 +1,31 @@ +*** MODIFIED BSD LICENSE +=============================================================================== + +Copyright (c) 2011, Nikolaos Kavvadias +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "Nikolaos Kavvadias" nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
trunk/doc/COPYING.BSD Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/doc/BUGS =================================================================== --- trunk/doc/BUGS (nonexistent) +++ trunk/doc/BUGS (revision 2) @@ -0,0 +1,11 @@ +fixed_extensions BUGS -- known bugs. Last updated: 2011-07-25 + +Known bugs in fixed_extensions-0.0.5 +------------------------------------ + + ** + - + - + + +BUGS ends here.
trunk/doc/BUGS Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/doc/VERSION =================================================================== --- trunk/doc/VERSION (nonexistent) +++ trunk/doc/VERSION (revision 2) @@ -0,0 +1 @@ +0.0.5
trunk/doc/VERSION Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/doc/AUTHORS =================================================================== --- trunk/doc/AUTHORS (nonexistent) +++ trunk/doc/AUTHORS (revision 2) @@ -0,0 +1,5 @@ +Authors of fixed_extensions. + +fixed_extensions Nikolaos Kavvadias + +AUTHORS ends here
trunk/doc/AUTHORS Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/doc/TODO =================================================================== --- trunk/doc/TODO (nonexistent) +++ trunk/doc/TODO (revision 2) @@ -0,0 +1,8 @@ +fixed_extensions --- TODO + +Todo: + + * Add more bit-manipulation operators for fixed-point arithmetic. + * Test with GHDL (has some problems with s/ufixed entity ports. + +end of file TODO
trunk/doc/TODO Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog (nonexistent) +++ trunk/doc/ChangeLog (revision 2) @@ -0,0 +1,5 @@ +2011-07-25 Nikolaos Kavvadias + + * First release 0.0.5. + +ChangeLog ends here
trunk/doc/ChangeLog Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/doc/THANKS =================================================================== --- trunk/doc/THANKS (nonexistent) +++ trunk/doc/THANKS (revision 2) @@ -0,0 +1,7 @@ +Thanks to: + + X.Y. for whatever. + + +Thessaloniki, Greece, 2011-07-25 +
trunk/doc/THANKS Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/doc/README =================================================================== --- trunk/doc/README (nonexistent) +++ trunk/doc/README (revision 2) @@ -0,0 +1,103 @@ +------------------------------------------------------------------------------ +-- Title : fixed_extensions (VHDL fixed-point arithmetic -- +-- : extensions package). -- +-- Author : Nikolaos Kavvadias -- +-- Contact : nikolaos.kavvadias@gmail.com -- +-- : http://www.nkavvadias.com -- +-- Release Date : 25 July 2011 -- +-- Version : 0.0.5 -- +--------------------:--------------------------------------------------------- +-- Revision history : -- +-- v0.0.5 : 2011-07-25 -- +-- : Initial release. -- +------------------------------------------------------------------------------ + + +1. INTRODUCTION +--------------- + +"fixed_extensions_pkg" is a fixed-point arithmetic package written in VHDL +according to the VHDL-2008 update of the standard. It uses VHDL-2008 back- +compatible libraries (by David Bishop) that are included in this distribution +for the sake of completeness. + +Currently, the "fixed_extensions_pkg" package implements the following: + + - ceil : round towards plus infinity. + - fix : round towards zero. + - floor : round towards minus infinity. + - round : round to nearest; ties to greatest absolute value. + - nearest : round to nearest; ties to plus infinity. + - convergent: round to nearest; ties to closest even. + - bitinsert : bit-field insertion to word + - bitextract: bit-field extraction from word + +"fixed_extensions" is distributed along with a tool (gentestround) to generate +customized VHDL test designs. + + +2. FILE LISTING +--------------- + + The fixed_extensions distributions includes the following files: + + /fixed_extensions- + /bench/vhdl + testrounding_tb.vhd Standard testbench file. + /doc + AUTHORS List of "fixed_extensions" authors. + BUGS Bug list. + ChangeLog A log for code changes. + COPYING.BSD The Modified BSD License. + README This file. + THANKS Acknowledgements. + TODO A list of future enhancements. + /gen/vhdl + testroundings.vhd Auto-generated test file for sfixed arithmetic. + testroundingu.vhd Auto-generated test file for ufixed arithmetic. + /rtl/vhdl + fixed_extensions_pkg_sim.vhd + The VHDL package for simulation-oriented use. + fixed_extensions_pkg_synth.vhd + The VHDL package for synthesis-oriented use. + /sim/rtl_sim/bin + run.sh A bash script for testing the package. + testroundings.do Modelsim macro script for testing sfixed arithmetic. + testroundings.sh Bash script for running an sfixed simulation. + testroundingu.do Modelsim macro script for testing ufixed arithmetic. + testroundingu.sh Bash script for running an ufixed simulation. + /sim/rtl_sim/src + fixed_float_types_custom.vhd + VHDL package with definitions for fixed-point arith. + fixed_pkg_c.vhd VHDL package implementing fixed-point arithmetic. + math_real.vhd VHDL package with some real arithmetic functions. + /sw + gentestround.c Test design generator written in ANSI C. + Makefile Makefile for compiling the test design generator. + + +3. FIXED_EXTENSIONS USAGE +------------------------- + + The fixed_extensions package can be used as follows: + $./run.sh + + +4. PREREQUISITIES +----------------- + +- Standard UNIX-based tools (tested on cygwin/x86) + make, bash +- [optional] Mentor Modelsim ("mti") (http://www.mentor.com) + Provides a simulation environment to run the tests. + + +5. CONTACT +---------- + +You may contact me for further questions/suggestions/corrections at: + + Nikolaos Kavvadias + + + http://www.nkavvadias.com
trunk/doc/README Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/sim/rtl_sim/src/fixed_float_types_custom.vhd =================================================================== --- trunk/sim/rtl_sim/src/fixed_float_types_custom.vhd (nonexistent) +++ trunk/sim/rtl_sim/src/fixed_float_types_custom.vhd (revision 2) @@ -0,0 +1,23 @@ +-- File automatically generated by "cdfg2hdl". +-- Filename: fixed_float_types_custom.vhd +-- Date: 29 April 2011 05:52:35 PM +-- Author: Nikolaos Kavvadias (C) 2009, 2010, 2011 + +package fixed_float_types is + -- Types used for generics of fixed_generic_pkg + type fixed_round_style_type is (fixed_round, fixed_truncate); + type fixed_overflow_style_type is (fixed_saturate, fixed_wrap); + type round_type is (round_nearest, -- Default, nearest LSB '0' + round_inf, -- Round toward positive infinity + round_neginf, -- Round toward negative infinity + round_zero); -- Round toward zero (truncate) + + -- Rounding routine to use in fixed point, fixed_round or fixed_truncate + constant fixed_round_style : fixed_round_style_type := fixed_truncate; + -- Overflow routine to use in fixed point, fixed_saturate or fixed_wrap + constant fixed_overflow_style : fixed_overflow_style_type := fixed_wrap; + -- Extra bits used in divide routines + constant fixed_guard_bits : NATURAL := 3; + -- If TRUE, then turn off warnings on "X" propagation + constant no_warning : BOOLEAN := (false); +end package fixed_float_types;
trunk/sim/rtl_sim/src/fixed_float_types_custom.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/sim/rtl_sim/src/fixed_pkg_c.vhd =================================================================== --- trunk/sim/rtl_sim/src/fixed_pkg_c.vhd (nonexistent) +++ trunk/sim/rtl_sim/src/fixed_pkg_c.vhd (revision 2) @@ -0,0 +1,8389 @@ +-- -------------------------------------------------------------------- +-- "fixed_pkg_c.vhdl" package contains functions for fixed point math. +-- Please see the documentation for the fixed point package. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee.std_logic_1164.all; +-- use ieee.numeric_std.all; +-- use ieee_proposed.fixed_float_types.all; +-- use ieee_proposed.fixed_pkg.all; +-- +-- This verison is designed to work with the VHDL-93 compilers +-- synthesis tools. Please note the "%%%" comments. These are where we +-- diverge from the VHDL-200X LRM. +-- -------------------------------------------------------------------- +-- Version : $Revision: 1.21 $ +-- Date : $Date: 2007/09/26 18:08:53 $ +-- -------------------------------------------------------------------- + +use STD.TEXTIO.all; +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.all; +use work.fixed_float_types.all; + +package fixed_pkg is +-- generic ( + -- Rounding routine to use in fixed point, fixed_round or fixed_truncate + constant fixed_round_style : fixed_round_style_type := fixed_round; + -- Overflow routine to use in fixed point, fixed_saturate or fixed_wrap + constant fixed_overflow_style : fixed_overflow_style_type := fixed_saturate; + -- Extra bits used in divide routines + constant fixed_guard_bits : NATURAL := 3; + -- If TRUE, then turn off warnings on "X" propagation + constant no_warning : BOOLEAN := (false + ); + + -- Author David Bishop (dbishop@vhdl.org) + + -- base Unsigned fixed point type, downto direction assumed + type UNRESOLVED_ufixed is array (INTEGER range <>) of STD_ULOGIC; + -- base Signed fixed point type, downto direction assumed + type UNRESOLVED_sfixed is array (INTEGER range <>) of STD_ULOGIC; + + subtype U_ufixed is UNRESOLVED_ufixed; + subtype U_sfixed is UNRESOLVED_sfixed; + + subtype ufixed is UNRESOLVED_ufixed; + subtype sfixed is UNRESOLVED_sfixed; + + --=========================================================================== + -- Arithmetic Operators: + --=========================================================================== + + -- Absolute value, 2's complement + -- abs sfixed(a downto b) = sfixed(a+1 downto b) + function "abs" (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Negation, 2's complement + -- - sfixed(a downto b) = sfixed(a+1 downto b) + function "-" (arg : UNRESOLVED_sfixed)return UNRESOLVED_sfixed; + + -- Addition + -- ufixed(a downto b) + ufixed(c downto d) + -- = ufixed(maximum(a,c)+1 downto minimum(b,d)) + function "+" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed(a downto b) + sfixed(c downto d) + -- = sfixed(maximum(a,c)+1 downto minimum(b,d)) + function "+" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Subtraction + -- ufixed(a downto b) - ufixed(c downto d) + -- = ufixed(maximum(a,c)+1 downto minimum(b,d)) + function "-" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed(a downto b) - sfixed(c downto d) + -- = sfixed(maximum(a,c)+1 downto minimum(b,d)) + function "-" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Multiplication + -- ufixed(a downto b) * ufixed(c downto d) = ufixed(a+c+1 downto b+d) + function "*" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed(a downto b) * sfixed(c downto d) = sfixed(a+c+1 downto b+d) + function "*" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Division + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) +-- function "/" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) +-- function "/" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Remainder + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (minimum(a,c) downto minimum(b,d)) +-- function "rem" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (minimum(a,c) downto minimum(b,d)) +-- function "rem" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Modulo + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (minimum(a,c) downto minimum(b, d)) +-- function "mod" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto minimum(b, d)) +-- function "mod" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + ---------------------------------------------------------------------------- + -- In these routines the "real" or "natural" (integer) + -- are converted into a fixed point number and then the operation is + -- performed. It is assumed that the array will be large enough. + -- If the input is "real" then the real number is converted into a fixed of + -- the same size as the fixed point input. If the number is an "integer" + -- then it is converted into fixed with the range (l'high downto 0). + ---------------------------------------------------------------------------- + + -- ufixed(a downto b) + ufixed(a downto b) = ufixed(a+1 downto b) + function "+" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + + -- ufixed(c downto d) + ufixed(c downto d) = ufixed(c+1 downto d) + function "+" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) + ufixed(a downto 0) = ufixed(a+1 downto minimum(0,b)) + function "+" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + + -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto minimum(0,d)) + function "+" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) - ufixed(a downto b) = ufixed(a+1 downto b) + function "-" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + + -- ufixed(c downto d) - ufixed(c downto d) = ufixed(c+1 downto d) + function "-" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) - ufixed(a downto 0) = ufixed(a+1 downto minimum(0,b)) + function "-" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + + -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto minimum(0,d)) + function "-" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) * ufixed(a downto b) = ufixed(2a+1 downto 2b) + function "*" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + + -- ufixed(c downto d) * ufixed(c downto d) = ufixed(2c+1 downto 2d) + function "*" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) + function "*" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + + -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) + function "*" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) +-- function "/" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + +-- -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) +-- function "/" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed(a downto b) / ufixed(a downto 0) = ufixed(a downto b-a-1) +-- function "/" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + + -- ufixed(c downto 0) / ufixed(c downto d) = ufixed(c-d downto -c-1) +-- function "/" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- ufixed (a downto b) rem ufixed (a downto b) = ufixed (a downto b) +-- function "rem" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + +-- -- ufixed (c downto d) rem ufixed (c downto d) = ufixed (c downto d) +-- function "rem" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + +-- -- ufixed (a downto b) rem ufixed (a downto 0) = ufixed (a downto minimum(b,0)) +-- function "rem" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + +-- -- ufixed (c downto 0) rem ufixed (c downto d) = ufixed (c downto minimum(d,0)) +-- function "rem" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + +-- -- ufixed (a downto b) mod ufixed (a downto b) = ufixed (a downto b) +-- function "mod" (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + +-- -- ufixed (c downto d) mod ufixed (c downto d) = ufixed (c downto d) +-- function "mod" (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + +-- -- ufixed (a downto b) mod ufixed (a downto 0) = ufixed (a downto minimum(b,0)) +-- function "mod" (l : UNRESOLVED_ufixed; r : NATURAL) return UNRESOLVED_ufixed; + +-- -- ufixed (c downto 0) mod ufixed (c downto d) = ufixed (c downto minimum(d,0)) +-- function "mod" (l : NATURAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + + -- sfixed(a downto b) + sfixed(a downto b) = sfixed(a+1 downto b) + function "+" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + + -- sfixed(c downto d) + sfixed(c downto d) = sfixed(c+1 downto d) + function "+" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) + sfixed(a downto 0) = sfixed(a+1 downto minimum(0,b)) + function "+" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + + -- sfixed(c downto 0) + sfixed(c downto d) = sfixed(c+1 downto minimum(0,d)) + function "+" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) - sfixed(a downto b) = sfixed(a+1 downto b) + function "-" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + + -- sfixed(c downto d) - sfixed(c downto d) = sfixed(c+1 downto d) + function "-" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) - sfixed(a downto 0) = sfixed(a+1 downto minimum(0,b)) + function "-" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + + -- sfixed(c downto 0) - sfixed(c downto d) = sfixed(c+1 downto minimum(0,d)) + function "-" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) * sfixed(a downto b) = sfixed(2a+1 downto 2b) + function "*" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + + -- sfixed(c downto d) * sfixed(c downto d) = sfixed(2c+1 downto 2d) + function "*" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) * sfixed(a downto 0) = sfixed(2a+1 downto b) + function "*" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + + -- sfixed(c downto 0) * sfixed(c downto d) = sfixed(2c+1 downto d) + function "*" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) / sfixed(a downto b) = sfixed(a-b+1 downto b-a) +-- function "/" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + + -- sfixed(c downto d) / sfixed(c downto d) = sfixed(c-d+1 downto d-c) +-- function "/" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed(a downto b) / sfixed(a downto 0) = sfixed(a+1 downto b-a) +-- function "/" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + + -- sfixed(c downto 0) / sfixed(c downto d) = sfixed(c-d+1 downto -c) +-- function "/" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- sfixed (a downto b) rem sfixed (a downto b) = sfixed (a downto b) +-- function "rem" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + +-- -- sfixed (c downto d) rem sfixed (c downto d) = sfixed (c downto d) +-- function "rem" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + +-- -- sfixed (a downto b) rem sfixed (a downto 0) = sfixed (a downto minimum(b,0)) +-- function "rem" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + +-- -- sfixed (c downto 0) rem sfixed (c downto d) = sfixed (c downto minimum(d,0)) +-- function "rem" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + +-- -- sfixed (a downto b) mod sfixed (a downto b) = sfixed (a downto b) +-- function "mod" (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + +-- -- sfixed (c downto d) mod sfixed (c downto d) = sfixed (c downto d) +-- function "mod" (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + +-- -- sfixed (a downto b) mod sfixed (a downto 0) = sfixed (a downto minimum(b,0)) +-- function "mod" (l : UNRESOLVED_sfixed; r : INTEGER) return UNRESOLVED_sfixed; + +-- -- sfixed (c downto 0) mod sfixed (c downto d) = sfixed (c downto minimum(d,0)) +-- function "mod" (l : INTEGER; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- This version of divide gives the user more control + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) +-- function divide ( +-- l, r : UNRESOLVED_ufixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed; + + -- This version of divide gives the user more control + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) +-- function divide ( +-- l, r : UNRESOLVED_sfixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed; + + -- These functions return 1/X + -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) +-- function reciprocal ( +-- arg : UNRESOLVED_ufixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed; + + -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) +-- function reciprocal ( +-- arg : UNRESOLVED_sfixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed; + + -- REM function + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (minimum(a,c) downto minimum(b,d)) +-- function remainder ( +-- l, r : UNRESOLVED_ufixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed; + + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (minimum(a,c) downto minimum(b,d)) +-- function remainder ( +-- l, r : UNRESOLVED_sfixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed; + + -- mod function + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (minimum(a,c) downto minimum(b, d)) +-- function modulo ( +-- l, r : UNRESOLVED_ufixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto minimum(b, d)) +-- function modulo ( +-- l, r : UNRESOLVED_sfixed; +-- constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed; + + -- Procedure for those who need an "accumulator" function. + -- add_carry (ufixed(a downto b), ufixed (c downto d)) + -- = ufixed (maximum(a,c) downto minimum(b,d)) + procedure add_carry ( + L, R : in UNRESOLVED_ufixed; + c_in : in STD_ULOGIC; + result : out UNRESOLVED_ufixed; + c_out : out STD_ULOGIC); + + -- add_carry (sfixed(a downto b), sfixed (c downto d)) + -- = sfixed (maximum(a,c) downto minimum(b,d)) + procedure add_carry ( + L, R : in UNRESOLVED_sfixed; + c_in : in STD_ULOGIC; + result : out UNRESOLVED_sfixed; + c_out : out STD_ULOGIC); + + -- Scales the result by a power of 2. Width of input = width of output with + -- the binary point moved. + function scalb (y : UNRESOLVED_ufixed; N : INTEGER) return UNRESOLVED_ufixed; + function scalb (y : UNRESOLVED_ufixed; N : SIGNED) return UNRESOLVED_ufixed; + function scalb (y : UNRESOLVED_sfixed; N : INTEGER) return UNRESOLVED_sfixed; + function scalb (y : UNRESOLVED_sfixed; N : SIGNED) return UNRESOLVED_sfixed; + + function Is_Negative (arg : UNRESOLVED_sfixed) return BOOLEAN; + + --=========================================================================== + -- Comparison Operators + --=========================================================================== + + function ">" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function ">" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + function "<" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function "<" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + function "<=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function "<=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + function ">=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function ">=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + function "=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function "=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + function "/=" (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function "/=" (l, r : UNRESOLVED_sfixed) return BOOLEAN; + + function \?=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?/=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<=\ (l, r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?/=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<=\ (l, r : UNRESOLVED_sfixed) return STD_ULOGIC; + + function std_match (l, r : UNRESOLVED_ufixed) return BOOLEAN; + function std_match (l, r : UNRESOLVED_sfixed) return BOOLEAN; + + -- Overloads the default "maximum" and "minimum" function + + function maximum (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function minimum (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function maximum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function minimum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + ---------------------------------------------------------------------------- + -- In these compare functions a natural is converted into a + -- fixed point number of the bounds "maximum(l'high,0) downto 0" + ---------------------------------------------------------------------------- + + function "=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + function "/=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + function ">=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + function "<=" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + function ">" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + function "<" (l : UNRESOLVED_ufixed; r : NATURAL) return BOOLEAN; + + function "=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "/=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function ">=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "<=" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function ">" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "<" (l : NATURAL; r : UNRESOLVED_ufixed) return BOOLEAN; + + function \?=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + function \?/=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + function \?>=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + function \?<=\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + function \?>\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + function \?<\ (l : UNRESOLVED_ufixed; r : NATURAL) return STD_ULOGIC; + + function \?=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?/=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<=\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<\ (l : NATURAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + + function maximum (l : UNRESOLVED_ufixed; r : NATURAL) + return UNRESOLVED_ufixed; + function minimum (l : UNRESOLVED_ufixed; r : NATURAL) + return UNRESOLVED_ufixed; + function maximum (l : NATURAL; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function minimum (l : NATURAL; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + ---------------------------------------------------------------------------- + -- In these compare functions a real is converted into a + -- fixed point number of the bounds "l'high+1 downto l'low" + ---------------------------------------------------------------------------- + + function "=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + function "/=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + function ">=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + function "<=" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + function ">" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + function "<" (l : UNRESOLVED_ufixed; r : REAL) return BOOLEAN; + + function "=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "/=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function ">=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "<=" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function ">" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + function "<" (l : REAL; r : UNRESOLVED_ufixed) return BOOLEAN; + + function \?=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + function \?/=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + function \?>=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + function \?<=\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + function \?>\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + function \?<\ (l : UNRESOLVED_ufixed; r : REAL) return STD_ULOGIC; + + function \?=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?/=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<=\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?>\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + function \?<\ (l : REAL; r : UNRESOLVED_ufixed) return STD_ULOGIC; + + function maximum (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + function maximum (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function minimum (l : UNRESOLVED_ufixed; r : REAL) return UNRESOLVED_ufixed; + function minimum (l : REAL; r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + ---------------------------------------------------------------------------- + -- In these compare functions an integer is converted into a + -- fixed point number of the bounds "maximum(l'high,1) downto 0" + ---------------------------------------------------------------------------- + + function "=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + function "/=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + function ">=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + function "<=" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + function ">" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + function "<" (l : UNRESOLVED_sfixed; r : INTEGER) return BOOLEAN; + + function "=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + function "/=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + function ">=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + function "<=" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + function ">" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + function "<" (l : INTEGER; r : UNRESOLVED_sfixed) return BOOLEAN; + + function \?=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + function \?/=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + function \?>=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + function \?<=\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + function \?>\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + function \?<\ (l : UNRESOLVED_sfixed; r : INTEGER) return STD_ULOGIC; + + function \?=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?/=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<=\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<\ (l : INTEGER; r : UNRESOLVED_sfixed) return STD_ULOGIC; + + function maximum (l : UNRESOLVED_sfixed; r : INTEGER) + return UNRESOLVED_sfixed; + function maximum (l : INTEGER; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function minimum (l : UNRESOLVED_sfixed; r : INTEGER) + return UNRESOLVED_sfixed; + function minimum (l : INTEGER; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + ---------------------------------------------------------------------------- + -- In these compare functions a real is converted into a + -- fixed point number of the bounds "l'high+1 downto l'low" + ---------------------------------------------------------------------------- + + function "=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + function "/=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + function ">=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + function "<=" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + function ">" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + function "<" (l : UNRESOLVED_sfixed; r : REAL) return BOOLEAN; + + function "=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + function "/=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + function ">=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + function "<=" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + function ">" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + function "<" (l : REAL; r : UNRESOLVED_sfixed) return BOOLEAN; + + function \?=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + function \?/=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + function \?>=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + function \?<=\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + function \?>\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + function \?<\ (l : UNRESOLVED_sfixed; r : REAL) return STD_ULOGIC; + + function \?=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?/=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<=\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?>\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + function \?<\ (l : REAL; r : UNRESOLVED_sfixed) return STD_ULOGIC; + + function maximum (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + function maximum (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function minimum (l : UNRESOLVED_sfixed; r : REAL) return UNRESOLVED_sfixed; + function minimum (l : REAL; r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + --=========================================================================== + -- Shift and Rotate Functions. + -- Note that sra and sla are not the same as the BIT_VECTOR version + --=========================================================================== + + function "sll" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "srl" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "rol" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "ror" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "sla" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "sra" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed; + function "sll" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function "srl" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function "rol" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function "ror" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function "sla" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function "sra" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed; + function SHIFT_LEFT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) + return UNRESOLVED_ufixed; + function SHIFT_RIGHT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) + return UNRESOLVED_ufixed; + function SHIFT_LEFT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) + return UNRESOLVED_sfixed; + function SHIFT_RIGHT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) + return UNRESOLVED_sfixed; + + ---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + + function "not" (l : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "and" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "or" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "nand" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "nor" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "xor" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "xnor" (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function "not" (l : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "and" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "or" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "nand" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "nor" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "xor" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function "xnor" (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- Vector and std_ulogic functions, same as functions in numeric_std + function "and" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "and" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "or" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "or" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "nand" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "nand" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "nor" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "nor" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "xor" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "xor" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "xnor" (l : STD_ULOGIC; r : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + function "xnor" (l : UNRESOLVED_ufixed; r : STD_ULOGIC) + return UNRESOLVED_ufixed; + function "and" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "and" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + function "or" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "or" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + function "nand" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "nand" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + function "nor" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "nor" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + function "xor" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "xor" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + function "xnor" (l : STD_ULOGIC; r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + function "xnor" (l : UNRESOLVED_sfixed; r : STD_ULOGIC) + return UNRESOLVED_sfixed; + + -- Reduction operators, same as numeric_std functions + function and_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function nand_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function or_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function nor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function xor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function xnor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC; + function and_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + function nand_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + function or_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + function nor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + function xor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + function xnor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC; + + -- returns arg'low-1 if not found + function find_leftmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) + return INTEGER; + function find_leftmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) + return INTEGER; + + -- returns arg'high+1 if not found + function find_rightmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) + return INTEGER; + function find_rightmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) + return INTEGER; + + --=========================================================================== + -- RESIZE Functions + --=========================================================================== + -- resizes the number (larger or smaller) + -- The returned result will be ufixed (left_index downto right_index) + -- If "round_style" is fixed_round, then the result will be rounded. + -- If the MSB of the remainder is a "1" AND the LSB of the unrounded result + -- is a '1' or the lower bits of the remainder include a '1' then the result + -- will be increased by the smallest representable number for that type. + -- "overflow_style" can be fixed_saturate or fixed_wrap. + -- In saturate mode, if the number overflows then the largest possible + -- representable number is returned. If wrap mode, then the upper bits + -- of the number are truncated. + + function resize ( + arg : UNRESOLVED_ufixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + -- "size_res" functions create the size of the output from the indices + -- of the "size_res" input. The actual value of "size_res" is not used. + function resize ( + arg : UNRESOLVED_ufixed; -- input + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + -- Note that in "wrap" mode the sign bit is not replicated. Thus the + -- resize of a negative number can have a positive result in wrap mode. + function resize ( + arg : UNRESOLVED_sfixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + function resize ( + arg : UNRESOLVED_sfixed; -- input + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + --=========================================================================== + -- Conversion Functions + --=========================================================================== + + -- integer (natural) to unsigned fixed point. + -- arguments are the upper and lower bounds of the number, thus + -- ufixed (7 downto -3) <= to_ufixed (int, 7, -3); + function to_ufixed ( + arg : NATURAL; -- integer + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + function to_ufixed ( + arg : NATURAL; -- integer + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + -- real to unsigned fixed point + function to_ufixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return UNRESOLVED_ufixed; + + function to_ufixed ( + arg : REAL; -- real + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return UNRESOLVED_ufixed; + + -- unsigned to unsigned fixed point + function to_ufixed ( + arg : UNSIGNED; -- unsigned + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + function to_ufixed ( + arg : UNSIGNED; -- unsigned + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed; + + -- Performs a conversion. ufixed (arg'range) is returned + function to_ufixed ( + arg : UNSIGNED) -- unsigned + return UNRESOLVED_ufixed; + + -- unsigned fixed point to unsigned + function to_unsigned ( + arg : UNRESOLVED_ufixed; -- fixed point input + constant size : NATURAL; -- length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNSIGNED; + + -- unsigned fixed point to unsigned + function to_unsigned ( + arg : UNRESOLVED_ufixed; -- fixed point input + size_res : UNSIGNED; -- used for length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNSIGNED; + + -- unsigned fixed point to real + function to_real ( + arg : UNRESOLVED_ufixed) -- fixed point input + return REAL; + + -- unsigned fixed point to integer + function to_integer ( + arg : UNRESOLVED_ufixed; -- fixed point input + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return NATURAL; + + -- Integer to UNRESOLVED_sfixed + function to_sfixed ( + arg : INTEGER; -- integer + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + function to_sfixed ( + arg : INTEGER; -- integer + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + -- Real to sfixed + function to_sfixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return UNRESOLVED_sfixed; + + function to_sfixed ( + arg : REAL; -- real + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return UNRESOLVED_sfixed; + + -- signed to sfixed + function to_sfixed ( + arg : SIGNED; -- signed + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + function to_sfixed ( + arg : SIGNED; -- signed + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed; + + -- signed to sfixed (output assumed to be size of signed input) + function to_sfixed ( + arg : SIGNED) -- signed + return UNRESOLVED_sfixed; + + -- Conversion from ufixed to sfixed + function to_sfixed ( + arg : UNRESOLVED_ufixed) + return UNRESOLVED_sfixed; + + -- signed fixed point to signed + function to_signed ( + arg : UNRESOLVED_sfixed; -- fixed point input + constant size : NATURAL; -- length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return SIGNED; + + -- signed fixed point to signed + function to_signed ( + arg : UNRESOLVED_sfixed; -- fixed point input + size_res : SIGNED; -- used for length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return SIGNED; + + -- signed fixed point to real + function to_real ( + arg : UNRESOLVED_sfixed) -- fixed point input + return REAL; + + -- signed fixed point to integer + function to_integer ( + arg : UNRESOLVED_sfixed; -- fixed point input + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return INTEGER; + + -- Because of the fairly complicated sizing rules in the fixed point + -- packages these functions are provided to compute the result ranges + -- Example: + -- signal uf1 : ufixed (3 downto -3); + -- signal uf2 : ufixed (4 downto -2); + -- signal uf1multuf2 : ufixed (ufixed_high (3, -3, '*', 4, -2) downto + -- ufixed_low (3, -3, '*', 4, -2)); + -- uf1multuf2 <= uf1 * uf2; + -- Valid characters: '+', '-', '*', '/', 'r' or 'R' (rem), 'm' or 'M' (mod), + -- '1' (reciprocal), 'a' or 'A' (abs), 'n' or 'N' (unary -) + function ufixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + + function ufixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + + function sfixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + + function sfixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + + -- Same as above, but using the "size_res" input only for their ranges: + -- signal uf1multuf2 : ufixed (ufixed_high (uf1, '*', uf2) downto + -- ufixed_low (uf1, '*', uf2)); + -- uf1multuf2 <= uf1 * uf2; + -- + function ufixed_high (size_res : UNRESOLVED_ufixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_ufixed) + return INTEGER; + + function ufixed_low (size_res : UNRESOLVED_ufixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_ufixed) + return INTEGER; + + function sfixed_high (size_res : UNRESOLVED_sfixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_sfixed) + return INTEGER; + + function sfixed_low (size_res : UNRESOLVED_sfixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_sfixed) + return INTEGER; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + + function saturate ( + size_res : UNRESOLVED_ufixed) -- only the size of this is used + return UNRESOLVED_ufixed; + + function saturate ( + size_res : UNRESOLVED_sfixed) -- only the size of this is used + return UNRESOLVED_sfixed; + + --=========================================================================== + -- Translation Functions + --=========================================================================== + + -- maps meta-logical values + function to_01 ( + s : UNRESOLVED_ufixed; -- fixed point input + constant XMAP : STD_ULOGIC := '0') -- Map x to + return UNRESOLVED_ufixed; + + -- maps meta-logical values + function to_01 ( + s : UNRESOLVED_sfixed; -- fixed point input + constant XMAP : STD_ULOGIC := '0') -- Map x to + return UNRESOLVED_sfixed; + + function Is_X (arg : UNRESOLVED_ufixed) return BOOLEAN; + function Is_X (arg : UNRESOLVED_sfixed) return BOOLEAN; + function to_X01 (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function to_X01 (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function to_X01Z (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function to_X01Z (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + function to_UX01 (arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed; + function to_UX01 (arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed; + + -- straight vector conversion routines, needed for synthesis. + -- These functions are here so that a std_logic_vector can be + -- converted to and from sfixed and ufixed. Note that you can + -- not convert these vectors because of their negative index. + + function to_slv ( + arg : UNRESOLVED_ufixed) -- fixed point vector + return STD_LOGIC_VECTOR; +-- alias to_StdLogicVector is to_slv [UNRESOLVED_ufixed +-- return STD_LOGIC_VECTOR]; +-- alias to_Std_Logic_Vector is to_slv [UNRESOLVED_ufixed +-- return STD_LOGIC_VECTOR]; + + function to_slv ( + arg : UNRESOLVED_sfixed) -- fixed point vector + return STD_LOGIC_VECTOR; +-- alias to_StdLogicVector is to_slv [UNRESOLVED_sfixed +-- return STD_LOGIC_VECTOR]; +-- alias to_Std_Logic_Vector is to_slv [UNRESOLVED_sfixed +-- return STD_LOGIC_VECTOR]; + + function to_sulv ( + arg : UNRESOLVED_ufixed) -- fixed point vector + return STD_ULOGIC_VECTOR; +-- alias to_StdULogicVector is to_sulv [UNRESOLVED_ufixed +-- return STD_ULOGIC_VECTOR]; +-- alias to_Std_ULogic_Vector is to_sulv [UNRESOLVED_ufixed +-- return STD_ULOGIC_VECTOR]; + + function to_sulv ( + arg : UNRESOLVED_sfixed) -- fixed point vector + return STD_ULOGIC_VECTOR; +-- alias to_StdULogicVector is to_sulv [UNRESOLVED_sfixed +-- return STD_ULOGIC_VECTOR]; +-- alias to_Std_ULogic_Vector is to_sulv [UNRESOLVED_sfixed +-- return STD_ULOGIC_VECTOR]; + + function to_ufixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + + function to_ufixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_ufixed) -- for size only + return UNRESOLVED_ufixed; + + function to_sfixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + + function to_sfixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_sfixed) -- for size only + return UNRESOLVED_sfixed; + + -- As a concession to those who use a graphical DSP environment, + -- these functions take parameters in those tools format and create + -- fixed point numbers. These functions are designed to convert from + -- a std_logic_vector to the VHDL fixed point format using the conventions + -- of these packages. In a pure VHDL environment you should use the + -- "to_ufixed" and "to_sfixed" routines. + + -- unsigned fixed point + function to_UFix ( + arg : STD_ULOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_ufixed; + + -- signed fixed point + function to_SFix ( + arg : STD_ULOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_sfixed; + + -- finding the bounds of a number. These functions can be used like this: + -- signal xxx : ufixed (7 downto -3); + -- -- Which is the same as "ufixed (UFix_high (11,3) downto UFix_low(11,3))" + -- signal yyy : ufixed (UFix_high (11, 3, "+", 11, 3) + -- downto UFix_low(11, 3, "+", 11, 3)); + -- Where "11" is the width of xxx (xxx'length), + -- and 3 is the lower bound (abs (xxx'low)) + -- In a pure VHDL environment use "ufixed_high" and "ufixed_low" + + function UFix_high (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + + function UFix_low (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + + -- Same as above but for signed fixed point. Note that the width + -- of a signed fixed point number ignores the sign bit, thus + -- width = sxxx'length-1 + + function SFix_high (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + + function SFix_low (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; +-- rtl_synthesis off +-- pragma synthesis_off + --=========================================================================== + -- string and textio Functions + --=========================================================================== + + -- purpose: writes fixed point into a line + procedure WRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + -- purpose: writes fixed point into a line + procedure WRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_ufixed); + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN); + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_sfixed); + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN); + + alias bwrite is WRITE [LINE, UNRESOLVED_ufixed, SIDE, width]; + alias bwrite is WRITE [LINE, UNRESOLVED_sfixed, SIDE, width]; + alias bread is READ [LINE, UNRESOLVED_ufixed]; + alias bread is READ [LINE, UNRESOLVED_ufixed, BOOLEAN]; + alias bread is READ [LINE, UNRESOLVED_sfixed]; + alias bread is READ [LINE, UNRESOLVED_sfixed, BOOLEAN]; + alias BINARY_WRITE is WRITE [LINE, UNRESOLVED_ufixed, SIDE, width]; + alias BINARY_WRITE is WRITE [LINE, UNRESOLVED_sfixed, SIDE, width]; + alias BINARY_READ is READ [LINE, UNRESOLVED_ufixed, BOOLEAN]; + alias BINARY_READ is READ [LINE, UNRESOLVED_ufixed]; + alias BINARY_READ is READ [LINE, UNRESOLVED_sfixed, BOOLEAN]; + alias BINARY_READ is READ [LINE, UNRESOLVED_sfixed]; + + -- octal read and write + procedure OWRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure OWRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed); + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN); + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed); + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN); + alias OCTAL_READ is OREAD [LINE, UNRESOLVED_ufixed, BOOLEAN]; + alias OCTAL_READ is OREAD [LINE, UNRESOLVED_ufixed]; + alias OCTAL_READ is OREAD [LINE, UNRESOLVED_sfixed, BOOLEAN]; + alias OCTAL_READ is OREAD [LINE, UNRESOLVED_sfixed]; + alias OCTAL_WRITE is OWRITE [LINE, UNRESOLVED_ufixed, SIDE, WIDTH]; + alias OCTAL_WRITE is OWRITE [LINE, UNRESOLVED_sfixed, SIDE, WIDTH]; + + -- hex read and write + procedure HWRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + -- purpose: writes fixed point into a line + procedure HWRITE ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed); + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN); + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed); + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN); + alias HEX_READ is HREAD [LINE, UNRESOLVED_ufixed, BOOLEAN]; + alias HEX_READ is HREAD [LINE, UNRESOLVED_sfixed, BOOLEAN]; + alias HEX_READ is HREAD [LINE, UNRESOLVED_ufixed]; + alias HEX_READ is HREAD [LINE, UNRESOLVED_sfixed]; + alias HEX_WRITE is HWRITE [LINE, UNRESOLVED_ufixed, SIDE, WIDTH]; + alias HEX_WRITE is HWRITE [LINE, UNRESOLVED_sfixed, SIDE, WIDTH]; + + -- returns a string, useful for: + -- assert (x = y) report "error found " & to_string(x) severity error; + function to_string (value : UNRESOLVED_ufixed) return STRING; + alias to_bstring is to_string [UNRESOLVED_ufixed return STRING]; + alias TO_BINARY_STRING is TO_STRING [UNRESOLVED_ufixed return STRING]; + + function to_ostring (value : UNRESOLVED_ufixed) return STRING; + alias TO_OCTAL_STRING is TO_OSTRING [UNRESOLVED_ufixed return STRING]; + + function to_hstring (value : UNRESOLVED_ufixed) return STRING; + alias TO_HEX_STRING is TO_HSTRING [UNRESOLVED_ufixed return STRING]; + + function to_string (value : UNRESOLVED_sfixed) return STRING; + alias to_bstring is to_string [UNRESOLVED_sfixed return STRING]; + alias TO_BINARY_STRING is TO_STRING [UNRESOLVED_sfixed return STRING]; + + function to_ostring (value : UNRESOLVED_sfixed) return STRING; + alias TO_OCTAL_STRING is TO_OSTRING [UNRESOLVED_sfixed return STRING]; + + function to_hstring (value : UNRESOLVED_sfixed) return STRING; + alias TO_HEX_STRING is TO_HSTRING [UNRESOLVED_sfixed return STRING]; + + -- From string functions allow you to convert a string into a fixed + -- point number. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100", uf1'high, uf1'low); -- 6.5 + -- The "." is optional in this syntax, however it exist and is + -- in the wrong location an error is produced. Overflow will + -- result in saturation. + + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + alias from_bstring is from_string [STRING, INTEGER, INTEGER + return UNRESOLVED_ufixed]; + alias from_binary_string is from_string [STRING, INTEGER, INTEGER + return UNRESOLVED_ufixed]; + + -- Octal and hex conversions work as follows: + -- uf1 <= from_hstring ("6.8", 3, -3); -- 6.5 (bottom zeros dropped) + -- uf1 <= from_ostring ("06.4", 3, -3); -- 6.5 (top zeros dropped) + + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + alias from_octal_string is from_ostring [STRING, INTEGER, INTEGER + return UNRESOLVED_ufixed]; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + alias from_hex_string is from_hstring [STRING, INTEGER, INTEGER + return UNRESOLVED_ufixed]; + + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + alias from_bstring is from_string [STRING, INTEGER, INTEGER + return UNRESOLVED_sfixed]; + alias from_binary_string is from_string [STRING, INTEGER, INTEGER + return UNRESOLVED_sfixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + alias from_octal_string is from_ostring [STRING, INTEGER, INTEGER + return UNRESOLVED_sfixed]; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + alias from_hex_string is from_hstring [STRING, INTEGER, INTEGER + return UNRESOLVED_sfixed]; + + -- Same as above, "size_res" is used for it's range only. + function from_string ( + bstring : STRING; -- binary string + size_res : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + alias from_bstring is from_string [STRING, UNRESOLVED_ufixed + return UNRESOLVED_ufixed]; + alias from_binary_string is from_string [STRING, UNRESOLVED_ufixed + return UNRESOLVED_ufixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + alias from_octal_string is from_ostring [STRING, UNRESOLVED_ufixed + return UNRESOLVED_ufixed]; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed; + alias from_hex_string is from_hstring [STRING, UNRESOLVED_ufixed + return UNRESOLVED_ufixed]; + + function from_string ( + bstring : STRING; -- binary string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + alias from_bstring is from_string [STRING, UNRESOLVED_sfixed + return UNRESOLVED_sfixed]; + alias from_binary_string is from_string [STRING, UNRESOLVED_sfixed + return UNRESOLVED_sfixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + alias from_octal_string is from_ostring [STRING, UNRESOLVED_sfixed + return UNRESOLVED_sfixed]; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed; + alias from_hex_string is from_hstring [STRING, UNRESOLVED_sfixed + return UNRESOLVED_sfixed]; + + -- Direct conversion functions. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100"); -- 6.5 + -- In this case the "." is not optional, and the size of + -- the output must match exactly. + + function from_string ( + bstring : STRING) -- binary string + return UNRESOLVED_ufixed; + alias from_bstring is from_string [STRING return UNRESOLVED_ufixed]; + alias from_binary_string is from_string [STRING return UNRESOLVED_ufixed]; + + -- Direct octal and hex conversion functions. In this case + -- the string lengths must match. Example: + -- signal sf1 := sfixed (5 downto -3); + -- sf1 <= from_ostring ("71.4") -- -6.5 + + function from_ostring ( + ostring : STRING) -- Octal string + return UNRESOLVED_ufixed; + alias from_octal_string is from_ostring [STRING return UNRESOLVED_ufixed]; + + function from_hstring ( + hstring : STRING) -- hex string + return UNRESOLVED_ufixed; + alias from_hex_string is from_hstring [STRING return UNRESOLVED_ufixed]; + + function from_string ( + bstring : STRING) -- binary string + return UNRESOLVED_sfixed; + alias from_bstring is from_string [STRING return UNRESOLVED_sfixed]; + alias from_binary_string is from_string [STRING return UNRESOLVED_sfixed]; + + function from_ostring ( + ostring : STRING) -- Octal string + return UNRESOLVED_sfixed; + alias from_octal_string is from_ostring [STRING return UNRESOLVED_sfixed]; + + function from_hstring ( + hstring : STRING) -- hex string + return UNRESOLVED_sfixed; + alias from_hex_string is from_hstring [STRING return UNRESOLVED_sfixed]; +-- rtl_synthesis on +-- pragma synthesis_on + + -- IN VHDL-2006 std_logic_vector is a subtype of std_ulogic_vector, so these + -- extra functions are needed for compatability. + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed; + + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_ufixed) -- for size only + return UNRESOLVED_ufixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_sfixed) -- for size only + return UNRESOLVED_sfixed; + + -- unsigned fixed point + function to_UFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_ufixed; + + -- signed fixed point + function to_SFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_sfixed; + +end package fixed_pkg; +------------------------------------------------------------------------------- +-- Proposed package body for the VHDL-200x-FT fixed_pkg package +-- (Fixed point math package) +-- This package body supplies a recommended implementation of these functions +-- Version : $Revision: 1.21 $ +-- Date : $Date: 2007/09/26 18:08:53 $ +-- +-- Created for VHDL-200X-ft, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------- +library IEEE; +use IEEE.MATH_REAL.all; + +package body fixed_pkg is + -- Author David Bishop (dbishop@vhdl.org) + -- Other contributers: Jim Lewis, Yannick Grugni, Ryan W. Hilton + -- null array constants + constant NAUF : UNRESOLVED_ufixed (0 downto 1) := (others => '0'); + constant NASF : UNRESOLVED_sfixed (0 downto 1) := (others => '0'); + constant NSLV : STD_ULOGIC_VECTOR (0 downto 1) := (others => '0'); + + -- This differed constant will tell you if the package body is synthesizable + -- or implemented as real numbers, set to "true" if synthesizable. + constant fixedsynth_or_real : BOOLEAN := true; + + -- %%% Replicated functions + function maximum ( + l, r : integer) -- inputs + return integer is + begin -- function max + if l > r then return l; + else return r; + end if; + end function maximum; + + function minimum ( + l, r : integer) -- inputs + return integer is + begin -- function min + if l > r then return r; + else return l; + end if; + end function minimum; + + function "sra" (arg : SIGNED; count : INTEGER) + return SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(arg, count); + else + return SHIFT_LEFT(arg, -count); + end if; + end function "sra"; + + function or_reduce (arg : STD_ULOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '0'; + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) or BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := or_reduce (BUS_int (BUS_int'left downto Half)); + Lower := or_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper or Lower; + end if; + end if; + return Result; + end function or_reduce; + + -- purpose: AND all of the bits in a vector together + -- This is a copy of the proposed "and_reduce" from 1076.3 + function and_reduce (arg : STD_ULOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '1'; + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) and BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := and_reduce (BUS_int (BUS_int'left downto Half)); + Lower := and_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper and Lower; + end if; + end if; + return Result; + end function and_reduce; + + function xor_reduce (arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range + begin + if (arg'length >= 1) then + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := xor_reduce (BUS_int (BUS_int'left downto Half)); + Lower := xor_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper xor Lower; + end if; + end if; + return Result; + end function xor_reduce; + + function nand_reduce(arg : std_ulogic_vector) return STD_ULOGIC is + begin + return not and_reduce (arg); + end function nand_reduce; + function nor_reduce(arg : std_ulogic_vector) return STD_ULOGIC is + begin + return not or_reduce (arg); + end function nor_reduce; + function xnor_reduce(arg : std_ulogic_vector) return STD_ULOGIC is + begin + return not xor_reduce (arg); + end function xnor_reduce; + -- Match table, copied form new std_logic_1164 +-- type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; +-- constant match_logic_table : stdlogic_table := ( +-- ----------------------------------------------------- +-- -- U X 0 1 Z W L H - | | +-- ----------------------------------------------------- +-- ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1'), -- | U | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | X | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | 0 | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | 1 | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | Z | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | W | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | L | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | H | +-- ('1', '1', '1', '1', '1', '1', '1', '1', '1') -- | - | +-- ); + +-- constant no_match_logic_table : stdlogic_table := ( +-- ----------------------------------------------------- +-- -- U X 0 1 Z W L H - | | +-- ----------------------------------------------------- +-- ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '0'), -- | U | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | X | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | 0 | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | 1 | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | Z | +-- ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | W | +-- ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | L | +-- ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | H | +-- ('0', '0', '0', '0', '0', '0', '0', '0', '0') -- | - | +-- ); + + ------------------------------------------------------------------- + -- ?= functions, Similar to "std_match", but returns "std_ulogic". + ------------------------------------------------------------------- + function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + variable lx, rx : STD_ULOGIC; + begin +-- return match_logic_table (l, r); + lx := to_x01(l); + rx := to_x01(r); + if lx = 'X' or rx = 'X' then + return 'X'; + elsif lx = rx then + return '1'; + else + return '0'; + end if; + end function \?=\; + function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + begin +-- return no_match_logic_table (l, r); + return not \?=\ (l, r); + end function \?/=\; + -- "?=" operator is similar to "std_match", but returns a std_ulogic.. + -- Id: M.2B + function \?=\ (L, R: UNSIGNED) return STD_ULOGIC is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : UNSIGNED(L_LEFT downto 0) is L; + alias XR : UNSIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); + variable LX : UNSIGNED(SIZE-1 downto 0); + variable RX : UNSIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin + -- Logically identical to an "=" operator. + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '1'; + for i in LX'low to LX'high loop + result1 := \?=\(LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; + + -- Id: M.3B + function \?=\ (L, R: SIGNED) return std_ulogic is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : SIGNED(L_LEFT downto 0) is L; + alias XR : SIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); + variable LX : SIGNED(SIZE-1 downto 0); + variable RX : SIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '1'; + for i in LX'low to LX'high loop + result1 := \?=\ (LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; + + function \?/=\ (L, R : UNSIGNED) return std_ulogic is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : UNSIGNED(L_LEFT downto 0) is L; + alias XR : UNSIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); + variable LX : UNSIGNED(SIZE-1 downto 0); + variable RX : UNSIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?/="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '0'; + for i in LX'low to LX'high loop + result1 := \?/=\ (LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; + + function \?/=\ (L, R : SIGNED) return std_ulogic is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : SIGNED(L_LEFT downto 0) is L; + alias XR : SIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAXIMUM(L'LENGTH, R'LENGTH); + variable LX : SIGNED(SIZE-1 downto 0); + variable RX : SIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?/="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '0'; + for i in LX'low to LX'high loop + result1 := \?/=\ (LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; + + function Is_X ( s : UNSIGNED ) return BOOLEAN is + begin + return Is_X (STD_LOGIC_VECTOR (s)); + end function Is_X; + + function Is_X ( s : SIGNED ) return BOOLEAN is + begin + return Is_X (STD_LOGIC_VECTOR (s)); + end function Is_X; + function \?>\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + -- %%% function "?>" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?>"\; + function \?>\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + function \?>=\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + -- %%% function "?>=" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?>="; + function \?>=\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + function \?<\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + -- %%% function "?<" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?<"; + function \?<\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<"": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + function \?<=\ (L, R : UNSIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + -- %%% function "?<=" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?<="; + function \?<=\ (L, R : SIGNED) return STD_ULOGIC is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<="": null detected, returning X" + severity warning; + return 'X'; + else + for i in L'range loop + if L(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + for i in R'range loop + if R(i) = '-' then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + end if; + end loop; + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + +-- %%% END replicated functions + -- Special version of "minimum" to do some boundary checking without errors + function mins (l, r : INTEGER) + return INTEGER is + begin -- function mins + if (L = INTEGER'low or R = INTEGER'low) then + return 0; -- error condition, silent + end if; + return minimum (L, R); + end function mins; + + -- Special version of "minimum" to do some boundary checking with errors + function mine (l, r : INTEGER) + return INTEGER is + begin -- function mine + if (L = INTEGER'low or R = INTEGER'low) then + report "fixed_pkg:" + & " Unbounded number passed, was a literal used?" + severity error; + return 0; + end if; + return minimum (L, R); + end function mine; + + -- The following functions are used only internally. Every function + -- calls "cleanvec" either directly or indirectly. + -- purpose: Fixes "downto" problem and resolves meta states + function cleanvec ( + arg : UNRESOLVED_sfixed) -- input + return UNRESOLVED_sfixed is + constant left_index : INTEGER := maximum(arg'left, arg'right); + constant right_index : INTEGER := mins(arg'left, arg'right); + variable result : UNRESOLVED_sfixed (arg'range); + begin -- function cleanvec + assert not (arg'ascending and (arg'low /= INTEGER'low)) + report "fixed_pkg:" + & " Vector passed using a ""to"" range, expected is ""downto""" + severity error; + return arg; + end function cleanvec; + + -- purpose: Fixes "downto" problem and resolves meta states + function cleanvec ( + arg : UNRESOLVED_ufixed) -- input + return UNRESOLVED_ufixed is + constant left_index : INTEGER := maximum(arg'left, arg'right); + constant right_index : INTEGER := mins(arg'left, arg'right); + variable result : UNRESOLVED_ufixed (arg'range); + begin -- function cleanvec + assert not (arg'ascending and (arg'low /= INTEGER'low)) + report "fixed_pkg:" + & " Vector passed using a ""to"" range, expected is ""downto""" + severity error; + return arg; + end function cleanvec; + + -- Type convert a "unsigned" into a "ufixed", used internally + function to_fixed ( + arg : UNSIGNED; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (left_index downto right_index); + begin -- function to_fixed + result := UNRESOLVED_ufixed(arg); + return result; + end function to_fixed; + + -- Type convert a "signed" into an "sfixed", used internally + function to_fixed ( + arg : SIGNED; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (left_index downto right_index); + begin -- function to_fixed + result := UNRESOLVED_sfixed(arg); + return result; + end function to_fixed; + + -- Type convert a "ufixed" into an "unsigned", used internally + function to_uns ( + arg : UNRESOLVED_ufixed) -- fp vector + return UNSIGNED is + subtype t is UNSIGNED(arg'high - arg'low downto 0); + variable slv : t; + begin -- function to_uns + slv := t(arg); + return slv; + end function to_uns; + + -- Type convert an "sfixed" into a "signed", used internally + function to_s ( + arg : UNRESOLVED_sfixed) -- fp vector + return SIGNED is + subtype t is SIGNED(arg'high - arg'low downto 0); + variable slv : t; + begin -- function to_s + slv := t(arg); + return slv; + end function to_s; + + -- adds 1 to the LSB of the number + procedure round_up (arg : in UNRESOLVED_ufixed; + result : out UNRESOLVED_ufixed; + overflowx : out BOOLEAN) is + variable arguns, resuns : UNSIGNED (arg'high-arg'low+1 downto 0) + := (others => '0'); + begin -- round_up + arguns (arguns'high-1 downto 0) := to_uns (arg); + resuns := arguns + 1; + result := to_fixed(resuns(arg'high-arg'low + downto 0), arg'high, arg'low); + overflowx := (resuns(resuns'high) = '1'); + end procedure round_up; + + -- adds 1 to the LSB of the number + procedure round_up (arg : in UNRESOLVED_sfixed; + result : out UNRESOLVED_sfixed; + overflowx : out BOOLEAN) is + variable args, ress : SIGNED (arg'high-arg'low+1 downto 0); + begin -- round_up + args (args'high-1 downto 0) := to_s (arg); + args(args'high) := arg(arg'high); -- sign extend + ress := args + 1; + result := to_fixed(ress (ress'high-1 + downto 0), arg'high, arg'low); + overflowx := ((arg(arg'high) /= ress(ress'high-1)) + and (or_reduce (STD_ULOGIC_VECTOR(ress)) /= '0')); + end procedure round_up; + + -- Rounding - Performs a "round_nearest" (IEEE 754) which rounds up + -- when the remainder is > 0.5. If the remainder IS 0.5 then if the + -- bottom bit is a "1" it is rounded, otherwise it remains the same. + function round_fixed (arg : UNRESOLVED_ufixed; + remainder : UNRESOLVED_ufixed; + overflow_style : fixed_overflow_style_type := fixed_overflow_style) + return UNRESOLVED_ufixed is + variable rounds : BOOLEAN; + variable round_overflow : BOOLEAN; + variable result : UNRESOLVED_ufixed (arg'range); + begin + rounds := false; + if (remainder'length > 1) then + if (remainder (remainder'high) = '1') then + rounds := (arg(arg'low) = '1') + or (or_reduce (to_sulv(remainder(remainder'high-1 downto + remainder'low))) = '1'); + end if; + else + rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); + end if; + if rounds then + round_up(arg => arg, + result => result, + overflowx => round_overflow); + else + result := arg; + end if; + if (overflow_style = fixed_saturate) and round_overflow then + result := saturate (result'high, result'low); + end if; + return result; + end function round_fixed; + + -- Rounding case statement + function round_fixed (arg : UNRESOLVED_sfixed; + remainder : UNRESOLVED_sfixed; + overflow_style : fixed_overflow_style_type := fixed_overflow_style) + return UNRESOLVED_sfixed is + variable rounds : BOOLEAN; + variable round_overflow : BOOLEAN; + variable result : UNRESOLVED_sfixed (arg'range); + begin + rounds := false; + if (remainder'length > 1) then + if (remainder (remainder'high) = '1') then + rounds := (arg(arg'low) = '1') + or (or_reduce (to_sulv(remainder(remainder'high-1 downto + remainder'low))) = '1'); + end if; + else + rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); + end if; + if rounds then + round_up(arg => arg, + result => result, + overflowx => round_overflow); + else + result := arg; + end if; + if round_overflow then + if (overflow_style = fixed_saturate) then + if arg(arg'high) = '0' then + result := saturate (result'high, result'low); + else + result := not saturate (result'high, result'low); + end if; + -- Sign bit not fixed when wrapping + end if; + end if; + return result; + end function round_fixed; + + -- converts an sfixed into a ufixed. The output is the same length as the + -- input, because abs("1000") = "1000" = 8. + function to_ufixed ( + arg : UNRESOLVED_sfixed) + return UNRESOLVED_ufixed + is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable xarg : UNRESOLVED_sfixed(left_index+1 downto right_index); + variable result : UNRESOLVED_ufixed(left_index downto right_index); + begin + if arg'length < 1 then + return NAUF; + end if; + xarg := abs(arg); + result := UNRESOLVED_ufixed (xarg (left_index downto right_index)); + return result; + end function to_ufixed; + +----------------------------------------------------------------------------- +-- Visible functions +----------------------------------------------------------------------------- + + -- Conversion functions. These are needed for synthesis where typically + -- the only input and output type is a std_logic_vector. + function to_sulv ( + arg : UNRESOLVED_ufixed) -- fixed point vector + return STD_ULOGIC_VECTOR is + variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0); + begin + if arg'length < 1 then + return NSLV; + end if; + result := STD_ULOGIC_VECTOR (arg); + return result; + end function to_sulv; + + function to_sulv ( + arg : UNRESOLVED_sfixed) -- fixed point vector + return STD_ULOGIC_VECTOR is + variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0); + begin + if arg'length < 1 then + return NSLV; + end if; + result := STD_ULOGIC_VECTOR (arg); + return result; + end function to_sulv; + + function to_slv ( + arg : UNRESOLVED_ufixed) -- fixed point vector + return STD_LOGIC_VECTOR is + begin + return std_logic_vector(to_sulv(arg)); + end function to_slv; + + function to_slv ( + arg : UNRESOLVED_sfixed) -- fixed point vector + return STD_LOGIC_VECTOR is + begin + return std_logic_vector(to_sulv(arg)); + end function to_slv; + + function to_ufixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return unresolved_ufixed is + variable result : UNRESOLVED_ufixed (left_index downto right_index); + begin + if (arg'length < 1 or right_index > left_index) then + return NAUF; + end if; + if (arg'length /= result'length) then + report "fixed_pkg:" & "TO_UFIXED(SLV) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NAUF; + else + result := to_fixed (arg => UNSIGNED(arg), + left_index => left_index, + right_index => right_index); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return unresolved_sfixed is + variable result : UNRESOLVED_sfixed (left_index downto right_index); + begin + if (arg'length < 1 or right_index > left_index) then + return NASF; + end if; + if (arg'length /= result'length) then + report "fixed_pkg:" & "TO_SFIXED(SLV) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NASF; + else + result := to_fixed (arg => SIGNED(arg), + left_index => left_index, + right_index => right_index); + return result; + end if; + end function to_sfixed; + + -- Two's complement number, Grows the vector by 1 bit. + -- because "abs (1000.000) = 01000.000" or abs(-16) = 16. + function "abs" ( + arg : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable ressns : SIGNED (arg'length downto 0); + variable result : UNRESOLVED_sfixed (left_index+1 downto right_index); + begin + if (arg'length < 1 or result'length < 1) then + return NASF; + end if; + ressns (arg'length-1 downto 0) := to_s (cleanvec (arg)); + ressns (arg'length) := ressns (arg'length-1); -- expand sign bit + result := to_fixed (abs(ressns), left_index+1, right_index); + return result; + end function "abs"; + + -- also grows the vector by 1 bit. + function "-" ( + arg : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + constant left_index : INTEGER := arg'high+1; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable ressns : SIGNED (arg'length downto 0); + variable result : UNRESOLVED_sfixed (left_index downto right_index); + begin + if (arg'length < 1 or result'length < 1) then + return NASF; + end if; + ressns (arg'length-1 downto 0) := to_s (cleanvec(arg)); + ressns (arg'length) := ressns (arg'length-1); -- expand sign bit + result := to_fixed (-ressns, left_index, right_index); + return result; + end function "-"; + + -- Addition + function "+" ( + l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) + ufixed(c downto d) = + return UNRESOLVED_ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mine(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable result : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + begin + if (l'length < 1 or r'length < 1 or result'length < 1) then + return NAUF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv + rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "+"; + + function "+" ( + l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) + sfixed(c downto d) = + return UNRESOLVED_sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mine(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable result : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index downto 0); + variable result_slv : SIGNED (left_index-right_index downto 0); + begin + if (l'length < 1 or r'length < 1 or result'length < 1) then + return NASF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv + rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "+"; + + -- Subtraction + function "-" ( + l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) - ufixed(c downto d) = + return UNRESOLVED_ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mine(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable result : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + begin + if (l'length < 1 or r'length < 1 or result'length < 1) then + return NAUF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv - rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "-"; + + function "-" ( + l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) - sfixed(c downto d) = + return UNRESOLVED_sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mine(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable result : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index downto 0); + variable result_slv : SIGNED (left_index-right_index downto 0); + begin + if (l'length < 1 or r'length < 1 or result'length < 1) then + return NASF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv - rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "-"; + + function "*" ( + l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) * ufixed(c downto d) = + return UNRESOLVED_ufixed is -- ufixed(a+c+1 downto b+d) + variable lslv : UNSIGNED (l'length-1 downto 0); + variable rslv : UNSIGNED (r'length-1 downto 0); + variable result_slv : UNSIGNED (r'length+l'length-1 downto 0); + variable result : UNRESOLVED_ufixed (l'high + r'high+1 downto + mine(l'low, l'low) + mine(r'low, r'low)); + begin + if (l'length < 1 or r'length < 1 or + result'length /= result_slv'length) then + return NAUF; + end if; + lslv := to_uns (cleanvec(l)); + rslv := to_uns (cleanvec(r)); + result_slv := lslv * rslv; + result := to_fixed (result_slv, result'high, result'low); + return result; + end function "*"; + + function "*" ( + l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) * sfixed(c downto d) = + return UNRESOLVED_sfixed is -- sfixed(a+c+1 downto b+d) + variable lslv : SIGNED (l'length-1 downto 0); + variable rslv : SIGNED (r'length-1 downto 0); + variable result_slv : SIGNED (r'length+l'length-1 downto 0); + variable result : UNRESOLVED_sfixed (l'high + r'high+1 downto + mine(l'low, l'low) + mine(r'low, r'low)); + begin + if (l'length < 1 or r'length < 1 or + result'length /= result_slv'length) then + return NASF; + end if; + lslv := to_s (cleanvec(l)); + rslv := to_s (cleanvec(r)); + result_slv := lslv * rslv; + result := to_fixed (result_slv, result'high, result'low); + return result; + end function "*"; + +-- function "/" ( +-- l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) / ufixed(c downto d) = +-- return UNRESOLVED_ufixed is -- ufixed(a-d downto b-c-1) +-- begin +-- return divide (l, r); +-- end function "/"; + +-- function "/" ( +-- l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) / sfixed(c downto d) = +-- return UNRESOLVED_sfixed is -- sfixed(a-d+1 downto b-c) +-- begin +-- return divide (l, r); +-- end function "/"; + + -- This version of divide gives the user more control + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) +-- function divide ( +-- l, r : UNRESOLVED_ufixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed is +-- variable result : UNRESOLVED_ufixed (l'high - mine(r'low, r'low) downto +-- mine (l'low, l'low) - r'high -1); +-- variable dresult : UNRESOLVED_ufixed (result'high downto result'low -guard_bits); +-- variable lresize : UNRESOLVED_ufixed (l'high downto l'high - dresult'length+1); +-- variable lslv : UNSIGNED (lresize'length-1 downto 0); +-- variable rslv : UNSIGNED (r'length-1 downto 0); +-- variable result_slv : UNSIGNED (lresize'length-1 downto 0); +-- begin +-- if (l'length < 1 or r'length < 1 or +-- mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then +-- return NAUF; +-- end if; +-- lresize := resize (arg => l, +-- left_index => lresize'high, +-- right_index => lresize'low, +-- overflow_style => fixed_wrap, -- vector only grows +-- round_style => fixed_truncate); +-- lslv := to_uns (cleanvec (lresize)); +-- rslv := to_uns (cleanvec (r)); +-- if (rslv = 0) then +-- report "fixed_pkg:" +-- & "DIVIDE(ufixed) Division by zero" severity error; +-- result := saturate (result'high, result'low); -- saturate +-- else +-- result_slv := lslv / rslv; +-- dresult := to_fixed (result_slv, dresult'high, dresult'low); +-- result := resize (arg => dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => fixed_wrap, -- overflow impossible +-- round_style => round_style); +-- end if; +-- return result; +-- end function divide; + + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) +-- function divide ( +-- l, r : UNRESOLVED_sfixed; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed is +-- variable result : UNRESOLVED_sfixed (l'high - mine(r'low, r'low) + 1 downto +-- mine (l'low, l'low) - r'high); +-- variable dresult : UNRESOLVED_sfixed (result'high downto result'low-guard_bits); +-- variable lresize : UNRESOLVED_sfixed (l'high+1 downto l'high+1 -dresult'length+1); +-- variable lslv : SIGNED (lresize'length-1 downto 0); +-- variable rslv : SIGNED (r'length-1 downto 0); +-- variable result_slv : SIGNED (lresize'length-1 downto 0); +-- begin +-- if (l'length < 1 or r'length < 1 or +-- mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then +-- return NASF; +-- end if; +-- lresize := resize (arg => l, +-- left_index => lresize'high, +-- right_index => lresize'low, +-- overflow_style => fixed_wrap, -- vector only grows +-- round_style => fixed_truncate); +-- lslv := to_s (cleanvec (lresize)); +-- rslv := to_s (cleanvec (r)); +-- if (rslv = 0) then +-- report "fixed_pkg:" +-- & "DIVIDE(sfixed) Division by zero" severity error; +-- result := saturate (result'high, result'low); +-- else +-- result_slv := lslv / rslv; +-- dresult := to_fixed (result_slv, dresult'high, dresult'low); +-- result := resize (arg => dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => fixed_wrap, -- overflow impossible +-- round_style => round_style); +-- end if; +-- return result; +-- end function divide; + + -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) +-- function reciprocal ( +-- arg : UNRESOLVED_ufixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed is +-- constant one : UNRESOLVED_ufixed (0 downto 0) := "1"; +-- begin +-- return divide (l => one, +-- r => arg, +-- round_style => round_style, +-- guard_bits => guard_bits); +-- end function reciprocal; + + -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) +-- function reciprocal ( +-- arg : UNRESOLVED_sfixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed is +-- constant one : UNRESOLVED_sfixed (1 downto 0) := "01"; -- extra bit. +-- variable resultx : UNRESOLVED_sfixed (-mine(arg'low, arg'low)+2 downto -arg'high); +-- begin +-- if (arg'length < 1 or resultx'length < 1) then +-- return NASF; +-- else +-- resultx := divide (l => one, +-- r => arg, +-- round_style => round_style, +-- guard_bits => guard_bits); +-- return resultx (resultx'high-1 downto resultx'low); -- remove extra bit +-- end if; +-- end function reciprocal; + + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) +-- function "rem" ( +-- l, r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return remainder (l, r); +-- end function "rem"; + +-- -- remainder +-- -- sfixed (a downto b) rem sfixed (c downto d) +-- -- = sfixed (min(a,c) downto min(b,d)) +-- function "rem" ( +-- l, r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return remainder (l, r); +-- end function "rem"; + + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) +-- function remainder ( +-- l, r : UNRESOLVED_ufixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed is +-- variable result : UNRESOLVED_ufixed (minimum(l'high, r'high) downto +-- mine(l'low, r'low)); +-- variable lresize : UNRESOLVED_ufixed (maximum(l'high, r'low) downto +-- mins(r'low, r'low)-guard_bits); +-- variable rresize : UNRESOLVED_ufixed (r'high downto r'low-guard_bits); +-- variable dresult : UNRESOLVED_ufixed (rresize'range); +-- variable lslv : UNSIGNED (lresize'length-1 downto 0); +-- variable rslv : UNSIGNED (rresize'length-1 downto 0); +-- variable result_slv : UNSIGNED (rslv'range); +-- begin +-- if (l'length < 1 or r'length < 1 or +-- mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then +-- return NAUF; +-- end if; +-- lresize := resize (arg => l, +-- left_index => lresize'high, +-- right_index => lresize'low, +-- overflow_style => fixed_wrap, -- vector only grows +-- round_style => fixed_truncate); +-- lslv := to_uns (lresize); +-- rresize := resize (arg => r, +-- left_index => rresize'high, +-- right_index => rresize'low, +-- overflow_style => fixed_wrap, -- vector only grows +-- round_style => fixed_truncate); +-- rslv := to_uns (rresize); +-- if (rslv = 0) then +-- report "fixed_pkg:" +-- & "remainder(ufixed) Division by zero" severity error; +-- result := saturate (result'high, result'low); -- saturate +-- else +-- if (r'low <= l'high) then +-- result_slv := lslv rem rslv; +-- dresult := to_fixed (result_slv, dresult'high, dresult'low); +-- result := resize (arg => dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => fixed_wrap, -- can't overflow +-- round_style => round_style); +-- end if; +-- if l'low < r'low then +-- result(mins(r'low-1, l'high) downto l'low) := +-- cleanvec(l(mins(r'low-1, l'high) downto l'low)); +-- end if; +-- end if; +-- return result; +-- end function remainder; + +-- -- remainder +-- -- sfixed (a downto b) rem sfixed (c downto d) +-- -- = sfixed (min(a,c) downto min(b,d)) +-- function remainder ( +-- l, r : UNRESOLVED_sfixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed is +-- variable l_abs : UNRESOLVED_ufixed (l'range); +-- variable r_abs : UNRESOLVED_ufixed (r'range); +-- variable result : UNRESOLVED_sfixed (minimum(r'high, l'high) downto +-- mine(r'low, l'low)); +-- variable neg_result : UNRESOLVED_sfixed (minimum(r'high, l'high)+1 downto +-- mins(r'low, l'low)); +-- begin +-- if (l'length < 1 or r'length < 1 or +-- mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then +-- return NASF; +-- end if; +-- l_abs := to_ufixed (l); +-- r_abs := to_ufixed (r); +-- result := UNRESOLVED_sfixed (remainder ( +-- l => l_abs, +-- r => r_abs, +-- round_style => round_style)); +-- neg_result := -result; +-- if l(l'high) = '1' then +-- result := neg_result(result'range); +-- end if; +-- return result; +-- end function remainder; + +-- -- modulo +-- -- ufixed (a downto b) mod ufixed (c downto d) +-- -- = ufixed (min(a,c) downto min(b, d)) +-- function "mod" ( +-- l, r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return modulo (l, r); +-- end function "mod"; + +-- -- sfixed (a downto b) mod sfixed (c downto d) +-- -- = sfixed (c downto min(b, d)) +-- function "mod" ( +-- l, r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return modulo(l, r); +-- end function "mod"; + +-- -- modulo +-- -- ufixed (a downto b) mod ufixed (c downto d) +-- -- = ufixed (min(a,c) downto min(b, d)) +-- function modulo ( +-- l, r : UNRESOLVED_ufixed; -- fixed point input +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_ufixed is +-- begin +-- return remainder(l => l, +-- r => r, +-- round_style => round_style, +-- guard_bits => guard_bits); +-- end function modulo; + +-- -- sfixed (a downto b) mod sfixed (c downto d) +-- -- = sfixed (c downto min(b, d)) +-- function modulo ( +-- l, r : UNRESOLVED_sfixed; -- fixed point input +-- constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; +-- constant round_style : fixed_round_style_type := fixed_round_style; +-- constant guard_bits : NATURAL := fixed_guard_bits) +-- return UNRESOLVED_sfixed is +-- variable l_abs : UNRESOLVED_ufixed (l'range); +-- variable r_abs : UNRESOLVED_ufixed (r'range); +-- variable result : UNRESOLVED_sfixed (r'high downto +-- mine(r'low, l'low)); +-- variable dresult : UNRESOLVED_sfixed (minimum(r'high, l'high)+1 downto +-- mins(r'low, l'low)); +-- variable dresult_not_zero : BOOLEAN; +-- begin +-- if (l'length < 1 or r'length < 1 or +-- mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then +-- return NASF; +-- end if; +-- l_abs := to_ufixed (l); +-- r_abs := to_ufixed (r); +-- dresult := "0" & UNRESOLVED_sfixed(remainder (l => l_abs, +-- r => r_abs, +-- round_style => round_style)); +-- if (to_s(dresult) = 0) then +-- dresult_not_zero := false; +-- else +-- dresult_not_zero := true; +-- end if; +-- if to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '0' +-- and dresult_not_zero then +-- result := resize (arg => r - dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => overflow_style, +-- round_style => round_style); +-- elsif to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '1' then +-- result := resize (arg => -dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => overflow_style, +-- round_style => round_style); +-- elsif to_x01(l(l'high)) = '0' and to_x01(r(r'high)) = '1' +-- and dresult_not_zero then +-- result := resize (arg => dresult + r, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => overflow_style, +-- round_style => round_style); +-- else +-- result := resize (arg => dresult, +-- left_index => result'high, +-- right_index => result'low, +-- overflow_style => overflow_style, +-- round_style => round_style); +-- end if; +-- return result; +-- end function modulo; + + -- Procedure for those who need an "accumulator" function + procedure add_carry ( + L, R : in UNRESOLVED_ufixed; + c_in : in STD_ULOGIC; + result : out UNRESOLVED_ufixed; + c_out : out STD_ULOGIC) is + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + variable cx : UNSIGNED (0 downto 0); -- Carry in + begin + if (l'length < 1 or r'length < 1) then + result := NAUF; + c_out := '0'; + else + cx (0) := c_in; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv + rslv + cx; + c_out := result_slv(left_index); + result := to_fixed(result_slv (left_index-right_index-1 downto 0), + left_index-1, right_index); + end if; + end procedure add_carry; + + procedure add_carry ( + L, R : in UNRESOLVED_sfixed; + c_in : in STD_ULOGIC; + result : out UNRESOLVED_sfixed; + c_out : out STD_ULOGIC) is + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index + downto 0); + variable result_slv : SIGNED (left_index-right_index + downto 0); + variable cx : SIGNED (1 downto 0); -- Carry in + begin + if (l'length < 1 or r'length < 1) then + result := NASF; + c_out := '0'; + else + cx (1) := '0'; + cx (0) := c_in; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv + rslv + cx; + c_out := result_slv(left_index); + result := to_fixed(result_slv (left_index-right_index-1 downto 0), + left_index-1, right_index); + end if; + end procedure add_carry; + + -- Scales the result by a power of 2. Width of input = width of output with + -- the decimal point moved. + function scalb (y : UNRESOLVED_ufixed; N : INTEGER) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (y'high+N downto y'low+N); + begin + if y'length < 1 then + return NAUF; + else + result := y; + return result; + end if; + end function scalb; + + function scalb (y : UNRESOLVED_ufixed; N : SIGNED) + return UNRESOLVED_ufixed is + begin + return scalb (y => y, + N => to_integer(N)); + end function scalb; + + function scalb (y : UNRESOLVED_sfixed; N : INTEGER) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (y'high+N downto y'low+N); + begin + if y'length < 1 then + return NASF; + else + result := y; + return result; + end if; + end function scalb; + + function scalb (y : UNRESOLVED_sfixed; N : SIGNED) + return UNRESOLVED_sfixed is + begin + return scalb (y => y, + N => to_integer(N)); + end function scalb; + + function Is_Negative (arg : UNRESOLVED_sfixed) return BOOLEAN is + begin + if to_X01(arg(arg'high)) = '1' then + return true; + else + return false; + end if; + end function Is_Negative; + + function find_rightmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) + return INTEGER is + begin + for_loop : for i in arg'reverse_range loop + if \?=\ (arg(i), y) = '1' then + return i; + end if; + end loop; + return arg'high+1; -- return out of bounds 'high + end function find_rightmost; + + function find_leftmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) + return INTEGER is + begin + for_loop : for i in arg'range loop + if \?=\ (arg(i), y) = '1' then + return i; + end if; + end loop; + return arg'low-1; -- return out of bounds 'low + end function find_leftmost; + + function find_rightmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) + return INTEGER is + begin + for_loop : for i in arg'reverse_range loop + if \?=\ (arg(i), y) = '1' then + return i; + end if; + end loop; + return arg'high+1; -- return out of bounds 'high + end function find_rightmost; + + function find_leftmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) + return INTEGER is + begin + for_loop : for i in arg'range loop + if \?=\ (arg(i), y) = '1' then + return i; + end if; + end loop; + return arg'low-1; -- return out of bounds 'low + end function find_leftmost; + + function "sll" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sll"; + + function "srl" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "srl"; + + function "rol" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv rol COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "rol"; + + function "ror" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv ror COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "ror"; + + function "sla" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + -- Arithmetic shift on an unsigned is a logical shift + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sla"; + + function "sra" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) + return UNRESOLVED_ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_ufixed (arg'range); + begin + argslv := to_uns (arg); + -- Arithmetic shift on an unsigned is a logical shift + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sra"; + + function "sll" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sll"; + + function "srl" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "srl"; + + function "rol" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv rol COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "rol"; + + function "ror" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv ror COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "ror"; + + function "sla" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + if COUNT > 0 then + -- Arithmetic shift left on a 2's complement number is a logic shift + argslv := argslv sll COUNT; + else + argslv := argslv sra -COUNT; + end if; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sla"; + + function "sra" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) + return UNRESOLVED_sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : UNRESOLVED_sfixed (arg'range); + begin + argslv := to_s (arg); + if COUNT > 0 then + argslv := argslv sra COUNT; + else + -- Arithmetic shift left on a 2's complement number is a logic shift + argslv := argslv sll -COUNT; + end if; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sra"; + + -- Because some people want the older functions. + function SHIFT_LEFT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) + return UNRESOLVED_ufixed is + begin + if (ARG'length < 1) then + return NAUF; + end if; + return ARG sla COUNT; + end function SHIFT_LEFT; + + function SHIFT_RIGHT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) + return UNRESOLVED_ufixed is + begin + if (ARG'length < 1) then + return NAUF; + end if; + return ARG sra COUNT; + end function SHIFT_RIGHT; + + function SHIFT_LEFT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) + return UNRESOLVED_sfixed is + begin + if (ARG'length < 1) then + return NASF; + end if; + return ARG sla COUNT; + end function SHIFT_LEFT; + + function SHIFT_RIGHT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) + return UNRESOLVED_sfixed is + begin + if (ARG'length < 1) then + return NASF; + end if; + return ARG sra COUNT; + end function SHIFT_RIGHT; + + ---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + function "not" (L : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + RESULT := not to_sulv(L); + return to_ufixed(RESULT, L'high, L'low); + end function "not"; + + function "and" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) and to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """and"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "and"; + + function "or" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) or to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """or"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "or"; + + function "nand" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) nand to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """nand"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "nand"; + + function "nor" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) nor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """nor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "nor"; + + function "xor" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) xor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """xor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "xor"; + + function "xnor" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) xnor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """xnor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "xnor"; + + function "not" (L : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + RESULT := not to_sulv(L); + return to_sfixed(RESULT, L'high, L'low); + end function "not"; + + function "and" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) and to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """and"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "and"; + + function "or" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) or to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """or"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "or"; + + function "nand" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) nand to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """nand"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "nand"; + + function "nor" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) nor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """nor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "nor"; + + function "xor" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) xor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """xor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "xor"; + + function "xnor" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_sulv(L) xnor to_sulv(R); + else + assert NO_WARNING + report "fixed_pkg:" + & """xnor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'X'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "xnor"; + + -- Vector and std_ulogic functions, same as functions in numeric_std + function "and" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (R'range); + begin + for i in result'range loop + result(i) := L and R(i); + end loop; + return result; + end function "and"; + + function "and" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) and R; + end loop; + return result; + end function "and"; + + function "or" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (R'range); + begin + for i in result'range loop + result(i) := L or R(i); + end loop; + return result; + end function "or"; + + function "or" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) or R; + end loop; + return result; + end function "or"; + + function "nand" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (R'range); + begin + for i in result'range loop + result(i) := L nand R(i); + end loop; + return result; + end function "nand"; + + function "nand" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nand R; + end loop; + return result; + end function "nand"; + + function "nor" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (R'range); + begin + for i in result'range loop + result(i) := L nor R(i); + end loop; + return result; + end function "nor"; + + function "nor" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nor R; + end loop; + return result; + end function "nor"; + + function "xor" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (R'range); + begin + for i in result'range loop + result(i) := L xor R(i); + end loop; + return result; + end function "xor"; + + function "xor" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xor R; + end loop; + return result; + end function "xor"; + + function "xnor" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (R'range); + begin + for i in result'range loop + result(i) := L xnor R(i); + end loop; + return result; + end function "xnor"; + + function "xnor" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xnor R; + end loop; + return result; + end function "xnor"; + + function "and" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (R'range); + begin + for i in result'range loop + result(i) := L and R(i); + end loop; + return result; + end function "and"; + + function "and" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) and R; + end loop; + return result; + end function "and"; + + function "or" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (R'range); + begin + for i in result'range loop + result(i) := L or R(i); + end loop; + return result; + end function "or"; + + function "or" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) or R; + end loop; + return result; + end function "or"; + + function "nand" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (R'range); + begin + for i in result'range loop + result(i) := L nand R(i); + end loop; + return result; + end function "nand"; + + function "nand" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nand R; + end loop; + return result; + end function "nand"; + + function "nor" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (R'range); + begin + for i in result'range loop + result(i) := L nor R(i); + end loop; + return result; + end function "nor"; + + function "nor" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nor R; + end loop; + return result; + end function "nor"; + + function "xor" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (R'range); + begin + for i in result'range loop + result(i) := L xor R(i); + end loop; + return result; + end function "xor"; + + function "xor" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xor R; + end loop; + return result; + end function "xor"; + + function "xnor" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (R'range); + begin + for i in result'range loop + result(i) := L xnor R(i); + end loop; + return result; + end function "xnor"; + + function "xnor" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xnor R; + end loop; + return result; + end function "xnor"; + + -- Reduction operator_reduces + function and_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return and_reduce (to_sulv(l)); + end function and_reduce; + + function nand_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return nand_reduce (to_sulv(l)); + end function nand_reduce; + + function or_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return or_reduce (to_sulv(l)); + end function or_reduce; + + function nor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return nor_reduce (to_sulv(l)); + end function nor_reduce; + + function xor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return xor_reduce (to_sulv(l)); + end function xor_reduce; + + function xnor_reduce (l : UNRESOLVED_ufixed) return STD_ULOGIC is + begin + return xnor_reduce (to_sulv(l)); + end function xnor_reduce; + + function and_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return and_reduce (to_sulv(l)); + end function and_reduce; + + function nand_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return nand_reduce (to_sulv(l)); + end function nand_reduce; + + function or_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return or_reduce (to_sulv(l)); + end function or_reduce; + + function nor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return nor_reduce (to_sulv(l)); + end function nor_reduce; + + function xor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return xor_reduce (to_sulv(l)); + end function xor_reduce; + + function xnor_reduce (l : UNRESOLVED_sfixed) return STD_ULOGIC is + begin + return xnor_reduce (to_sulv(l)); + end function xnor_reduce; + -- End reduction operator_reduces + + function \?=\ (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin -- ?= + if ((L'length < 1) or (R'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return \?=\ (lslv, rslv); + end if; + end function \?=\; + + function \?/=\ (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin -- ?/= + if ((L'length < 1) or (R'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?/="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return \?/=\ (lslv, rslv); + end if; + end function \?/=\; + + function \?>\ (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin -- ?> + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?>"": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return \?>\ (lslv, rslv); + end if; + end function \?>\; + + function \?>=\ (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin -- ?>= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?>="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return \?>=\ (lslv, rslv); + end if; + end function \?>=\; + + function \?<\ (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin -- ?< + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?<"": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return \?<\ (lslv, rslv); + end if; + end function \?<\; + + function \?<=\ (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin -- ?<= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?<="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return \?<=\ (lslv, rslv); + end if; + end function \?<=\; + + function \?=\ (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin -- ?= + if ((L'length < 1) or (R'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return \?=\ (lslv, rslv); + end if; + end function \?=\; + + function \?/=\ (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin -- ?/= + if ((L'length < 1) or (R'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?/="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return \?/=\ (lslv, rslv); + end if; + end function \?/=\; + + function \?>\ (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin -- ?> + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?>"": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return \?>\ (lslv, rslv); + end if; + end function \?>\; + + function \?>=\ (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin -- ?>= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?>="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return \?>=\ (lslv, rslv); + end if; + end function \?>=\; + + function \?<\ (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin -- ?< + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?<"": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return \?<\ (lslv, rslv); + end if; + end function \?<\; + + function \?<=\ (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin -- ?<= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "fixed_pkg:" + & """?<="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return \?<=\ (lslv, rslv); + end if; + end function \?<=\; + + -- Match function, similar to "std_match" from numeric_std + function std_match (L, R : UNRESOLVED_ufixed) return BOOLEAN is + begin + if (L'high = R'high and L'low = R'low) then + return std_match(to_sulv(L), to_sulv(R)); + else + assert NO_WARNING + report "fixed_pkg:" + & "STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" + severity warning; + return false; + end if; + end function std_match; + + function std_match (L, R : UNRESOLVED_sfixed) return BOOLEAN is + begin + if (L'high = R'high and L'low = R'low) then + return std_match(to_sulv(L), to_sulv(R)); + else + assert NO_WARNING + report "fixed_pkg:" + & "STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" + severity warning; + return false; + end if; + end function std_match; + + -- compare functions + function "=" ( + l, r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv = rslv; + end function "="; + + function "=" ( + l, r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv = rslv; + end function "="; + + function "/=" ( + l, r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """/="": null argument detected, returning TRUE" + severity warning; + return true; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """/="": metavalue detected, returning TRUE" + severity warning; + return true; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv /= rslv; + end function "/="; + + function "/=" ( + l, r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """/="": null argument detected, returning TRUE" + severity warning; + return true; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """/="": metavalue detected, returning TRUE" + severity warning; + return true; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv /= rslv; + end function "/="; + + function ">" ( + l, r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """>"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """>"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv > rslv; + end function ">"; + + function ">" ( + l, r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """>"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """>"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv > rslv; + end function ">"; + + function "<" ( + l, r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """<"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """<"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv < rslv; + end function "<"; + + function "<" ( + l, r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """<"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """<"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv < rslv; + end function "<"; + + function ">=" ( + l, r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """>="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """>="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv >= rslv; + end function ">="; + + function ">=" ( + l, r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """>="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """>="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv >= rslv; + end function ">="; + + function "<=" ( + l, r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """<="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """<="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv <= rslv; + end function "<="; + + function "<=" ( + l, r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & """<="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "fixed_pkg:" + & """<="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv <= rslv; + end function "<="; + + -- overloads of the default maximum and minimum functions + function maximum (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + begin + if (l'length < 1 or r'length < 1) then + return NAUF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + if lresize > rresize then return lresize; + else return rresize; + end if; + end function maximum; + + function maximum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + begin + if (l'length < 1 or r'length < 1) then + return NASF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + if lresize > rresize then return lresize; + else return rresize; + end if; + end function maximum; + + function minimum (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); + begin + if (l'length < 1 or r'length < 1) then + return NAUF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + if lresize > rresize then return rresize; + else return lresize; + end if; + end function minimum; + + function minimum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); + begin + if (l'length < 1 or r'length < 1) then + return NASF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + if lresize > rresize then return rresize; + else return lresize; + end if; + end function minimum; + + function to_ufixed ( + arg : NATURAL; -- integer + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant fw : INTEGER := mins (right_index, right_index); -- catch literals + variable result : UNRESOLVED_ufixed (left_index downto fw); + variable sresult : UNRESOLVED_ufixed (left_index downto 0) := + (others => '0'); -- integer portion + variable argx : NATURAL; -- internal version of arg + begin + if (result'length < 1) then + return NAUF; + end if; + if arg /= 0 then + argx := arg; + for I in 0 to sresult'left loop + if (argx mod 2) = 0 then + sresult(I) := '0'; + else + sresult(I) := '1'; + end if; + argx := argx/2; + end loop; + if argx /= 0 then + assert NO_WARNING + report "fixed_pkg:" + & "TO_UFIXED(NATURAL): vector truncated" + severity warning; + if overflow_style = fixed_saturate then + return saturate (left_index, right_index); + end if; + end if; + result := resize (arg => sresult, + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + else + result := (others => '0'); + end if; + return result; + end function to_ufixed; + + function to_sfixed ( + arg : INTEGER; -- integer + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant fw : INTEGER := mins (right_index, right_index); -- catch literals + variable result : UNRESOLVED_sfixed (left_index downto fw); + variable sresult : UNRESOLVED_sfixed (left_index downto 0) := + (others => '0'); -- integer portion + variable argx : INTEGER; -- internal version of arg + variable sign : STD_ULOGIC; -- sign of input + begin + if (result'length < 1) then -- null range + return NASF; + end if; + if arg /= 0 then + if (arg < 0) then + sign := '1'; + argx := -(arg + 1); + else + sign := '0'; + argx := arg; + end if; + for I in 0 to sresult'left loop + if (argx mod 2) = 0 then + sresult(I) := sign; + else + sresult(I) := not sign; + end if; + argx := argx/2; + end loop; + if argx /= 0 or left_index < 0 or sign /= sresult(sresult'left) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_SFIXED(INTEGER): vector truncated" + severity warning; + if overflow_style = fixed_saturate then -- saturate + if arg < 0 then + result := not saturate (result'high, result'low); -- underflow + else + result := saturate (result'high, result'low); -- overflow + end if; + return result; + end if; + end if; + result := resize (arg => sresult, + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + else + result := (others => '0'); + end if; + return result; + end function to_sfixed; + + function to_ufixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return UNRESOLVED_ufixed is + constant fw : INTEGER := mins (right_index, right_index); -- catch literals + variable result : UNRESOLVED_ufixed (left_index downto fw) := + (others => '0'); + variable Xresult : UNRESOLVED_ufixed (left_index downto + fw-guard_bits) := + (others => '0'); + variable presult : REAL; +-- variable overflow_needed : BOOLEAN; + begin + -- If negative or null range, return. + if (left_index < fw) then + return NAUF; + end if; + if (arg < 0.0) then + report "fixed_pkg:" + & "TO_UFIXED: Negative argument passed " + & REAL'image(arg) severity error; + return result; + end if; + presult := arg; + if presult >= (2.0**(left_index+1)) then + assert NO_WARNING report "fixed_pkg:" + & "TO_UFIXED(REAL): vector truncated" + severity warning; + if overflow_style = fixed_wrap then + presult := presult mod (2.0**(left_index+1)); -- wrap + else + return saturate (result'high, result'low); + end if; + end if; + for i in Xresult'range loop + if presult >= 2.0**i then + Xresult(i) := '1'; + presult := presult - 2.0**i; + else + Xresult(i) := '0'; + end if; + end loop; + if guard_bits > 0 and round_style = fixed_round then + result := round_fixed (arg => Xresult (left_index + downto right_index), + remainder => Xresult (right_index-1 downto + right_index-guard_bits), + overflow_style => overflow_style); + else + result := Xresult (result'range); + end if; + return result; + end function to_ufixed; + + function to_sfixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return UNRESOLVED_sfixed is + constant fw : INTEGER := mins (right_index, right_index); -- catch literals + variable result : UNRESOLVED_sfixed (left_index downto fw) := + (others => '0'); + variable Xresult : UNRESOLVED_sfixed (left_index+1 downto fw-guard_bits) := + (others => '0'); + variable presult : REAL; + begin + if (left_index < fw) then -- null range + return NASF; + end if; + if (arg >= (2.0**left_index) or arg < -(2.0**left_index)) then + assert NO_WARNING report "fixed_pkg:" + & "TO_SFIXED(REAL): vector truncated" + severity warning; + if overflow_style = fixed_saturate then + if arg < 0.0 then -- saturate + result := not saturate (result'high, result'low); -- underflow + else + result := saturate (result'high, result'low); -- overflow + end if; + return result; + else + presult := abs(arg) mod (2.0**(left_index+1)); -- wrap + end if; + else + presult := abs(arg); + end if; + for i in Xresult'range loop + if presult >= 2.0**i then + Xresult(i) := '1'; + presult := presult - 2.0**i; + else + Xresult(i) := '0'; + end if; + end loop; + if arg < 0.0 then + Xresult := to_fixed(-to_s(Xresult), Xresult'high, Xresult'low); + end if; + if guard_bits > 0 and round_style = fixed_round then + result := round_fixed (arg => Xresult (left_index + downto right_index), + remainder => Xresult (right_index-1 downto + right_index-guard_bits), + overflow_style => overflow_style); + else + result := Xresult (result'range); + end if; + return result; + end function to_sfixed; + + function to_ufixed ( + arg : UNSIGNED; -- unsigned + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; + variable result : UNRESOLVED_ufixed (left_index downto right_index); + begin + if arg'length < 1 or (left_index < right_index) then + return NAUF; + end if; + result := resize (arg => UNRESOLVED_ufixed (XARG), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_ufixed; + + -- converted version + function to_ufixed ( + arg : UNSIGNED) -- unsigned + return UNRESOLVED_ufixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; + begin + if arg'length < 1 then + return NAUF; + end if; + return UNRESOLVED_ufixed(xarg); + end function to_ufixed; + + function to_sfixed ( + arg : SIGNED; -- signed + constant left_index : INTEGER; -- left index (high index) + constant right_index : INTEGER := 0; -- right index + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; + variable result : UNRESOLVED_sfixed (left_index downto right_index); + begin + if arg'length < 1 or (left_index < right_index) then + return NASF; + end if; + result := resize (arg => UNRESOLVED_sfixed (XARG), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_sfixed; + + -- converted version + function to_sfixed ( + arg : SIGNED) -- signed + return UNRESOLVED_sfixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; + begin + if arg'length < 1 then + return NASF; + end if; + return UNRESOLVED_sfixed(xarg); + end function to_sfixed; + + function to_sfixed (arg : UNRESOLVED_ufixed) return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (arg'high+1 downto arg'low); + begin + if arg'length < 1 then + return NASF; + end if; + result (arg'high downto arg'low) := UNRESOLVED_sfixed(cleanvec(arg)); + result (arg'high+1) := '0'; + return result; + end function to_sfixed; + + -- Because of the fairly complicated sizing rules in the fixed point + -- packages these functions are provided to compute the result ranges + -- Example: + -- signal uf1 : ufixed (3 downto -3); + -- signal uf2 : ufixed (4 downto -2); + -- signal uf1multuf2 : ufixed (ufixed_high (3, -3, '*', 4, -2) downto + -- ufixed_low (3, -3, '*', 4, -2)); + -- uf1multuf2 <= uf1 * uf2; + -- Valid characters: '+', '-', '*', '/', 'r' or 'R' (rem), 'm' or 'M' (mod), + -- '1' (reciprocal), 'A', 'a' (abs), 'N', 'n' (-sfixed) + function ufixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return maximum (left_index, left_index2) + 1; + when '*' => return left_index + left_index2 + 1; + when '/' => return left_index - right_index2; + when '1' => return -right_index; -- reciprocal + when 'R'|'r' => return mins (left_index, left_index2); -- "rem" + when 'M'|'m' => return mins (left_index, left_index2); -- "mod" + when others => return left_index; -- For abs and default + end case; + end function ufixed_high; + + function ufixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return mins (right_index, right_index2); + when '*' => return right_index + right_index2; + when '/' => return right_index - left_index2 - 1; + when '1' => return -left_index - 1; -- reciprocal + when 'R'|'r' => return mins (right_index, right_index2); -- "rem" + when 'M'|'m' => return mins (right_index, right_index2); -- "mod" + when others => return right_index; -- for abs and default + end case; + end function ufixed_low; + + function sfixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return maximum (left_index, left_index2) + 1; + when '*' => return left_index + left_index2 + 1; + when '/' => return left_index - right_index2 + 1; + when '1' => return -right_index + 1; -- reciprocal + when 'R'|'r' => return mins (left_index, left_index2); -- "rem" + when 'M'|'m' => return left_index2; -- "mod" + when 'A'|'a' => return left_index + 1; -- "abs" + when 'N'|'n' => return left_index + 1; -- -sfixed + when others => return left_index; + end case; + end function sfixed_high; + + function sfixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return mins (right_index, right_index2); + when '*' => return right_index + right_index2; + when '/' => return right_index - left_index2; + when '1' => return -left_index; -- reciprocal + when 'R'|'r' => return mins (right_index, right_index2); -- "rem" + when 'M'|'m' => return mins (right_index, right_index2); -- "mod" + when others => return right_index; -- default for abs, neg and default + end case; + end function sfixed_low; + + -- Same as above, but using the "size_res" input only for their ranges: + -- signal uf1multuf2 : ufixed (ufixed_high (uf1, '*', uf2) downto + -- ufixed_low (uf1, '*', uf2)); + -- uf1multuf2 <= uf1 * uf2; + function ufixed_high (size_res : UNRESOLVED_ufixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_ufixed) + return INTEGER is + begin + return ufixed_high (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function ufixed_high; + + function ufixed_low (size_res : UNRESOLVED_ufixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_ufixed) + return INTEGER is + begin + return ufixed_low (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function ufixed_low; + + function sfixed_high (size_res : UNRESOLVED_sfixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_sfixed) + return INTEGER is + begin + return sfixed_high (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function sfixed_high; + + function sfixed_low (size_res : UNRESOLVED_sfixed; + operation : CHARACTER := 'X'; + size_res2 : UNRESOLVED_sfixed) + return INTEGER is + begin + return sfixed_low (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function sfixed_low; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed is + constant sat : UNRESOLVED_ufixed (left_index downto right_index) := + (others => '1'); + begin + return sat; + end function saturate; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed is + variable sat : UNRESOLVED_sfixed (left_index downto right_index) := + (others => '1'); + begin + -- saturate positive, to saturate negative, just do "not saturate()" + sat (left_index) := '0'; + return sat; + end function saturate; + + function saturate ( + size_res : UNRESOLVED_ufixed) -- only the size of this is used + return UNRESOLVED_ufixed is + begin + return saturate (size_res'high, size_res'low); + end function saturate; + + function saturate ( + size_res : UNRESOLVED_sfixed) -- only the size of this is used + return UNRESOLVED_sfixed is + begin + return saturate (size_res'high, size_res'low); + end function saturate; + + -- As a concession to those who use a graphical DSP environment, + -- these functions take parameters in those tools format and create + -- fixed point numbers. These functions are designed to convert from + -- a std_logic_vector to the VHDL fixed point format using the conventions + -- of these packages. In a pure VHDL environment you should use the + -- "to_ufixed" and "to_sfixed" routines. + -- Unsigned fixed point + function to_UFix ( + arg : STD_ULOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (width-fraction-1 downto -fraction); + begin + if (arg'length /= result'length) then + report "fixed_pkg:" + & "TO_UFIX (STD_ULOGIC_VECTOR) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NAUF; + else + result := to_ufixed (arg, result'high, result'low); + return result; + end if; + end function to_UFix; + + -- signed fixed point + function to_SFix ( + arg : STD_ULOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (width-fraction-1 downto -fraction); + begin + if (arg'length /= result'length) then + report "fixed_pkg:" + & "TO_SFIX (STD_ULOGIC_VECTOR) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NASF; + else + result := to_sfixed (arg, result'high, result'low); + return result; + end if; + end function to_SFix; + + -- finding the bounds of a number. These functions can be used like this: + -- signal xxx : ufixed (7 downto -3); + -- -- Which is the same as "ufixed (UFix_high (11,3) downto UFix_low(11,3))" + -- signal yyy : ufixed (UFix_high (11, 3, "+", 11, 3) + -- downto UFix_low(11, 3, "+", 11, 3)); + -- Where "11" is the width of xxx (xxx'length), + -- and 3 is the lower bound (abs (xxx'low)) + -- In a pure VHDL environment use "ufixed_high" and "ufixed_low" + function ufix_high ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return ufixed_high (left_index => width - 1 - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - 1 - fraction2, + right_index2 => -fraction2); + end function ufix_high; + + function ufix_low ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return ufixed_low (left_index => width - 1 - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - 1 - fraction2, + right_index2 => -fraction2); + end function ufix_low; + + function sfix_high ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return sfixed_high (left_index => width - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - fraction2, + right_index2 => -fraction2); + end function sfix_high; + + function sfix_low ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return sfixed_low (left_index => width - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - fraction2, + right_index2 => -fraction2); + end function sfix_low; + + function to_unsigned ( + arg : UNRESOLVED_ufixed; -- ufixed point input + constant size : NATURAL; -- length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNSIGNED is + begin + return to_uns(resize (arg => arg, + left_index => size-1, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + end function to_unsigned; + + function to_unsigned ( + arg : UNRESOLVED_ufixed; -- ufixed point input + size_res : UNSIGNED; -- length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNSIGNED is + begin + return to_unsigned (arg => arg, + size => size_res'length, + round_style => round_style, + overflow_style => overflow_style); + end function to_unsigned; + + function to_signed ( + arg : UNRESOLVED_sfixed; -- sfixed point input + constant size : NATURAL; -- length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return SIGNED is + begin + return to_s(resize (arg => arg, + left_index => size-1, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + end function to_signed; + + function to_signed ( + arg : UNRESOLVED_sfixed; -- sfixed point input + size_res : SIGNED; -- used for length of output + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return SIGNED is + begin + return to_signed (arg => arg, + size => size_res'length, + round_style => round_style, + overflow_style => overflow_style); + end function to_signed; + + function to_real ( + arg : UNRESOLVED_ufixed) -- ufixed point input + return REAL is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := arg'low; + variable result : REAL; -- result + variable arg_int : UNRESOLVED_ufixed (left_index downto right_index); + begin + if (arg'length < 1) then + return 0.0; + end if; + arg_int := to_x01(cleanvec(arg)); + if (Is_X(arg_int)) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_REAL (ufixed): metavalue detected, returning 0.0" + severity warning; + return 0.0; + end if; + result := 0.0; + for i in arg_int'range loop + if (arg_int(i) = '1') then + result := result + (2.0**i); + end if; + end loop; + return result; + end function to_real; + + function to_real ( + arg : UNRESOLVED_sfixed) -- ufixed point input + return REAL is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := arg'low; + variable result : REAL; -- result + variable arg_int : UNRESOLVED_sfixed (left_index downto right_index); + -- unsigned version of argument + variable arg_uns : UNRESOLVED_ufixed (left_index downto right_index); + -- absolute of argument + begin + if (arg'length < 1) then + return 0.0; + end if; + arg_int := to_x01(cleanvec(arg)); + if (Is_X(arg_int)) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_REAL (sfixed): metavalue detected, returning 0.0" + severity warning; + return 0.0; + end if; + arg_uns := to_ufixed (arg_int); + result := to_real (arg_uns); + if (arg_int(arg_int'high) = '1') then + result := -result; + end if; + return result; + end function to_real; + + function to_integer ( + arg : UNRESOLVED_ufixed; -- fixed point input + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return NATURAL is + constant left_index : INTEGER := arg'high; + variable arg_uns : UNSIGNED (left_index+1 downto 0) + := (others => '0'); + begin + if (arg'length < 1) then + return 0; + end if; + if (Is_X (arg)) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_INTEGER (ufixed): metavalue detected, returning 0" + severity warning; + return 0; + end if; + if (left_index < -1) then + return 0; + end if; + arg_uns := to_uns(resize (arg => arg, + left_index => arg_uns'high, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + return to_integer (arg_uns); + end function to_integer; + + function to_integer ( + arg : UNRESOLVED_sfixed; -- fixed point input + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return INTEGER is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := arg'low; + variable arg_s : SIGNED (left_index+1 downto 0); + begin + if (arg'length < 1) then + return 0; + end if; + if (Is_X (arg)) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_INTEGER (sfixed): metavalue detected, returning 0" + severity warning; + return 0; + end if; + if (left_index < -1) then + return 0; + end if; + arg_s := to_s(resize (arg => arg, + left_index => arg_s'high, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + return to_integer (arg_s); + end function to_integer; + + function to_01 ( + s : UNRESOLVED_ufixed; -- ufixed point input + constant XMAP : STD_ULOGIC := '0') -- Map x to + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (s'range); -- result + begin + if (s'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_01(ufixed): null detected, returning NULL" + severity warning; + return NAUF; + end if; + return to_fixed (to_01(to_uns(s), XMAP), s'high, s'low); + end function to_01; + + function to_01 ( + s : UNRESOLVED_sfixed; -- sfixed point input + constant XMAP : STD_ULOGIC := '0') -- Map x to + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (s'range); + begin + if (s'length < 1) then + assert NO_WARNING + report "fixed_pkg:" + & "TO_01(sfixed): null detected, returning NULL" + severity warning; + return NASF; + end if; + return to_fixed (to_01(to_s(s), XMAP), s'high, s'low); + end function to_01; + + function Is_X ( + arg : UNRESOLVED_ufixed) + return BOOLEAN is + variable argslv : STD_ULOGIC_VECTOR (arg'length-1 downto 0); -- slv + begin + argslv := to_sulv(arg); + return Is_X (argslv); + end function Is_X; + + function Is_X ( + arg : UNRESOLVED_sfixed) + return BOOLEAN is + variable argslv : STD_ULOGIC_VECTOR (arg'length-1 downto 0); -- slv + begin + argslv := to_sulv(arg); + return Is_X (argslv); + end function Is_X; + + function To_X01 ( + arg : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return to_ufixed (To_X01(to_sulv(arg)), arg'high, arg'low); + end function To_X01; + + function to_X01 ( + arg : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return to_sfixed (To_X01(to_sulv(arg)), arg'high, arg'low); + end function To_X01; + + function To_X01Z ( + arg : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return to_ufixed (To_X01Z(to_sulv(arg)), arg'high, arg'low); + end function To_X01Z; + + function to_X01Z ( + arg : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return to_sfixed (To_X01Z(to_sulv(arg)), arg'high, arg'low); + end function To_X01Z; + + function To_UX01 ( + arg : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return to_ufixed (To_UX01(to_sulv(arg)), arg'high, arg'low); + end function To_UX01; + + function to_UX01 ( + arg : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return to_sfixed (To_UX01(to_sulv(arg)), arg'high, arg'low); + end function To_UX01; + + function resize ( + arg : UNRESOLVED_ufixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant arghigh : INTEGER := maximum (arg'high, arg'low); + constant arglow : INTEGER := mine (arg'high, arg'low); + variable invec : UNRESOLVED_ufixed (arghigh downto arglow); + variable result : UNRESOLVED_ufixed(left_index downto right_index) := + (others => '0'); + variable needs_rounding : BOOLEAN := false; + begin -- resize + if (arg'length < 1) or (result'length < 1) then + return NAUF; + elsif (invec'length < 1) then + return result; -- string literal value + else + invec := cleanvec(arg); + if (right_index > arghigh) then -- return top zeros + needs_rounding := (round_style = fixed_round) and + (right_index = arghigh+1); + elsif (left_index < arglow) then -- return overflow + if (overflow_style = fixed_saturate) and + (or_reduce(to_sulv(invec)) = '1') then + result := saturate (result'high, result'low); -- saturate + end if; + elsif (arghigh > left_index) then + -- wrap or saturate? + if (overflow_style = fixed_saturate and + or_reduce (to_sulv(invec(arghigh downto left_index+1))) = '1') + then + result := saturate (result'high, result'low); -- saturate + else + if (arglow >= right_index) then + result (left_index downto arglow) := + invec(left_index downto arglow); + else + result (left_index downto right_index) := + invec (left_index downto right_index); + needs_rounding := (round_style = fixed_round); -- round + end if; + end if; + else -- arghigh <= integer width + if (arglow >= right_index) then + result (arghigh downto arglow) := invec; + else + result (arghigh downto right_index) := + invec (arghigh downto right_index); + needs_rounding := (round_style = fixed_round); -- round + end if; + end if; + -- Round result + if needs_rounding then + result := round_fixed (arg => result, + remainder => invec (right_index-1 + downto arglow), + overflow_style => overflow_style); + end if; + return result; + end if; + end function resize; + + function resize ( + arg : UNRESOLVED_sfixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant arghigh : INTEGER := maximum (arg'high, arg'low); + constant arglow : INTEGER := mine (arg'high, arg'low); + variable invec : UNRESOLVED_sfixed (arghigh downto arglow); + variable result : UNRESOLVED_sfixed(left_index downto right_index) := + (others => '0'); + variable reduced : STD_ULOGIC; + variable needs_rounding : BOOLEAN := false; -- rounding + begin -- resize + if (arg'length < 1) or (result'length < 1) then + return NASF; + elsif (invec'length < 1) then + return result; -- string literal value + else + invec := cleanvec(arg); + if (right_index > arghigh) then -- return top zeros + if (arg'low /= INTEGER'low) then -- check for a literal + result := (others => arg(arghigh)); -- sign extend + end if; + needs_rounding := (round_style = fixed_round) and + (right_index = arghigh+1); + elsif (left_index < arglow) then -- return overflow + if (overflow_style = fixed_saturate) then + reduced := or_reduce (to_sulv(invec)); + if (reduced = '1') then + if (invec(arghigh) = '0') then + -- saturate POSITIVE + result := saturate (result'high, result'low); + else + -- saturate negative + result := not saturate (result'high, result'low); + end if; + -- else return 0 (input was 0) + end if; + -- else return 0 (wrap) + end if; + elsif (arghigh > left_index) then + if (invec(arghigh) = '0') then + reduced := or_reduce (to_sulv(invec(arghigh-1 downto + left_index))); + if overflow_style = fixed_saturate and reduced = '1' then + -- saturate positive + result := saturate (result'high, result'low); + else + if (right_index > arglow) then + result := invec (left_index downto right_index); + needs_rounding := (round_style = fixed_round); + else + result (left_index downto arglow) := + invec (left_index downto arglow); + end if; + end if; + else + reduced := and_reduce (to_sulv(invec(arghigh-1 downto + left_index))); + if overflow_style = fixed_saturate and reduced = '0' then + result := not saturate (result'high, result'low); + else + if (right_index > arglow) then + result := invec (left_index downto right_index); + needs_rounding := (round_style = fixed_round); + else + result (left_index downto arglow) := + invec (left_index downto arglow); + end if; + end if; + end if; + else -- arghigh <= integer width + if (arglow >= right_index) then + result (arghigh downto arglow) := invec; + else + result (arghigh downto right_index) := + invec (arghigh downto right_index); + needs_rounding := (round_style = fixed_round); -- round + end if; + if (left_index > arghigh) then -- sign extend + result(left_index downto arghigh+1) := (others => invec(arghigh)); + end if; + end if; + -- Round result + if (needs_rounding) then + result := round_fixed (arg => result, + remainder => invec (right_index-1 + downto arglow), + overflow_style => overflow_style); + end if; + return result; + end if; + end function resize; + + -- size_res functions + -- These functions compute the size from a passed variable named "size_res" + -- The only part of this variable used it it's size, it is never passed + -- to a lower level routine. + function to_ufixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_ufixed) -- for size only + return UNRESOLVED_ufixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_ufixed (size_res'left downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NAUF; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_sfixed) -- for size only + return UNRESOLVED_sfixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_sfixed (size_res'left downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NASF; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low); + return result; + end if; + end function to_sfixed; + + function to_ufixed ( + arg : NATURAL; -- integer + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_ufixed (size_res'left downto fw); + begin + if (result'length < 1) then + return NAUF; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : INTEGER; -- integer + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_sfixed (size_res'left downto fw); + begin + if (result'length < 1) then + return NASF; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_sfixed; + + function to_ufixed ( + arg : REAL; -- real + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return UNRESOLVED_ufixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_ufixed (size_res'left downto fw); + begin + if (result'length < 1) then + return NAUF; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + guard_bits => guard_bits, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : REAL; -- real + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return UNRESOLVED_sfixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_sfixed (size_res'left downto fw); + begin + if (result'length < 1) then + return NASF; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + guard_bits => guard_bits, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_sfixed; + + function to_ufixed ( + arg : UNSIGNED; -- unsigned + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_ufixed (size_res'left downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NAUF; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : SIGNED; -- signed + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_sfixed (size_res'left downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NASF; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_sfixed; + + function resize ( + arg : UNRESOLVED_ufixed; -- input + size_res : UNRESOLVED_ufixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_ufixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_ufixed (size_res'high downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NAUF; + else + result := resize (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function resize; + + function resize ( + arg : UNRESOLVED_sfixed; -- input + size_res : UNRESOLVED_sfixed; -- for size only + constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; + constant round_style : fixed_round_style_type := fixed_round_style) + return UNRESOLVED_sfixed is + constant fw : INTEGER := mine (size_res'low, size_res'low); -- catch literals + variable result : UNRESOLVED_sfixed (size_res'high downto fw); + begin + if (result'length < 1 or arg'length < 1) then + return NASF; + else + result := resize (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function resize; + + -- Overloaded math functions for real + function "+" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : REAL) + return UNRESOLVED_ufixed is + begin + return (l + to_ufixed (r, l'high, l'low)); + end function "+"; + + function "+" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, r'low) + r); + end function "+"; + + function "+" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : REAL) + return UNRESOLVED_sfixed is + begin + return (l + to_sfixed (r, l'high, l'low)); + end function "+"; + + function "+" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, r'low) + r); + end function "+"; + + function "-" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : REAL) + return UNRESOLVED_ufixed is + begin + return (l - to_ufixed (r, l'high, l'low)); + end function "-"; + + function "-" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, r'low) - r); + end function "-"; + + function "-" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : REAL) + return UNRESOLVED_sfixed is + begin + return (l - to_sfixed (r, l'high, l'low)); + end function "-"; + + function "-" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, r'low) - r); + end function "-"; + + function "*" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : REAL) + return UNRESOLVED_ufixed is + begin + return (l * to_ufixed (r, l'high, l'low)); + end function "*"; + + function "*" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, r'low) * r); + end function "*"; + + function "*" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : REAL) + return UNRESOLVED_sfixed is + begin + return (l * to_sfixed (r, l'high, l'low)); + end function "*"; + + function "*" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, r'low) * r); + end function "*"; + +-- function "/" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l / to_ufixed (r, l'high, l'low)); +-- end function "/"; + +-- function "/" ( +-- l : REAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, r'low) / r); +-- end function "/"; + +-- function "/" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l / to_sfixed (r, l'high, l'low)); +-- end function "/"; + +-- function "/" ( +-- l : REAL; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, r'low) / r); +-- end function "/"; + +-- function "rem" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l rem to_ufixed (r, l'high, l'low)); +-- end function "rem"; + +-- function "rem" ( +-- l : REAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, r'low) rem r); +-- end function "rem"; + +-- function "rem" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l rem to_sfixed (r, l'high, l'low)); +-- end function "rem"; + +-- function "rem" ( +-- l : REAL; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, r'low) rem r); +-- end function "rem"; + +-- function "mod" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l mod to_ufixed (r, l'high, l'low)); +-- end function "mod"; + +-- function "mod" ( +-- l : REAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, r'low) mod r); +-- end function "mod"; + +-- function "mod" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : REAL) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l mod to_sfixed (r, l'high, l'low)); +-- end function "mod"; + +-- function "mod" ( +-- l : REAL; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, r'low) mod r); +-- end function "mod"; + + -- Overloaded math functions for integers + function "+" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : NATURAL) + return UNRESOLVED_ufixed is + begin + return (l + to_ufixed (r, l'high, 0)); + end function "+"; + + function "+" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, 0) + r); + end function "+"; + + function "+" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : INTEGER) + return UNRESOLVED_sfixed is + begin + return (l + to_sfixed (r, l'high, 0)); + end function "+"; + + function "+" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, 0) + r); + end function "+"; + + -- Overloaded functions + function "-" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : NATURAL) + return UNRESOLVED_ufixed is + begin + return (l - to_ufixed (r, l'high, 0)); + end function "-"; + + function "-" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, 0) - r); + end function "-"; + + function "-" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : INTEGER) + return UNRESOLVED_sfixed is + begin + return (l - to_sfixed (r, l'high, 0)); + end function "-"; + + function "-" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, 0) - r); + end function "-"; + + -- Overloaded functions + function "*" ( + l : UNRESOLVED_ufixed; -- fixed point input + r : NATURAL) + return UNRESOLVED_ufixed is + begin + return (l * to_ufixed (r, l'high, 0)); + end function "*"; + + function "*" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return (to_ufixed (l, r'high, 0) * r); + end function "*"; + + function "*" ( + l : UNRESOLVED_sfixed; -- fixed point input + r : INTEGER) + return UNRESOLVED_sfixed is + begin + return (l * to_sfixed (r, l'high, 0)); + end function "*"; + + function "*" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return UNRESOLVED_sfixed is + begin + return (to_sfixed (l, r'high, 0) * r); + end function "*"; + + -- Overloaded functions +-- function "/" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : NATURAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l / to_ufixed (r, l'high, 0)); +-- end function "/"; + +-- function "/" ( +-- l : NATURAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, 0) / r); +-- end function "/"; + +-- function "/" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : INTEGER) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l / to_sfixed (r, l'high, 0)); +-- end function "/"; + +-- function "/" ( +-- l : INTEGER; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, 0) / r); +-- end function "/"; + +-- function "rem" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : NATURAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l rem to_ufixed (r, l'high, 0)); +-- end function "rem"; + +-- function "rem" ( +-- l : NATURAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, 0) rem r); +-- end function "rem"; + +-- function "rem" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : INTEGER) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l rem to_sfixed (r, l'high, 0)); +-- end function "rem"; + +-- function "rem" ( +-- l : INTEGER; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, 0) rem r); +-- end function "rem"; + +-- function "mod" ( +-- l : UNRESOLVED_ufixed; -- fixed point input +-- r : NATURAL) +-- return UNRESOLVED_ufixed is +-- begin +-- return (l mod to_ufixed (r, l'high, 0)); +-- end function "mod"; + +-- function "mod" ( +-- l : NATURAL; +-- r : UNRESOLVED_ufixed) -- fixed point input +-- return UNRESOLVED_ufixed is +-- begin +-- return (to_ufixed (l, r'high, 0) mod r); +-- end function "mod"; + +-- function "mod" ( +-- l : UNRESOLVED_sfixed; -- fixed point input +-- r : INTEGER) +-- return UNRESOLVED_sfixed is +-- begin +-- return (l mod to_sfixed (r, l'high, 0)); +-- end function "mod"; + +-- function "mod" ( +-- l : INTEGER; +-- r : UNRESOLVED_sfixed) -- fixed point input +-- return UNRESOLVED_sfixed is +-- begin +-- return (to_sfixed (l, r'high, 0) mod r); +-- end function "mod"; + + -- overloaded ufixed compare functions with integer + function "=" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l = to_ufixed (r, l'high, l'low)); + end function "="; + + function "/=" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l /= to_ufixed (r, l'high, l'low)); + end function "/="; + + function ">=" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l >= to_ufixed (r, l'high, l'low)); + end function ">="; + + function "<=" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l <= to_ufixed (r, l'high, l'low)); + end function "<="; + + function ">" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l > to_ufixed (r, l'high, l'low)); + end function ">"; + + function "<" ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l < to_ufixed (r, l'high, l'low)); + end function "<"; + + function \?=\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?=\ (l, to_ufixed (r, l'high, l'low)); + end function \?=\; + + function \?/=\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?/=\ (l, to_ufixed (r, l'high, l'low)); + end function \?/=\; + + function \?>=\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?>=\ (l, to_ufixed (r, l'high, l'low)); + end function \?>=\; + + function \?<=\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?<=\ (l, to_ufixed (r, l'high, l'low)); + end function \?<=\; + + function \?>\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?>\ (l, to_ufixed (r, l'high, l'low)); + end function \?>\; + + function \?<\ ( + l : UNRESOLVED_ufixed; + r : NATURAL) -- fixed point input + return STD_ULOGIC is + begin + return \?<\ (l, to_ufixed (r, l'high, l'low)); + end function \?<\; + + function maximum ( + l : UNRESOLVED_ufixed; -- fixed point input + r : NATURAL) + return UNRESOLVED_ufixed is + begin + return maximum (l, to_ufixed (r, l'high, l'low)); + end function maximum; + + function minimum ( + l : UNRESOLVED_ufixed; -- fixed point input + r : NATURAL) + return UNRESOLVED_ufixed is + begin + return minimum (l, to_ufixed (r, l'high, l'low)); + end function minimum; + + -- NATURAL to ufixed + function "=" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) = r); + end function "="; + + function "/=" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) /= r); + end function "/="; + + function ">=" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) >= r); + end function ">="; + + function "<=" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) <= r); + end function "<="; + + function ">" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) > r); + end function ">"; + + function "<" ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) < r); + end function "<"; + + function \?=\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?=\ (to_ufixed (l, r'high, r'low), r); + end function \?=\; + + function \?/=\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?/=\ (to_ufixed (l, r'high, r'low), r); + end function \?/=\; + + function \?>=\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>=\ (to_ufixed (l, r'high, r'low), r); + end function \?>=\; + + function \?<=\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<=\ (to_ufixed (l, r'high, r'low), r); + end function \?<=\; + + function \?>\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>\ (to_ufixed (l, r'high, r'low), r); + end function \?>\; + + function \?<\ ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<\ (to_ufixed (l, r'high, r'low), r); + end function \?<\; + + function maximum ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return maximum (to_ufixed (l, r'high, r'low), r); + end function maximum; + + function minimum ( + l : NATURAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return minimum (to_ufixed (l, r'high, r'low), r); + end function minimum; + + -- overloaded ufixed compare functions with real + function "=" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l = to_ufixed (r, l'high, l'low)); + end function "="; + + function "/=" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l /= to_ufixed (r, l'high, l'low)); + end function "/="; + + function ">=" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l >= to_ufixed (r, l'high, l'low)); + end function ">="; + + function "<=" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l <= to_ufixed (r, l'high, l'low)); + end function "<="; + + function ">" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l > to_ufixed (r, l'high, l'low)); + end function ">"; + + function "<" ( + l : UNRESOLVED_ufixed; + r : REAL) + return BOOLEAN is + begin + return (l < to_ufixed (r, l'high, l'low)); + end function "<"; + + function \?=\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?=\ (l, to_ufixed (r, l'high, l'low)); + end function \?=\; + + function \?/=\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?/=\ (l, to_ufixed (r, l'high, l'low)); + end function \?/=\; + + function \?>=\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?>=\ (l, to_ufixed (r, l'high, l'low)); + end function \?>=\; + + function \?<=\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?<=\ (l, to_ufixed (r, l'high, l'low)); + end function \?<=\; + + function \?>\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?>\ (l, to_ufixed (r, l'high, l'low)); + end function \?>\; + + function \?<\ ( + l : UNRESOLVED_ufixed; + r : REAL) + return STD_ULOGIC is + begin + return \?<\ (l, to_ufixed (r, l'high, l'low)); + end function \?<\; + + function maximum ( + l : UNRESOLVED_ufixed; + r : REAL) + return UNRESOLVED_ufixed is + begin + return maximum (l, to_ufixed (r, l'high, l'low)); + end function maximum; + + function minimum ( + l : UNRESOLVED_ufixed; + r : REAL) + return UNRESOLVED_ufixed is + begin + return minimum (l, to_ufixed (r, l'high, l'low)); + end function minimum; + + -- real and ufixed + function "=" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) = r); + end function "="; + + function "/=" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) /= r); + end function "/="; + + function ">=" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) >= r); + end function ">="; + + function "<=" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) <= r); + end function "<="; + + function ">" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) > r); + end function ">"; + + function "<" ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (l, r'high, r'low) < r); + end function "<"; + + function \?=\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?=\ (to_ufixed (l, r'high, r'low), r); + end function \?=\; + + function \?/=\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?/=\ (to_ufixed (l, r'high, r'low), r); + end function \?/=\; + + function \?>=\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>=\ (to_ufixed (l, r'high, r'low), r); + end function \?>=\; + + function \?<=\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<=\ (to_ufixed (l, r'high, r'low), r); + end function \?<=\; + + function \?>\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>\ (to_ufixed (l, r'high, r'low), r); + end function \?>\; + + function \?<\ ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<\ (to_ufixed (l, r'high, r'low), r); + end function \?<\; + + function maximum ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return maximum (to_ufixed (l, r'high, r'low), r); + end function maximum; + + function minimum ( + l : REAL; + r : UNRESOLVED_ufixed) -- fixed point input + return UNRESOLVED_ufixed is + begin + return minimum (to_ufixed (l, r'high, r'low), r); + end function minimum; + + -- overloaded sfixed compare functions with integer + function "=" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l = to_sfixed (r, l'high, l'low)); + end function "="; + + function "/=" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l /= to_sfixed (r, l'high, l'low)); + end function "/="; + + function ">=" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l >= to_sfixed (r, l'high, l'low)); + end function ">="; + + function "<=" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l <= to_sfixed (r, l'high, l'low)); + end function "<="; + + function ">" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l > to_sfixed (r, l'high, l'low)); + end function ">"; + + function "<" ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return BOOLEAN is + begin + return (l < to_sfixed (r, l'high, l'low)); + end function "<"; + + function \?=\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?=\ (l, to_sfixed (r, l'high, l'low)); + end function \?=\; + + function \?/=\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?/=\ (l, to_sfixed (r, l'high, l'low)); + end function \?/=\; + + function \?>=\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?>=\ (l, to_sfixed (r, l'high, l'low)); + end function \?>=\; + + function \?<=\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?<=\ (l, to_sfixed (r, l'high, l'low)); + end function \?<=\; + + function \?>\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?>\ (l, to_sfixed (r, l'high, l'low)); + end function \?>\; + + function \?<\ ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return STD_ULOGIC is + begin + return \?<\ (l, to_sfixed (r, l'high, l'low)); + end function \?<\; + + function maximum ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return UNRESOLVED_sfixed is + begin + return maximum (l, to_sfixed (r, l'high, l'low)); + end function maximum; + + function minimum ( + l : UNRESOLVED_sfixed; + r : INTEGER) + return UNRESOLVED_sfixed is + begin + return minimum (l, to_sfixed (r, l'high, l'low)); + end function minimum; + + -- integer and sfixed + function "=" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) = r); + end function "="; + + function "/=" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) /= r); + end function "/="; + + function ">=" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) >= r); + end function ">="; + + function "<=" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) <= r); + end function "<="; + + function ">" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) > r); + end function ">"; + + function "<" ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) < r); + end function "<"; + + function \?=\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?=\ (to_sfixed (l, r'high, r'low), r); + end function \?=\; + + function \?/=\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?/=\ (to_sfixed (l, r'high, r'low), r); + end function \?/=\; + + function \?>=\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>=\ (to_sfixed (l, r'high, r'low), r); + end function \?>=\; + + function \?<=\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<=\ (to_sfixed (l, r'high, r'low), r); + end function \?<=\; + + function \?>\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>\ (to_sfixed (l, r'high, r'low), r); + end function \?>\; + + function \?<\ ( + l : INTEGER; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<\ (to_sfixed (l, r'high, r'low), r); + end function \?<\; + + function maximum ( + l : INTEGER; + r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return maximum (to_sfixed (l, r'high, r'low), r); + end function maximum; + + function minimum ( + l : INTEGER; + r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return minimum (to_sfixed (l, r'high, r'low), r); + end function minimum; + + -- overloaded sfixed compare functions with real + function "=" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l = to_sfixed (r, l'high, l'low)); + end function "="; + + function "/=" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l /= to_sfixed (r, l'high, l'low)); + end function "/="; + + function ">=" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l >= to_sfixed (r, l'high, l'low)); + end function ">="; + + function "<=" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l <= to_sfixed (r, l'high, l'low)); + end function "<="; + + function ">" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l > to_sfixed (r, l'high, l'low)); + end function ">"; + + function "<" ( + l : UNRESOLVED_sfixed; + r : REAL) + return BOOLEAN is + begin + return (l < to_sfixed (r, l'high, l'low)); + end function "<"; + + function \?=\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?=\ (l, to_sfixed (r, l'high, l'low)); + end function \?=\; + + function \?/=\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?/=\ (l, to_sfixed (r, l'high, l'low)); + end function \?/=\; + + function \?>=\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?>=\ (l, to_sfixed (r, l'high, l'low)); + end function \?>=\; + + function \?<=\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?<=\ (l, to_sfixed (r, l'high, l'low)); + end function \?<=\; + + function \?>\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?>\ (l, to_sfixed (r, l'high, l'low)); + end function \?>\; + + function \?<\ ( + l : UNRESOLVED_sfixed; + r : REAL) + return STD_ULOGIC is + begin + return \?<\ (l, to_sfixed (r, l'high, l'low)); + end function \?<\; + + function maximum ( + l : UNRESOLVED_sfixed; + r : REAL) + return UNRESOLVED_sfixed is + begin + return maximum (l, to_sfixed (r, l'high, l'low)); + end function maximum; + + function minimum ( + l : UNRESOLVED_sfixed; + r : REAL) + return UNRESOLVED_sfixed is + begin + return minimum (l, to_sfixed (r, l'high, l'low)); + end function minimum; + + -- REAL and sfixed + function "=" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) = r); + end function "="; + + function "/=" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) /= r); + end function "/="; + + function ">=" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) >= r); + end function ">="; + + function "<=" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) <= r); + end function "<="; + + function ">" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) > r); + end function ">"; + + function "<" ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (l, r'high, r'low) < r); + end function "<"; + + function \?=\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?=\ (to_sfixed (l, r'high, r'low), r); + end function \?=\; + + function \?/=\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?/=\ (to_sfixed (l, r'high, r'low), r); + end function \?/=\; + + function \?>=\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>=\ (to_sfixed (l, r'high, r'low), r); + end function \?>=\; + + function \?<=\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<=\ (to_sfixed (l, r'high, r'low), r); + end function \?<=\; + + function \?>\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?>\ (to_sfixed (l, r'high, r'low), r); + end function \?>\; + + function \?<\ ( + l : REAL; + r : UNRESOLVED_sfixed) -- fixed point input + return STD_ULOGIC is + begin + return \?<\ (to_sfixed (l, r'high, r'low), r); + end function \?<\; + + function maximum ( + l : REAL; + r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return maximum (to_sfixed (l, r'high, r'low), r); + end function maximum; + + function minimum ( + l : REAL; + r : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return minimum (to_sfixed (l, r'high, r'low), r); + end function minimum; +-- rtl_synthesis off +-- pragma synthesis_off + -- copied from std_logic_textio + type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', error); + type char_indexed_by_MVL9 is array (STD_ULOGIC) of CHARACTER; + type MVL9_indexed_by_char is array (CHARACTER) of STD_ULOGIC; + type MVL9plus_indexed_by_char is array (CHARACTER) of MVL9plus; + + constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-"; + constant char_to_MVL9 : MVL9_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); + constant char_to_MVL9plus : MVL9plus_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => error); + constant NBSP : CHARACTER := CHARACTER'val(160); -- space character + constant NUS : STRING(2 to 1) := (others => ' '); + + -- %%% Replicated Textio functions + procedure Char2TriBits (C : CHARACTER; + RESULT : out STD_ULOGIC_VECTOR(2 downto 0); + GOOD : out BOOLEAN; + ISSUE_ERROR : in BOOLEAN) is + begin + case c is + when '0' => result := o"0"; good := true; + when '1' => result := o"1"; good := true; + when '2' => result := o"2"; good := true; + when '3' => result := o"3"; good := true; + when '4' => result := o"4"; good := true; + when '5' => result := o"5"; good := true; + when '6' => result := o"6"; good := true; + when '7' => result := o"7"; good := true; + when 'Z' => result := "ZZZ"; good := true; + when 'X' => result := "XXX"; good := true; + when others => + assert not ISSUE_ERROR + report "fixed_pkg:" + & "OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + result := "UUU"; + good := false; + end case; + end procedure Char2TriBits; + -- Hex Read and Write procedures for STD_ULOGIC_VECTOR. + -- Modified from the original to be more forgiving. + + procedure Char2QuadBits (C : CHARACTER; + RESULT : out STD_ULOGIC_VECTOR(3 downto 0); + GOOD : out BOOLEAN; + ISSUE_ERROR : in BOOLEAN) is + begin + case c is + when '0' => result := x"0"; good := true; + when '1' => result := x"1"; good := true; + when '2' => result := x"2"; good := true; + when '3' => result := x"3"; good := true; + when '4' => result := x"4"; good := true; + when '5' => result := x"5"; good := true; + when '6' => result := x"6"; good := true; + when '7' => result := x"7"; good := true; + when '8' => result := x"8"; good := true; + when '9' => result := x"9"; good := true; + when 'A' | 'a' => result := x"A"; good := true; + when 'B' | 'b' => result := x"B"; good := true; + when 'C' | 'c' => result := x"C"; good := true; + when 'D' | 'd' => result := x"D"; good := true; + when 'E' | 'e' => result := x"E"; good := true; + when 'F' | 'f' => result := x"F"; good := true; + when 'Z' => result := "ZZZZ"; good := true; + when 'X' => result := "XXXX"; good := true; + when others => + assert not ISSUE_ERROR + report "fixed_pkg:" + & "HREAD Error: Read a '" & c & + "', expected a Hex character (0-F)." + severity error; + result := "UUUU"; + good := false; + end case; + end procedure Char2QuadBits; + + -- purpose: Skips white space + procedure skip_whitespace ( + L : inout LINE) is + variable readOk : BOOLEAN; + variable c : CHARACTER; + begin + while L /= null and L.all'length /= 0 loop + if (L.all(1) = ' ' or L.all(1) = NBSP or L.all(1) = HT) then + read (l, c, readOk); + else + exit; + end if; + end loop; + end procedure skip_whitespace; + + function to_ostring (value : STD_ULOGIC_VECTOR) return STRING is + constant ne : INTEGER := (value'length+2)/3; + variable pad : STD_ULOGIC_VECTOR(0 to (ne*3 - value'length) - 1); + variable ivalue : STD_ULOGIC_VECTOR(0 to ne*3 - 1); + variable result : STRING(1 to ne); + variable tri : STD_ULOGIC_VECTOR(0 to 2); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + tri := To_X01Z(ivalue(3*i to 3*i+2)); + case tri is + when o"0" => result(i+1) := '0'; + when o"1" => result(i+1) := '1'; + when o"2" => result(i+1) := '2'; + when o"3" => result(i+1) := '3'; + when o"4" => result(i+1) := '4'; + when o"5" => result(i+1) := '5'; + when o"6" => result(i+1) := '6'; + when o"7" => result(i+1) := '7'; + when "ZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return result; + end if; + end function to_ostring; + ------------------------------------------------------------------- + function to_hstring (value : STD_ULOGIC_VECTOR) return STRING is + constant ne : INTEGER := (value'length+3)/4; + variable pad : STD_ULOGIC_VECTOR(0 to (ne*4 - value'length) - 1); + variable ivalue : STD_ULOGIC_VECTOR(0 to ne*4 - 1); + variable result : STRING(1 to ne); + variable quad : STD_ULOGIC_VECTOR(0 to 3); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + quad := To_X01Z(ivalue(4*i to 4*i+3)); + case quad is + when x"0" => result(i+1) := '0'; + when x"1" => result(i+1) := '1'; + when x"2" => result(i+1) := '2'; + when x"3" => result(i+1) := '3'; + when x"4" => result(i+1) := '4'; + when x"5" => result(i+1) := '5'; + when x"6" => result(i+1) := '6'; + when x"7" => result(i+1) := '7'; + when x"8" => result(i+1) := '8'; + when x"9" => result(i+1) := '9'; + when x"A" => result(i+1) := 'A'; + when x"B" => result(i+1) := 'B'; + when x"C" => result(i+1) := 'C'; + when x"D" => result(i+1) := 'D'; + when x"E" => result(i+1) := 'E'; + when x"F" => result(i+1) := 'F'; + when "ZZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return result; + end if; + end function to_hstring; + + +-- %%% END replicated textio functions + + -- purpose: writes fixed point into a line + procedure write ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + variable s : STRING(1 to value'length +1) := (others => ' '); + variable sindx : INTEGER; + begin -- function write Example: 0011.1100 + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx + 1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx + 1; + end loop; + write(l, s, justified, field); + end procedure write; + + -- purpose: writes fixed point into a line + procedure write ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + variable s : STRING(1 to value'length +1); + variable sindx : INTEGER; + begin -- function write Example: 0011.1100 + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx + 1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx + 1; + end loop; + write(l, s, justified, field); + end procedure write; + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_ufixed) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable readOk : BOOLEAN; + variable i : INTEGER; -- index variable + variable mv : ufixed (VALUE'range); + variable lastu : BOOLEAN := false; -- last character was an "_" + variable founddot : BOOLEAN := false; -- found a "." + begin -- READ + VALUE := (VALUE'range => 'U'); + Skip_whitespace (L); + if VALUE'length > 0 then -- non Null input string + read (l, c, readOk); + i := value'high; + while i >= VALUE'low loop + if readOk = false then -- Bail out if there was a bad read + report "fixed_pkg:" & "READ(ufixed) " + & "End of string encountered" + severity error; + return; + elsif c = '_' then + if i = value'high then + report "fixed_pkg:" & "READ(ufixed) " + & "String begins with an ""_""" severity error; + return; + elsif lastu then + report "fixed_pkg:" & "READ(ufixed) " + & "Two underscores detected in input string ""__""" + severity error; + return; + else + lastu := true; + end if; + elsif c = '.' then -- binary point + if founddot then + report "fixed_pkg:" & "READ(ufixed) " + & "Two binary points found in input string" severity error; + return; + elsif i /= -1 then -- Seperator in the wrong spot + report "fixed_pkg:" & "READ(ufixed) " + & "Decimal point does not match number format " + severity error; + return; + end if; + founddot := true; + lastu := false; + elsif c = ' ' or c = NBSP or c = HT then -- reading done. + report "fixed_pkg:" & "READ(ufixed) " + & "Short read, Space encounted in input string" + severity error; + return; + elsif char_to_MVL9plus(c) = error then + report "fixed_pkg:" & "READ(ufixed) " + & "Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + return; + else + mv(i) := char_to_MVL9(c); + i := i - 1; + if i < mv'low then + VALUE := mv; + return; + end if; + lastu := false; + end if; + read(L, c, readOk); + end loop; + end if; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable readOk : BOOLEAN; + variable mv : ufixed (VALUE'range); + variable i : INTEGER; -- index variable + variable lastu : BOOLEAN := false; -- last character was an "_" + variable founddot : BOOLEAN := false; -- found a "." + begin -- READ + VALUE := (VALUE'range => 'U'); + Skip_whitespace (L); + if VALUE'length > 0 then + read (l, c, readOk); + i := value'high; + GOOD := false; + while i >= VALUE'low loop + if not readOk then -- Bail out if there was a bad read + return; + elsif c = '_' then + if i = value'high then -- Begins with an "_" + return; + elsif lastu then -- "__" detected + return; + else + lastu := true; + end if; + elsif c = '.' then -- binary point + if founddot then + return; + elsif i /= -1 then -- Seperator in the wrong spot + return; + end if; + founddot := true; + lastu := false; + elsif (char_to_MVL9plus(c) = error) then -- Illegal character/short read + return; + else + mv(i) := char_to_MVL9(c); + i := i - 1; + if i < mv'low then -- reading done + GOOD := true; + VALUE := mv; + return; + end if; + lastu := false; + end if; + read(L, c, readOk); + end loop; + else + GOOD := true; -- read into a null array + end if; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_sfixed) is + variable c : CHARACTER; + variable readOk : BOOLEAN; + variable i : INTEGER; -- index variable + variable mv : sfixed (VALUE'range); + variable lastu : BOOLEAN := false; -- last character was an "_" + variable founddot : BOOLEAN := false; -- found a "." + begin -- READ + VALUE := (VALUE'range => 'U'); + Skip_whitespace (L); + if VALUE'length > 0 then -- non Null input string + read (l, c, readOk); + i := value'high; + while i >= VALUE'low loop + if readOk = false then -- Bail out if there was a bad read + report "fixed_pkg:" & "READ(sfixed) " + & "End of string encountered" + severity error; + return; + elsif c = '_' then + if i = value'high then + report "fixed_pkg:" & "READ(sfixed) " + & "String begins with an ""_""" severity error; + return; + elsif lastu then + report "fixed_pkg:" & "READ(sfixed) " + & "Two underscores detected in input string ""__""" + severity error; + return; + else + lastu := true; + end if; + elsif c = '.' then -- binary point + if founddot then + report "fixed_pkg:" & "READ(sfixed) " + & "Two binary points found in input string" severity error; + return; + elsif i /= -1 then -- Seperator in the wrong spot + report "fixed_pkg:" & "READ(sfixed) " + & "Decimal point does not match number format " + severity error; + return; + end if; + founddot := true; + lastu := false; + elsif c = ' ' or c = NBSP or c = HT then -- reading done. + report "fixed_pkg:" & "READ(sfixed) " + & "Short read, Space encounted in input string" + severity error; + return; + elsif char_to_MVL9plus(c) = error then + report "fixed_pkg:" & "READ(sfixed) " + & "Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + return; + else + mv(i) := char_to_MVL9(c); + i := i - 1; + if i < mv'low then + VALUE := mv; + return; + end if; + lastu := false; + end if; + read(L, c, readOk); + end loop; + end if; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN) is + variable value_ufixed : UNRESOLVED_ufixed (VALUE'range); + begin -- READ + READ (L => L, VALUE => value_ufixed, GOOD => GOOD); + VALUE := UNRESOLVED_sfixed (value_ufixed); + end procedure READ; + + -- octal read and write + procedure owrite ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_ostring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure owrite; + + procedure owrite ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_ostring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure owrite; + + -- purpose: Routines common to the OREAD routines + procedure OREAD_common ( + L : inout LINE; + slv : out STD_ULOGIC_VECTOR; + igood : out BOOLEAN; + idex : out INTEGER; + constant bpoint : in INTEGER; -- binary point + constant message : in BOOLEAN; + constant smath : in BOOLEAN) is + + -- purpose: error message routine + procedure errmes ( + constant mess : in STRING) is -- error message + begin + if message then + if smath then + report "fixed_pkg:" + & "OREAD(sfixed) " + & mess + severity error; + else + report "fixed_pkg:" + & "OREAD(ufixed) " + & mess + severity error; + end if; + end if; + end procedure errmes; + variable xgood : BOOLEAN; + variable nybble : STD_ULOGIC_VECTOR (2 downto 0); -- 3 bits + variable c : CHARACTER; + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + variable founddot : BOOLEAN := false; -- found a dot. + begin + Skip_whitespace (L); + if slv'length > 0 then + i := slv'high; + read (l, c, xgood); + while i > 0 loop + if xgood = false then + errmes ("Error: end of string encountered"); + exit; + elsif c = '_' then + if i = slv'length then + errmes ("Error: String begins with an ""_"""); + xgood := false; + exit; + elsif lastu then + errmes ("Error: Two underscores detected in input string ""__"""); + xgood := false; + exit; + else + lastu := true; + end if; + elsif (c = '.') then + if (i + 1 /= bpoint) then + errmes ("encountered ""."" at wrong index"); + xgood := false; + exit; + elsif i = slv'length then + errmes ("encounted a ""."" at the beginning of the line"); + xgood := false; + exit; + elsif founddot then + errmes ("Two ""."" encounted in input string"); + xgood := false; + exit; + end if; + founddot := true; + lastu := false; + else + Char2triBits(c, nybble, xgood, message); + if not xgood then + exit; + end if; + slv (i downto i-2) := nybble; + i := i - 3; + lastu := false; + end if; + if i > 0 then + read (L, c, xgood); + end if; + end loop; + idex := i; + igood := xgood; + else + igood := true; -- read into a null array + idex := -1; + end if; + end procedure OREAD_common; + + -- Note that for Octal and Hex read, you can not start with a ".", + -- the read is for numbers formatted "A.BC". These routines go to + -- the nearest bounds, so "F.E" will fit into an sfixed (2 downto -3). + procedure OREAD (L : inout LINE; + VALUE : out UNRESOLVED_ufixed) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-2)/3)*3; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + OREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => true, + smath => false); + if igood then -- We did not get another error + if not ((i = -1) and -- We read everything, and high bits 0 + (or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then + report "fixed_pkg:" + & "OREAD(ufixed): Vector truncated." + severity error; + else + if (or_reduce (slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "fixed_pkg:" + & "OREAD(ufixed): Vector truncated" + severity warning; + end if; + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end if; + end if; + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-2)/3)*3; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + OREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => false, + smath => false); + if (igood and -- We did not get another error + (i = -1) and -- We read everything, and high bits 0 + (or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + good := true; + else + good := false; + end if; + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-2)/3)*3; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + OREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => true, + smath => true); + if igood then -- We did not get another error + if not ((i = -1) and -- We read everything + ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then + report "fixed_pkg:" + & "OREAD(sfixed): Vector truncated." + severity error; + else + if (or_reduce (slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "fixed_pkg:" + & "OREAD(sfixed): Vector truncated" + severity warning; + end if; + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end if; + end if; + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-2)/3)*3; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + OREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => false, + smath => true); + if (igood -- We did not get another error + and (i = -1) -- We read everything + and ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + good := true; + else + good := false; + end if; + end procedure OREAD; + + -- hex read and write + procedure hwrite ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_hstring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure hwrite; + + -- purpose: writes fixed point into a line + procedure hwrite ( + L : inout LINE; -- input line + VALUE : in UNRESOLVED_sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_hstring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure hwrite; + + -- purpose: Routines common to the OREAD routines + procedure HREAD_common ( + L : inout LINE; + slv : out STD_ULOGIC_VECTOR; + igood : out BOOLEAN; + idex : out INTEGER; + constant bpoint : in INTEGER; -- binary point + constant message : in BOOLEAN; + constant smath : in BOOLEAN) is + + -- purpose: error message routine + procedure errmes ( + constant mess : in STRING) is -- error message + begin + if message then + if smath then + report "fixed_pkg:" + & "HREAD(sfixed) " + & mess + severity error; + else + report "fixed_pkg:" + & "HREAD(ufixed) " + & mess + severity error; + end if; + end if; + end procedure errmes; + variable xgood : BOOLEAN; + variable nybble : STD_ULOGIC_VECTOR (3 downto 0); -- 4 bits + variable c : CHARACTER; + variable i : INTEGER; + variable lastu : BOOLEAN := false; -- last character was an "_" + variable founddot : BOOLEAN := false; -- found a dot. + begin + Skip_whitespace (L); + if slv'length > 0 then + i := slv'high; + read (l, c, xgood); + while i > 0 loop + if xgood = false then + errmes ("Error: end of string encountered"); + exit; + elsif c = '_' then + if i = slv'length then + errmes ("Error: String begins with an ""_"""); + xgood := false; + exit; + elsif lastu then + errmes ("Error: Two underscores detected in input string ""__"""); + xgood := false; + exit; + else + lastu := true; + end if; + elsif (c = '.') then + if (i + 1 /= bpoint) then + errmes ("encountered ""."" at wrong index"); + xgood := false; + exit; + elsif i = slv'length then + errmes ("encounted a ""."" at the beginning of the line"); + xgood := false; + exit; + elsif founddot then + errmes ("Two ""."" encounted in input string"); + xgood := false; + exit; + end if; + founddot := true; + lastu := false; + else + Char2QuadBits(c, nybble, xgood, message); + if not xgood then + exit; + end if; + slv (i downto i-3) := nybble; + i := i - 4; + lastu := false; + end if; + if i > 0 then + read (L, c, xgood); + end if; + end loop; + idex := i; + igood := xgood; + else + idex := -1; + igood := true; -- read null string + end if; + end procedure HREAD_common; + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-3)/4)*4; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + HREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => false, + smath => false); + if igood then + if not ((i = -1) and -- We read everything, and high bits 0 + (or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then + report "fixed_pkg:" + & "HREAD(ufixed): Vector truncated." + severity error; + else + if (or_reduce (slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "fixed_pkg:" + & "HREAD(ufixed): Vector truncated" + severity warning; + end if; + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end if; + end if; + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_ufixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-3)/4)*4; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + HREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => false, + smath => false); + if (igood and -- We did not get another error + (i = -1) and -- We read everything, and high bits 0 + (or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + good := true; + else + good := false; + end if; + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-3)/4)*4; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + HREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => true, + smath => true); + if igood then -- We did not get another error + if not ((i = -1) -- We read everything + and ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then + report "fixed_pkg:" + & "HREAD(sfixed): Vector truncated." + severity error; + else + if (or_reduce (slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "fixed_pkg:" + & "HREAD(sfixed): Vector truncated" + severity warning; + end if; + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end if; + end if; + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out UNRESOLVED_sfixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(0, VALUE'low)-3)/4)*4; + variable slv : STD_ULOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable valuex : UNRESOLVED_sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable i : INTEGER; + begin + VALUE := (VALUE'range => 'U'); + HREAD_common ( L => L, + slv => slv, + igood => igood, + idex => i, + bpoint => -lbv, + message => false, + smath => true); + if (igood and -- We did not get another error + (i = -1) and -- We read everything + ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reduce (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + good := true; + else + good := false; + end if; + end procedure HREAD; + + function to_string (value : UNRESOLVED_ufixed) return STRING is + variable s : STRING(1 to value'length +1) := (others => ' '); + variable subval : UNRESOLVED_ufixed (value'high downto -1); + variable sindx : INTEGER; + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + if value(value'high) = 'Z' then + return to_string (resize (sfixed(value), 0, value'low)); + else + return to_string (resize (value, 0, value'low)); + end if; + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_string(subval); + else + return to_string (resize (value, value'high, -1)); + end if; + else + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx + 1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx + 1; + end loop; + return s; + end if; + end if; + end function to_string; + + function to_string (value : UNRESOLVED_sfixed) return STRING is + variable s : STRING(1 to value'length + 1) := (others => ' '); + variable subval : UNRESOLVED_sfixed (value'high downto -1); + variable sindx : INTEGER; + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_string (resize (value, 0, value'low)); + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_string(subval); + else + return to_string (resize (value, value'high, -1)); + end if; + else + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx + 1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx + 1; + end loop; + return s; + end if; + end if; + end function to_string; + + function to_ostring (value : UNRESOLVED_ufixed) return STRING is + constant lne : INTEGER := (-VALUE'low+2)/3; + variable subval : UNRESOLVED_ufixed (value'high downto -3); + variable lpad : STD_ULOGIC_VECTOR (0 to (lne*3 + VALUE'low) -1); + variable slv : STD_ULOGIC_VECTOR (value'length-1 downto 0); + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + if value(value'high) = 'Z' then + return to_ostring (resize (sfixed(value), 2, value'low)); + else + return to_ostring (resize (value, 2, value'low)); + end if; + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_ostring(subval); + else + return to_ostring (resize (value, value'high, -3)); + end if; + else + slv := to_sulv (value); + if Is_X (value (value'low)) then + lpad := (others => value (value'low)); + else + lpad := (others => '0'); + end if; + return to_ostring(slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_ostring(slv(slv'high-VALUE'high-1 downto 0) & lpad); + end if; + end if; + end function to_ostring; + + function to_hstring (value : UNRESOLVED_ufixed) return STRING is + constant lne : INTEGER := (-VALUE'low+3)/4; + variable subval : UNRESOLVED_ufixed (value'high downto -4); + variable lpad : STD_ULOGIC_VECTOR (0 to (lne*4 + VALUE'low) -1); + variable slv : STD_ULOGIC_VECTOR (value'length-1 downto 0); + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + if value(value'high) = 'Z' then + return to_hstring (resize (sfixed(value), 3, value'low)); + else + return to_hstring (resize (value, 3, value'low)); + end if; + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_hstring(subval); + else + return to_hstring (resize (value, value'high, -4)); + end if; + else + slv := to_sulv (value); + if Is_X (value (value'low)) then + lpad := (others => value(value'low)); + else + lpad := (others => '0'); + end if; + return to_hstring(slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_hstring(slv(slv'high-VALUE'high-1 downto 0)&lpad); + end if; + end if; + end function to_hstring; + + function to_ostring (value : UNRESOLVED_sfixed) return STRING is + constant ne : INTEGER := ((value'high+1)+2)/3; + variable pad : STD_ULOGIC_VECTOR(0 to (ne*3 - (value'high+1)) - 1); + constant lne : INTEGER := (-VALUE'low+2)/3; + variable subval : UNRESOLVED_sfixed (value'high downto -3); + variable lpad : STD_ULOGIC_VECTOR (0 to (lne*3 + VALUE'low) -1); + variable slv : STD_ULOGIC_VECTOR (VALUE'high - VALUE'low downto 0); + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_ostring (resize (value, 2, value'low)); + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_ostring(subval); + else + return to_ostring (resize (value, value'high, -3)); + end if; + else + pad := (others => value(value'high)); + slv := to_sulv (value); + if Is_X (value (value'low)) then + lpad := (others => value(value'low)); + else + lpad := (others => '0'); + end if; + return to_ostring(pad & slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_ostring(slv(slv'high-VALUE'high-1 downto 0) & lpad); + end if; + end if; + end function to_ostring; + + function to_hstring (value : UNRESOLVED_sfixed) return STRING is + constant ne : INTEGER := ((value'high+1)+3)/4; + variable pad : STD_ULOGIC_VECTOR(0 to (ne*4 - (value'high+1)) - 1); + constant lne : INTEGER := (-VALUE'low+3)/4; + variable subval : UNRESOLVED_sfixed (value'high downto -4); + variable lpad : STD_ULOGIC_VECTOR (0 to (lne*4 + VALUE'low) -1); + variable slv : STD_ULOGIC_VECTOR (value'length-1 downto 0); + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_hstring (resize (value, 3, value'low)); + elsif value'low >= 0 then + if Is_X (value(value'low)) then + subval := (others => value(value'low)); + subval (value'range) := value; + return to_hstring(subval); + else + return to_hstring (resize (value, value'high, -4)); + end if; + else + slv := to_sulv (value); + pad := (others => value(value'high)); + if Is_X (value (value'low)) then + lpad := (others => value(value'low)); + else + lpad := (others => '0'); + end if; + return to_hstring(pad & slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_hstring(slv(slv'high-VALUE'high-1 downto 0) & lpad); + end if; + end if; + end function to_hstring; + + -- From string functions allow you to convert a string into a fixed + -- point number. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100", uf1'high, uf1'low); -- 6.5 + -- The "." is optional in this syntax, however it exist and is + -- in the wrong location an error is produced. Overflow will + -- result in saturation. + + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + read (L, result, good); + deallocate (L); + assert (good) + report "fixed_pkg:" + & "from_string: Bad string "& bstring severity error; + return result; + end function from_string; + + -- Octal and hex conversions work as follows: + -- uf1 <= from_hstring ("6.8", 3, -3); -- 6.5 (bottom zeros dropped) + -- uf1 <= from_ostring ("06.4", 3, -3); -- 6.5 (top zeros dropped) + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + oread (L, result, good); + deallocate (L); + assert (good) + report "fixed_pkg:" + & "from_ostring: Bad string "& ostring severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed is + variable result : UNRESOLVED_ufixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + hread (L, result, good); + deallocate (L); + assert (good) + report "fixed_pkg:" + & "from_hstring: Bad string "& hstring severity error; + return result; + end function from_hstring; + + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + read (L, result, good); + deallocate (L); + assert (good) + report "fixed_pkg:" + & "from_string: Bad string "& bstring severity error; + return result; + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + oread (L, result, good); + deallocate (L); + assert (good) + report "fixed_pkg:" + & "from_ostring: Bad string "& ostring severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed is + variable result : UNRESOLVED_sfixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + hread (L, result, good); + deallocate (L); + assert (good) + report "fixed_pkg:" + & "from_hstring: Bad string "& hstring severity error; + return result; + end function from_hstring; + + -- Same as above, "size_res" is used for it's range only. + function from_string ( + bstring : STRING; -- binary string + size_res : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return from_string (bstring, size_res'high, size_res'low); + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return from_ostring (ostring, size_res'high, size_res'low); + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : UNRESOLVED_ufixed) + return UNRESOLVED_ufixed is + begin + return from_hstring(hstring, size_res'high, size_res'low); + end function from_hstring; + + function from_string ( + bstring : STRING; -- binary string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return from_string (bstring, size_res'high, size_res'low); + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return from_ostring (ostring, size_res'high, size_res'low); + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : UNRESOLVED_sfixed) + return UNRESOLVED_sfixed is + begin + return from_hstring (hstring, size_res'high, size_res'low); + end function from_hstring; + + -- purpose: Calculate the string boundaries + procedure calculate_string_boundry ( + arg : in STRING; -- input string + left_index : out INTEGER; -- left + right_index : out INTEGER) is -- right + -- examples "10001.111" would return +4, -3 + -- "07X.44" would return +2, -2 (then the octal routine would multiply) + -- "A_B_._C" would return +1, -1 (then the hex routine would multiply) + alias xarg : STRING (arg'length downto 1) is arg; -- make it downto range + variable l, r : INTEGER; -- internal indexes + variable founddot : BOOLEAN := false; + begin + if arg'length > 0 then + l := xarg'high - 1; + r := 0; + for i in xarg'range loop + if xarg(i) = '_' then + if r = 0 then + l := l - 1; + else + r := r + 1; + end if; + elsif xarg(i) = ' ' or xarg(i) = NBSP or xarg(i) = HT then + report "fixed_pkg:" + & "Found a space in the input STRING " & xarg + severity error; + elsif xarg(i) = '.' then + if founddot then + report "fixed_pkg:" + & "Found two binary points in input string " & xarg + severity error; + else + l := l - i; + r := -i + 1; + founddot := true; + end if; + end if; + end loop; + left_index := l; + right_index := r; + else + left_index := 0; + right_index := 0; + end if; + end procedure calculate_string_boundry; + + -- Direct conversion functions. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100"); -- 6.5 + -- In this case the "." is not optional, and the size of + -- the output must match exactly. + function from_string ( + bstring : STRING) -- binary string + return UNRESOLVED_ufixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (bstring, left_index, right_index); + return from_string (bstring, left_index, right_index); + end function from_string; + + -- Direct octal and hex conversion functions. In this case + -- the string lengths must match. Example: + -- signal sf1 := sfixed (5 downto -3); + -- sf1 <= from_ostring ("71.4") -- -6.5 + function from_ostring ( + ostring : STRING) -- Octal string + return UNRESOLVED_ufixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (ostring, left_index, right_index); + return from_ostring (ostring, ((left_index+1)*3)-1, right_index*3); + end function from_ostring; + + function from_hstring ( + hstring : STRING) -- hex string + return UNRESOLVED_ufixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (hstring, left_index, right_index); + return from_hstring (hstring, ((left_index+1)*4)-1, right_index*4); + end function from_hstring; + + function from_string ( + bstring : STRING) -- binary string + return UNRESOLVED_sfixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (bstring, left_index, right_index); + return from_string (bstring, left_index, right_index); + end function from_string; + + function from_ostring ( + ostring : STRING) -- Octal string + return UNRESOLVED_sfixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (ostring, left_index, right_index); + return from_ostring (ostring, ((left_index+1)*3)-1, right_index*3); + end function from_ostring; + + function from_hstring ( + hstring : STRING) -- hex string + return UNRESOLVED_sfixed is + variable left_index, right_index : INTEGER; + begin + calculate_string_boundry (hstring, left_index, right_index); + return from_hstring (hstring, ((left_index+1)*4)-1, right_index*4); + end function from_hstring; +-- pragma synthesis_on +-- rtl_synthesis on + -- IN VHDL-2006 std_logic_vector is a subtype of std_ulogic_vector, so these + -- extra functions are needed for compatability. + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_ufixed is + begin + return to_ufixed ( + arg => std_ulogic_vector (arg), + left_index => left_index, + right_index => right_index); + end function to_ufixed; + + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_ufixed) -- for size only + return UNRESOLVED_ufixed is + begin + return to_ufixed ( + arg => std_ulogic_vector (arg), + size_res => size_res); + end function to_ufixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return UNRESOLVED_sfixed is + begin + return to_sfixed ( + arg => std_ulogic_vector (arg), + left_index => left_index, + right_index => right_index); + end function to_sfixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : UNRESOLVED_sfixed) -- for size only + return UNRESOLVED_sfixed is + begin + return to_sfixed ( + arg => std_ulogic_vector (arg), + size_res => size_res); + end function to_sfixed; + + -- unsigned fixed point + function to_UFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_ufixed is + begin + return to_UFix ( + arg => std_ulogic_vector (arg), + width => width, + fraction => fraction); + end function to_UFix; + + -- signed fixed point + function to_SFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return UNRESOLVED_sfixed is + begin + return to_SFix ( + arg => std_ulogic_vector (arg), + width => width, + fraction => fraction); + end function to_SFix; + +end package body fixed_pkg;
trunk/sim/rtl_sim/src/fixed_pkg_c.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/sim/rtl_sim/src/math_real.vhd =================================================================== --- trunk/sim/rtl_sim/src/math_real.vhd (nonexistent) +++ trunk/sim/rtl_sim/src/math_real.vhd (revision 2) @@ -0,0 +1,2507 @@ +-- -------------------------------------------------------------------- +-- +-- Copyright © 2008 by IEEE. All rights reserved. +-- +-- This source file is an essential part of IEEE Std 1076-2008, +-- IEEE Standard VHDL Language Reference Manual. This source file may not be +-- copied, sold, or included with software that is sold without written +-- permission from the IEEE Standards Department. This source file may be +-- copied for individual use between licensed users. This source file is +-- provided on an AS IS basis. The IEEE disclaims ANY WARRANTY EXPRESS OR +-- IMPLIED INCLUDING ANY WARRANTY OF MERCHANTABILITY AND FITNESS FOR USE +-- FOR A PARTICULAR PURPOSE. The user of the source file shall indemnify +-- and hold IEEE harmless from any damages or liability arising out of the +-- use thereof. +-- +-- Title : Standard VHDL Mathematical Packages +-- : (MATH_REAL package declaration) +-- : +-- Library : This package shall be compiled into a library +-- : symbolically named IEEE. +-- : +-- Developers: IEEE DASC VHDL Mathematical Packages Working Group +-- : +-- Purpose : This package defines a standard for designers to use in +-- : describing VHDL models that make use of common REAL +-- : constants and common REAL elementary mathematical +-- : functions. +-- : +-- Limitation: The values generated by the functions in this package +-- : may vary from platform to platform, and the precision +-- : of results is only guaranteed to be the minimum required +-- : by IEEE Std 1076-2008. +-- : +-- Note : This package may be modified to include additional data +-- : required by tools, but it must in no way change the +-- : external interfaces or simulation behavior of the +-- : description. It is permissible to add comments and/or +-- : attributes to the package declarations, but not to change +-- : or delete any original lines of the package declaration. +-- : The package body may be changed only in accordance with +-- : the terms of Clause 16 of this standard. +-- : +-- -------------------------------------------------------------------- +-- $Revision: 1220 $ +-- $Date: 2008-04-10 17:16:09 +0930 (Thu, 10 Apr 2008) $ +-- -------------------------------------------------------------------- + +package MATH_REAL is + constant CopyRightNotice : STRING + := "Copyright 2008 IEEE. All rights reserved."; + + -- + -- Constant Definitions + -- + constant MATH_E : REAL := 2.71828_18284_59045_23536; + -- Value of e + constant MATH_1_OVER_E : REAL := 0.36787_94411_71442_32160; + -- Value of 1/e + constant MATH_PI : REAL := 3.14159_26535_89793_23846; + -- Value of pi + constant MATH_2_PI : REAL := 6.28318_53071_79586_47693; + -- Value of 2*pi + constant MATH_1_OVER_PI : REAL := 0.31830_98861_83790_67154; + -- Value of 1/pi + constant MATH_PI_OVER_2 : REAL := 1.57079_63267_94896_61923; + -- Value of pi/2 + constant MATH_PI_OVER_3 : REAL := 1.04719_75511_96597_74615; + -- Value of pi/3 + constant MATH_PI_OVER_4 : REAL := 0.78539_81633_97448_30962; + -- Value of pi/4 + constant MATH_3_PI_OVER_2 : REAL := 4.71238_89803_84689_85769; + -- Value 3*pi/2 + constant MATH_LOG_OF_2 : REAL := 0.69314_71805_59945_30942; + -- Natural log of 2 + constant MATH_LOG_OF_10 : REAL := 2.30258_50929_94045_68402; + -- Natural log of 10 + constant MATH_LOG2_OF_E : REAL := 1.44269_50408_88963_4074; + -- Log base 2 of e + constant MATH_LOG10_OF_E : REAL := 0.43429_44819_03251_82765; + -- Log base 10 of e + constant MATH_SQRT_2 : REAL := 1.41421_35623_73095_04880; + -- square root of 2 + constant MATH_1_OVER_SQRT_2 : REAL := 0.70710_67811_86547_52440; + -- square root of 1/2 + constant MATH_SQRT_PI : REAL := 1.77245_38509_05516_02730; + -- square root of pi + constant MATH_DEG_TO_RAD : REAL := 0.01745_32925_19943_29577; + -- Conversion factor from degree to radian + constant MATH_RAD_TO_DEG : REAL := 57.29577_95130_82320_87680; + -- Conversion factor from radian to degree + + -- + -- Function Declarations + -- + function SIGN (X : in REAL) return REAL; + -- Purpose: + -- Returns 1.0 if X > 0.0; 0.0 if X = 0.0; -1.0 if X < 0.0 + -- Special values: + -- None + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ABS(SIGN(X)) <= 1.0 + -- Notes: + -- None + + function CEIL (X : in REAL) return REAL; + -- Purpose: + -- Returns smallest INTEGER value (as REAL) not less than X + -- Special values: + -- None + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- CEIL(X) is mathematically unbounded + -- Notes: + -- a) Implementations have to support at least the domain + -- ABS(X) < REAL(INTEGER'HIGH) + + function FLOOR (X : in REAL) return REAL; + -- Purpose: + -- Returns largest INTEGER value (as REAL) not greater than X + -- Special values: + -- FLOOR(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- FLOOR(X) is mathematically unbounded + -- Notes: + -- a) Implementations have to support at least the domain + -- ABS(X) < REAL(INTEGER'HIGH) + + function ROUND (X : in REAL) return REAL; + -- Purpose: + -- Rounds X to the nearest integer value (as real). If X is + -- halfway between two integers, rounding is away from 0.0 + -- Special values: + -- ROUND(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ROUND(X) is mathematically unbounded + -- Notes: + -- a) Implementations have to support at least the domain + -- ABS(X) < REAL(INTEGER'HIGH) + + function TRUNC (X : in REAL) return REAL; + -- Purpose: + -- Truncates X towards 0.0 and returns truncated value + -- Special values: + -- TRUNC(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- TRUNC(X) is mathematically unbounded + -- Notes: + -- a) Implementations have to support at least the domain + -- ABS(X) < REAL(INTEGER'HIGH) + + function "MOD" (X, Y : in REAL) return REAL; + -- Purpose: + -- Returns floating point modulus of X/Y, with the same sign as + -- Y, and absolute value less than the absolute value of Y, and + -- for some INTEGER value N the result satisfies the relation + -- X = Y*N + MOD(X,Y) + -- Special values: + -- None + -- Domain: + -- X in REAL; Y in REAL and Y /= 0.0 + -- Error conditions: + -- Error if Y = 0.0 + -- Range: + -- ABS(MOD(X,Y)) < ABS(Y) + -- Notes: + -- None + + function REALMAX (X, Y : in REAL) return REAL; + -- Purpose: + -- Returns the algebraically larger of X and Y + -- Special values: + -- REALMAX(X,Y) = X when X = Y + -- Domain: + -- X in REAL; Y in REAL + -- Error conditions: + -- None + -- Range: + -- REALMAX(X,Y) is mathematically unbounded + -- Notes: + -- None + + function REALMIN (X, Y : in REAL) return REAL; + -- Purpose: + -- Returns the algebraically smaller of X and Y + -- Special values: + -- REALMIN(X,Y) = X when X = Y + -- Domain: + -- X in REAL; Y in REAL + -- Error conditions: + -- None + -- Range: + -- REALMIN(X,Y) is mathematically unbounded + -- Notes: + -- None + + procedure UNIFORM(variable SEED1, SEED2 : inout POSITIVE; variable X : out REAL); + -- Purpose: + -- Returns, in X, a pseudo-random number with uniform + -- distribution in the open interval (0.0, 1.0). + -- Special values: + -- None + -- Domain: + -- 1 <= SEED1 <= 2147483562; 1 <= SEED2 <= 2147483398 + -- Error conditions: + -- Error if SEED1 or SEED2 outside of valid domain + -- Range: + -- 0.0 < X < 1.0 + -- Notes: + -- a) The semantics for this function are described by the + -- algorithm published by Pierre L'Ecuyer in "Communications + -- of the ACM," vol. 31, no. 6, June 1988, pp. 742-774. + -- The algorithm is based on the combination of two + -- multiplicative linear congruential generators for 32-bit + -- platforms. + -- + -- b) Before the first call to UNIFORM, the seed values + -- (SEED1, SEED2) have to be initialized to values in the range + -- [1, 2147483562] and [1, 2147483398] respectively. The + -- seed values are modified after each call to UNIFORM. + -- + -- c) This random number generator is portable for 32-bit + -- computers, and it has a period of ~2.30584*(10**18) for each + -- set of seed values. + -- + -- d) For information on spectral tests for the algorithm, refer + -- to the L'Ecuyer article. + + function SQRT (X : in REAL) return REAL; + -- Purpose: + -- Returns square root of X + -- Special values: + -- SQRT(0.0) = 0.0 + -- SQRT(1.0) = 1.0 + -- Domain: + -- X >= 0.0 + -- Error conditions: + -- Error if X < 0.0 + -- Range: + -- SQRT(X) >= 0.0 + -- Notes: + -- a) The upper bound of the reachable range of SQRT is + -- approximately given by: + -- SQRT(X) <= SQRT(REAL'HIGH) + + function CBRT (X : in REAL) return REAL; + -- Purpose: + -- Returns cube root of X + -- Special values: + -- CBRT(0.0) = 0.0 + -- CBRT(1.0) = 1.0 + -- CBRT(-1.0) = -1.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- CBRT(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of CBRT is approximately given by: + -- ABS(CBRT(X)) <= CBRT(REAL'HIGH) + + function "**" (X : in INTEGER; Y : in REAL) return REAL; + -- Purpose: + -- Returns Y power of X ==> X**Y + -- Special values: + -- X**0.0 = 1.0; X /= 0 + -- 0**Y = 0.0; Y > 0.0 + -- X**1.0 = REAL(X); X >= 0 + -- 1**Y = 1.0 + -- Domain: + -- X > 0 + -- X = 0 for Y > 0.0 + -- X < 0 for Y = 0.0 + -- Error conditions: + -- Error if X < 0 and Y /= 0.0 + -- Error if X = 0 and Y <= 0.0 + -- Range: + -- X**Y >= 0.0 + -- Notes: + -- a) The upper bound of the reachable range for "**" is + -- approximately given by: + -- X**Y <= REAL'HIGH + + function "**" (X : in REAL; Y : in REAL) return REAL; + -- Purpose: + -- Returns Y power of X ==> X**Y + -- Special values: + -- X**0.0 = 1.0; X /= 0.0 + -- 0.0**Y = 0.0; Y > 0.0 + -- X**1.0 = X; X >= 0.0 + -- 1.0**Y = 1.0 + -- Domain: + -- X > 0.0 + -- X = 0.0 for Y > 0.0 + -- X < 0.0 for Y = 0.0 + -- Error conditions: + -- Error if X < 0.0 and Y /= 0.0 + -- Error if X = 0.0 and Y <= 0.0 + -- Range: + -- X**Y >= 0.0 + -- Notes: + -- a) The upper bound of the reachable range for "**" is + -- approximately given by: + -- X**Y <= REAL'HIGH + + function EXP (X : in REAL) return REAL; + -- Purpose: + -- Returns e**X; where e = MATH_E + -- Special values: + -- EXP(0.0) = 1.0 + -- EXP(1.0) = MATH_E + -- EXP(-1.0) = MATH_1_OVER_E + -- EXP(X) = 0.0 for X <= -LOG(REAL'HIGH) + -- Domain: + -- X in REAL such that EXP(X) <= REAL'HIGH + -- Error conditions: + -- Error if X > LOG(REAL'HIGH) + -- Range: + -- EXP(X) >= 0.0 + -- Notes: + -- a) The usable domain of EXP is approximately given by: + -- X <= LOG(REAL'HIGH) + + function LOG (X : in REAL) return REAL; + -- Purpose: + -- Returns natural logarithm of X + -- Special values: + -- LOG(1.0) = 0.0 + -- LOG(MATH_E) = 1.0 + -- Domain: + -- X > 0.0 + -- Error conditions: + -- Error if X <= 0.0 + -- Range: + -- LOG(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of LOG is approximately given by: + -- LOG(0+) <= LOG(X) <= LOG(REAL'HIGH) + + function LOG2 (X : in REAL) return REAL; + -- Purpose: + -- Returns logarithm base 2 of X + -- Special values: + -- LOG2(1.0) = 0.0 + -- LOG2(2.0) = 1.0 + -- Domain: + -- X > 0.0 + -- Error conditions: + -- Error if X <= 0.0 + -- Range: + -- LOG2(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of LOG2 is approximately given by: + -- LOG2(0+) <= LOG2(X) <= LOG2(REAL'HIGH) + + function LOG10 (X : in REAL) return REAL; + -- Purpose: + -- Returns logarithm base 10 of X + -- Special values: + -- LOG10(1.0) = 0.0 + -- LOG10(10.0) = 1.0 + -- Domain: + -- X > 0.0 + -- Error conditions: + -- Error if X <= 0.0 + -- Range: + -- LOG10(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of LOG10 is approximately given by: + -- LOG10(0+) <= LOG10(X) <= LOG10(REAL'HIGH) + + function LOG (X : in REAL; BASE : in REAL) return REAL; + -- Purpose: + -- Returns logarithm base BASE of X + -- Special values: + -- LOG(1.0, BASE) = 0.0 + -- LOG(BASE, BASE) = 1.0 + -- Domain: + -- X > 0.0 + -- BASE > 0.0 + -- BASE /= 1.0 + -- Error conditions: + -- Error if X <= 0.0 + -- Error if BASE <= 0.0 + -- Error if BASE = 1.0 + -- Range: + -- LOG(X, BASE) is mathematically unbounded + -- Notes: + -- a) When BASE > 1.0, the reachable range of LOG is + -- approximately given by: + -- LOG(0+, BASE) <= LOG(X, BASE) <= LOG(REAL'HIGH, BASE) + -- b) When 0.0 < BASE < 1.0, the reachable range of LOG is + -- approximately given by: + -- LOG(REAL'HIGH, BASE) <= LOG(X, BASE) <= LOG(0+, BASE) + + function SIN (X : in REAL) return REAL; + -- Purpose: + -- Returns sine of X; X in radians + -- Special values: + -- SIN(X) = 0.0 for X = k*MATH_PI, where k is an INTEGER + -- SIN(X) = 1.0 for X = (4*k+1)*MATH_PI_OVER_2, where k is an + -- INTEGER + -- SIN(X) = -1.0 for X = (4*k+3)*MATH_PI_OVER_2, where k is an + -- INTEGER + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ABS(SIN(X)) <= 1.0 + -- Notes: + -- a) For larger values of ABS(X), degraded accuracy is allowed. + + function COS (X : in REAL) return REAL; + -- Purpose: + -- Returns cosine of X; X in radians + -- Special values: + -- COS(X) = 0.0 for X = (2*k+1)*MATH_PI_OVER_2, where k is an + -- INTEGER + -- COS(X) = 1.0 for X = (2*k)*MATH_PI, where k is an INTEGER + -- COS(X) = -1.0 for X = (2*k+1)*MATH_PI, where k is an INTEGER + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ABS(COS(X)) <= 1.0 + -- Notes: + -- a) For larger values of ABS(X), degraded accuracy is allowed. + + function TAN (X : in REAL) return REAL; + -- Purpose: + -- Returns tangent of X; X in radians + -- Special values: + -- TAN(X) = 0.0 for X = k*MATH_PI, where k is an INTEGER + -- Domain: + -- X in REAL and + -- X /= (2*k+1)*MATH_PI_OVER_2, where k is an INTEGER + -- Error conditions: + -- Error if X = ((2*k+1) * MATH_PI_OVER_2), where k is an + -- INTEGER + -- Range: + -- TAN(X) is mathematically unbounded + -- Notes: + -- a) For larger values of ABS(X), degraded accuracy is allowed. + + function ARCSIN (X : in REAL) return REAL; + -- Purpose: + -- Returns inverse sine of X + -- Special values: + -- ARCSIN(0.0) = 0.0 + -- ARCSIN(1.0) = MATH_PI_OVER_2 + -- ARCSIN(-1.0) = -MATH_PI_OVER_2 + -- Domain: + -- ABS(X) <= 1.0 + -- Error conditions: + -- Error if ABS(X) > 1.0 + -- Range: + -- ABS(ARCSIN(X) <= MATH_PI_OVER_2 + -- Notes: + -- None + + function ARCCOS (X : in REAL) return REAL; + -- Purpose: + -- Returns inverse cosine of X + -- Special values: + -- ARCCOS(1.0) = 0.0 + -- ARCCOS(0.0) = MATH_PI_OVER_2 + -- ARCCOS(-1.0) = MATH_PI + -- Domain: + -- ABS(X) <= 1.0 + -- Error conditions: + -- Error if ABS(X) > 1.0 + -- Range: + -- 0.0 <= ARCCOS(X) <= MATH_PI + -- Notes: + -- None + + function ARCTAN (Y : in REAL) return REAL; + -- Purpose: + -- Returns the value of the angle in radians of the point + -- (1.0, Y), which is in rectangular coordinates + -- Special values: + -- ARCTAN(0.0) = 0.0 + -- Domain: + -- Y in REAL + -- Error conditions: + -- None + -- Range: + -- ABS(ARCTAN(Y)) <= MATH_PI_OVER_2 + -- Notes: + -- None + + function ARCTAN (Y : in REAL; X : in REAL) return REAL; + -- Purpose: + -- Returns the principal value of the angle in radians of + -- the point (X, Y), which is in rectangular coordinates + -- Special values: + -- ARCTAN(0.0, X) = 0.0 if X > 0.0 + -- ARCTAN(0.0, X) = MATH_PI if X < 0.0 + -- ARCTAN(Y, 0.0) = MATH_PI_OVER_2 if Y > 0.0 + -- ARCTAN(Y, 0.0) = -MATH_PI_OVER_2 if Y < 0.0 + -- Domain: + -- Y in REAL + -- X in REAL, X /= 0.0 when Y = 0.0 + -- Error conditions: + -- Error if X = 0.0 and Y = 0.0 + -- Range: + -- -MATH_PI < ARCTAN(Y,X) <= MATH_PI + -- Notes: + -- None + + function SINH (X : in REAL) return REAL; + -- Purpose: + -- Returns hyperbolic sine of X + -- Special values: + -- SINH(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- SINH(X) is mathematically unbounded + -- Notes: + -- a) The usable domain of SINH is approximately given by: + -- ABS(X) <= LOG(REAL'HIGH) + + + function COSH (X : in REAL) return REAL; + -- Purpose: + -- Returns hyperbolic cosine of X + -- Special values: + -- COSH(0.0) = 1.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- COSH(X) >= 1.0 + -- Notes: + -- a) The usable domain of COSH is approximately given by: + -- ABS(X) <= LOG(REAL'HIGH) + + function TANH (X : in REAL) return REAL; + -- Purpose: + -- Returns hyperbolic tangent of X + -- Special values: + -- TANH(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ABS(TANH(X)) <= 1.0 + -- Notes: + -- None + + function ARCSINH (X : in REAL) return REAL; + -- Purpose: + -- Returns inverse hyperbolic sine of X + -- Special values: + -- ARCSINH(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ARCSINH(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of ARCSINH is approximately given by: + -- ABS(ARCSINH(X)) <= LOG(REAL'HIGH) + + function ARCCOSH (X : in REAL) return REAL; + -- Purpose: + -- Returns inverse hyperbolic cosine of X + -- Special values: + -- ARCCOSH(1.0) = 0.0 + -- Domain: + -- X >= 1.0 + -- Error conditions: + -- Error if X < 1.0 + -- Range: + -- ARCCOSH(X) >= 0.0 + -- Notes: + -- a) The upper bound of the reachable range of ARCCOSH is + -- approximately given by: ARCCOSH(X) <= LOG(REAL'HIGH) + + function ARCTANH (X : in REAL) return REAL; + -- Purpose: + -- Returns inverse hyperbolic tangent of X + -- Special values: + -- ARCTANH(0.0) = 0.0 + -- Domain: + -- ABS(X) < 1.0 + -- Error conditions: + -- Error if ABS(X) >= 1.0 + -- Range: + -- ARCTANH(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of ARCTANH is approximately given by: + -- ABS(ARCTANH(X)) < LOG(REAL'HIGH) + +end package MATH_REAL; + +package body MATH_REAL is + + -- + -- Local Constants for Use in the Package Body Only + -- + constant MATH_E_P2 : REAL := 7.38905_60989_30650; -- e**2 + constant MATH_E_P10 : REAL := 22026.46579_48067_17; -- e**10 + constant MATH_EIGHT_PI : REAL := 25.13274_12287_18345_90770_115; --8*pi + constant MAX_ITER: INTEGER := 27; -- Maximum precision factor for cordic + constant MAX_COUNT: INTEGER := 150; -- Maximum count for number of tries + constant BASE_EPS: REAL := 0.00001; -- Factor for convergence criteria + constant KC : REAL := 6.0725293500888142e-01; -- Constant for cordic + + -- + -- Local Type Declarations for Cordic Operations + -- + type REAL_VECTOR is array (NATURAL range <>) of REAL; + type NATURAL_VECTOR is array (NATURAL range <>) of NATURAL; + subtype REAL_VECTOR_N is REAL_VECTOR (0 to MAX_ITER); + subtype REAL_ARR_2 is REAL_VECTOR (0 to 1); + subtype REAL_ARR_3 is REAL_VECTOR (0 to 2); + subtype QUADRANT is INTEGER range 0 to 3; + type CORDIC_MODE_TYPE is (ROTATION, VECTORING); + + -- + -- Auxiliary Functions for Cordic Algorithms + -- + function POWER_OF_2_SERIES (D : in NATURAL_VECTOR; INITIAL_VALUE : in REAL; + NUMBER_OF_VALUES : in NATURAL) return REAL_VECTOR is + -- Description: + -- Returns power of two for a vector of values + -- Notes: + -- None + -- + variable V : REAL_VECTOR (0 to NUMBER_OF_VALUES); + variable TEMP : REAL := INITIAL_VALUE; + variable FLAG : BOOLEAN := TRUE; + begin + for I in 0 to NUMBER_OF_VALUES loop + V(I) := TEMP; + for P in D'RANGE loop + if I = D(P) then + FLAG := FALSE; + exit; + end if; + end loop; + if FLAG then + TEMP := TEMP/2.0; + end if; + FLAG := TRUE; + end loop; + return V; + end function POWER_OF_2_SERIES; + + + constant TWO_AT_MINUS : REAL_VECTOR := POWER_OF_2_SERIES( + NATURAL_VECTOR'(100, 90),1.0, + MAX_ITER); + + constant EPSILON : REAL_VECTOR_N := ( + 7.8539816339744827e-01, + 4.6364760900080606e-01, + 2.4497866312686413e-01, + 1.2435499454676144e-01, + 6.2418809995957351e-02, + 3.1239833430268277e-02, + 1.5623728620476830e-02, + 7.8123410601011116e-03, + 3.9062301319669717e-03, + 1.9531225164788189e-03, + 9.7656218955931937e-04, + 4.8828121119489829e-04, + 2.4414062014936175e-04, + 1.2207031189367021e-04, + 6.1035156174208768e-05, + 3.0517578115526093e-05, + 1.5258789061315760e-05, + 7.6293945311019699e-06, + 3.8146972656064960e-06, + 1.9073486328101870e-06, + 9.5367431640596080e-07, + 4.7683715820308876e-07, + 2.3841857910155801e-07, + 1.1920928955078067e-07, + 5.9604644775390553e-08, + 2.9802322387695303e-08, + 1.4901161193847654e-08, + 7.4505805969238281e-09 + ); + + function CORDIC ( X0 : in REAL; + Y0 : in REAL; + Z0 : in REAL; + N : in NATURAL; -- Precision factor + CORDIC_MODE : in CORDIC_MODE_TYPE -- Rotation (Z -> 0) + -- or vectoring (Y -> 0) + ) return REAL_ARR_3 is + -- Description: + -- Compute cordic values + -- Notes: + -- None + variable X : REAL := X0; + variable Y : REAL := Y0; + variable Z : REAL := Z0; + variable X_TEMP : REAL; + begin + if CORDIC_MODE = ROTATION then + for K in 0 to N loop + X_TEMP := X; + if ( Z >= 0.0) then + X := X - Y * TWO_AT_MINUS(K); + Y := Y + X_TEMP * TWO_AT_MINUS(K); + Z := Z - EPSILON(K); + else + X := X + Y * TWO_AT_MINUS(K); + Y := Y - X_TEMP * TWO_AT_MINUS(K); + Z := Z + EPSILON(K); + end if; + end loop; + else + for K in 0 to N loop + X_TEMP := X; + if ( Y < 0.0) then + X := X - Y * TWO_AT_MINUS(K); + Y := Y + X_TEMP * TWO_AT_MINUS(K); + Z := Z - EPSILON(K); + else + X := X + Y * TWO_AT_MINUS(K); + Y := Y - X_TEMP * TWO_AT_MINUS(K); + Z := Z + EPSILON(K); + end if; + end loop; + end if; + return REAL_ARR_3'(X, Y, Z); + end function CORDIC; + + -- + -- Bodies for Global Mathematical Functions Start Here + -- + function SIGN (X: in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + if ( X > 0.0 ) then + return 1.0; + elsif ( X < 0.0 ) then + return -1.0; + else + return 0.0; + end if; + end function SIGN; + + function CEIL (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) No conversion to an INTEGER type is expected, so truncate + -- cannot overflow for large arguments + -- b) The domain supported by this function is X <= LARGE + -- c) Returns X if ABS(X) >= LARGE + + constant LARGE: REAL := REAL(INTEGER'HIGH); + variable RD: REAL; + + begin + if ABS(X) >= LARGE then + return X; + end if; + + RD := REAL ( INTEGER(X)); + if RD = X then + return X; + end if; + + if X > 0.0 then + if RD >= X then + return RD; + else + return RD + 1.0; + end if; + elsif X = 0.0 then + return 0.0; + else + if RD <= X then + return RD + 1.0; + else + return RD; + end if; + end if; + end function CEIL; + + function FLOOR (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) No conversion to an INTEGER type is expected, so truncate + -- cannot overflow for large arguments + -- b) The domain supported by this function is ABS(X) <= LARGE + -- c) Returns X if ABS(X) >= LARGE + + constant LARGE: REAL := REAL(INTEGER'HIGH); + variable RD: REAL; + + begin + if ABS( X ) >= LARGE then + return X; + end if; + + RD := REAL ( INTEGER(X)); + if RD = X then + return X; + end if; + + if X > 0.0 then + if RD <= X then + return RD; + else + return RD - 1.0; + end if; + elsif X = 0.0 then + return 0.0; + else + if RD >= X then + return RD - 1.0; + else + return RD; + end if; + end if; + end function FLOOR; + + function ROUND (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 if X = 0.0 + -- b) Returns FLOOR(X + 0.5) if X > 0 + -- c) Returns CEIL(X - 0.5) if X < 0 + + begin + if X > 0.0 then + return FLOOR(X + 0.5); + elsif X < 0.0 then + return CEIL( X - 0.5); + else + return 0.0; + end if; + end function ROUND; + + function TRUNC (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 if X = 0.0 + -- b) Returns FLOOR(X) if X > 0 + -- c) Returns CEIL(X) if X < 0 + + begin + if X > 0.0 then + return FLOOR(X); + elsif X < 0.0 then + return CEIL( X); + else + return 0.0; + end if; + end function TRUNC; + + + + + function "MOD" (X, Y: in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 on error + + variable XNEGATIVE : BOOLEAN := X < 0.0; + variable YNEGATIVE : BOOLEAN := Y < 0.0; + variable VALUE : REAL; + begin + -- Check validity of input arguments + if (Y = 0.0) then + assert FALSE + report "MOD(X, 0.0) is undefined" + severity ERROR; + return 0.0; + end if; + + -- Compute value + if ( XNEGATIVE ) then + if ( YNEGATIVE ) then + VALUE := X + (FLOOR(ABS(X)/ABS(Y)))*ABS(Y); + else + VALUE := X + (CEIL(ABS(X)/ABS(Y)))*ABS(Y); + end if; + else + if ( YNEGATIVE ) then + VALUE := X - (CEIL(ABS(X)/ABS(Y)))*ABS(Y); + else + VALUE := X - (FLOOR(ABS(X)/ABS(Y)))*ABS(Y); + end if; + end if; + + return VALUE; + end function "MOD"; + + + function REALMAX (X, Y : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) REALMAX(X,Y) = X when X = Y + -- + begin + if X >= Y then + return X; + else + return Y; + end if; + end function REALMAX; + + function REALMIN (X, Y : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) REALMIN(X,Y) = X when X = Y + -- + begin + if X <= Y then + return X; + else + return Y; + end if; + end function REALMIN; + + + procedure UNIFORM(variable SEED1,SEED2:inout POSITIVE;variable X:out REAL) + is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 on error + -- + variable Z, K: INTEGER; + variable TSEED1 : INTEGER := INTEGER'(SEED1); + variable TSEED2 : INTEGER := INTEGER'(SEED2); + begin + -- Check validity of arguments + if SEED1 > 2147483562 then + assert FALSE + report "SEED1 > 2147483562 in UNIFORM" + severity ERROR; + X := 0.0; + return; + end if; + + if SEED2 > 2147483398 then + assert FALSE + report "SEED2 > 2147483398 in UNIFORM" + severity ERROR; + X := 0.0; + return; + end if; + + -- Compute new seed values and pseudo-random number + K := TSEED1/53668; + TSEED1 := 40014 * (TSEED1 - K * 53668) - K * 12211; + + if TSEED1 < 0 then + TSEED1 := TSEED1 + 2147483563; + end if; + + K := TSEED2/52774; + TSEED2 := 40692 * (TSEED2 - K * 52774) - K * 3791; + + if TSEED2 < 0 then + TSEED2 := TSEED2 + 2147483399; + end if; + + Z := TSEED1 - TSEED2; + if Z < 1 then + Z := Z + 2147483562; + end if; + + -- Get output values + SEED1 := POSITIVE'(TSEED1); + SEED2 := POSITIVE'(TSEED2); + X := REAL(Z)*4.656613e-10; + end procedure UNIFORM; + + + + function SQRT (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Uses the Newton-Raphson approximation: + -- F(n+1) = 0.5*[F(n) + x/F(n)] + -- b) Returns 0.0 on error + -- + + constant EPS : REAL := BASE_EPS*BASE_EPS; -- Convergence factor + + variable INIVAL: REAL; + variable OLDVAL : REAL ; + variable NEWVAL : REAL ; + variable COUNT : INTEGER := 1; + + begin + -- Check validity of argument + if ( X < 0.0 ) then + assert FALSE + report "X < 0.0 in SQRT(X)" + severity ERROR; + return 0.0; + end if; + + -- Get the square root for special cases + if X = 0.0 then + return 0.0; + else + if ( X = 1.0 ) then + return 1.0; + end if; + end if; + + -- Get the square root for general cases + INIVAL := EXP(LOG(X)*(0.5)); -- Mathematically correct but imprecise + OLDVAL := INIVAL; + NEWVAL := (X/OLDVAL + OLDVAL)*0.5; + + -- Check for relative and absolute error and max count + while ( ( (ABS((NEWVAL -OLDVAL)/NEWVAL) > EPS) OR + (ABS(NEWVAL - OLDVAL) > EPS) ) AND + (COUNT < MAX_COUNT) ) loop + OLDVAL := NEWVAL; + NEWVAL := (X/OLDVAL + OLDVAL)*0.5; + COUNT := COUNT + 1; + end loop; + return NEWVAL; + end function SQRT; + + function CBRT (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Uses the Newton-Raphson approximation: + -- F(n+1) = (1/3)*[2*F(n) + x/F(n)**2]; + -- + constant EPS : REAL := BASE_EPS*BASE_EPS; + + variable INIVAL: REAL; + variable XLOCAL : REAL := X; + variable NEGATIVE : BOOLEAN := X < 0.0; + variable OLDVAL : REAL ; + variable NEWVAL : REAL ; + variable COUNT : INTEGER := 1; + + begin + + -- Compute root for special cases + if X = 0.0 then + return 0.0; + elsif ( X = 1.0 ) then + return 1.0; + else + if X = -1.0 then + return -1.0; + end if; + end if; + + -- Compute root for general cases + if NEGATIVE then + XLOCAL := -X; + end if; + + INIVAL := EXP(LOG(XLOCAL)/(3.0)); -- Mathematically correct but + -- imprecise + OLDVAL := INIVAL; + NEWVAL := (XLOCAL/(OLDVAL*OLDVAL) + 2.0*OLDVAL)/3.0; + + -- Check for relative and absolute errors and max count + while ( ( (ABS((NEWVAL -OLDVAL)/NEWVAL) > EPS ) OR + (ABS(NEWVAL - OLDVAL) > EPS ) ) AND + ( COUNT < MAX_COUNT ) ) loop + OLDVAL := NEWVAL; + NEWVAL :=(XLOCAL/(OLDVAL*OLDVAL) + 2.0*OLDVAL)/3.0; + COUNT := COUNT + 1; + end loop; + + if NEGATIVE then + NEWVAL := -NEWVAL; + end if; + + return NEWVAL; + end function CBRT; + + function "**" (X : in INTEGER; Y : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 on error condition + + begin + -- Check validity of argument + if ( ( X < 0 ) and ( Y /= 0.0 ) ) then + assert FALSE + report "X < 0 and Y /= 0.0 in X**Y" + severity ERROR; + return 0.0; + end if; + + if ( ( X = 0 ) and ( Y <= 0.0 ) ) then + assert FALSE + report "X = 0 and Y <= 0.0 in X**Y" + severity ERROR; + return 0.0; + end if; + + -- Get value for special cases + if ( X = 0 and Y > 0.0 ) then + return 0.0; + end if; + + if ( X = 1 ) then + return 1.0; + end if; + + if ( Y = 0.0 and X /= 0 ) then + return 1.0; + end if; + + if ( Y = 1.0) then + return (REAL(X)); + end if; + + -- Get value for general case + return EXP (Y * LOG (REAL(X))); + end function "**"; + + function "**" (X : in REAL; Y : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 on error condition + + begin + -- Check validity of argument + if ( ( X < 0.0 ) and ( Y /= 0.0 ) ) then + assert FALSE + report "X < 0.0 and Y /= 0.0 in X**Y" + severity ERROR; + return 0.0; + end if; + + if ( ( X = 0.0 ) and ( Y <= 0.0 ) ) then + assert FALSE + report "X = 0.0 and Y <= 0.0 in X**Y" + severity ERROR; + return 0.0; + end if; + + -- Get value for special cases + if ( X = 0.0 and Y > 0.0 ) then + return 0.0; + end if; + + if ( X = 1.0 ) then + return 1.0; + end if; + + if ( Y = 0.0 and X /= 0.0 ) then + return 1.0; + end if; + + if ( Y = 1.0) then + return (X); + end if; + + -- Get value for general case + return EXP (Y * LOG (X)); + end function "**"; + + function EXP (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) This function computes the exponential using the following + -- series: + -- exp(x) = 1 + x + x**2/2! + x**3/3! + ... ; |x| < 1.0 + -- and reduces argument X to take advantage of exp(x+y) = + -- exp(x)*exp(y) + -- + -- b) This implementation limits X to be less than LOG(REAL'HIGH) + -- to avoid overflow. Returns REAL'HIGH when X reaches that + -- limit + -- + constant EPS : REAL := BASE_EPS*BASE_EPS*BASE_EPS;-- Precision criteria + + variable RECIPROCAL: BOOLEAN := X < 0.0;-- Check sign of argument + variable XLOCAL : REAL := ABS(X); -- Use positive value + variable OLDVAL: REAL ; + variable COUNT: INTEGER ; + variable NEWVAL: REAL ; + variable LAST_TERM: REAL ; + variable FACTOR : REAL := 1.0; + + begin + -- Compute value for special cases + if X = 0.0 then + return 1.0; + end if; + + if XLOCAL = 1.0 then + if RECIPROCAL then + return MATH_1_OVER_E; + else + return MATH_E; + end if; + end if; + + if XLOCAL = 2.0 then + if RECIPROCAL then + return 1.0/MATH_E_P2; + else + return MATH_E_P2; + end if; + end if; + + if XLOCAL = 10.0 then + if RECIPROCAL then + return 1.0/MATH_E_P10; + else + return MATH_E_P10; + end if; + end if; + + if XLOCAL > LOG(REAL'HIGH) then + if RECIPROCAL then + return 0.0; + else + assert FALSE + report "X > LOG(REAL'HIGH) in EXP(X)" + severity NOTE; + return REAL'HIGH; + end if; + end if; + + -- Reduce argument to ABS(X) < 1.0 + while XLOCAL > 10.0 loop + XLOCAL := XLOCAL - 10.0; + FACTOR := FACTOR*MATH_E_P10; + end loop; + + while XLOCAL > 1.0 loop + XLOCAL := XLOCAL - 1.0; + FACTOR := FACTOR*MATH_E; + end loop; + + -- Compute value for case 0 < XLOCAL < 1 + OLDVAL := 1.0; + LAST_TERM := XLOCAL; + NEWVAL:= OLDVAL + LAST_TERM; + COUNT := 2; + + -- Check for relative and absolute errors and max count + while ( ( (ABS((NEWVAL - OLDVAL)/NEWVAL) > EPS) OR + (ABS(NEWVAL - OLDVAL) > EPS) ) AND + (COUNT < MAX_COUNT ) ) loop + OLDVAL := NEWVAL; + LAST_TERM := LAST_TERM*(XLOCAL / (REAL(COUNT))); + NEWVAL := OLDVAL + LAST_TERM; + COUNT := COUNT + 1; + end loop; + + -- Compute final value using exp(x+y) = exp(x)*exp(y) + NEWVAL := NEWVAL*FACTOR; + + if RECIPROCAL then + NEWVAL := 1.0/NEWVAL; + end if; + + return NEWVAL; + end function EXP; + + + -- + -- Auxiliary Functions to Compute LOG + -- + function ILOGB(X: in REAL) return INTEGER IS + -- Description: + -- Returns n such that -1 <= ABS(X)/2^n < 2 + -- Notes: + -- None + + variable N: INTEGER := 0; + variable Y: REAL := ABS(X); + + begin + if(Y = 1.0 or Y = 0.0) then + return 0; + end if; + + if( Y > 1.0) then + while Y >= 2.0 loop + Y := Y/2.0; + N := N+1; + end loop; + return N; + end if; + + -- O < Y < 1 + while Y < 1.0 loop + Y := Y*2.0; + N := N -1; + end loop; + return N; + end function ILOGB; + + function LDEXP(X: in REAL; N: in INTEGER) RETURN REAL IS + -- Description: + -- Returns X*2^n + -- Notes: + -- None + begin + return X*(2.0 ** N); + end function LDEXP; + + function LOG (X : in REAL ) return REAL IS + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- + -- Notes: + -- a) Returns REAL'LOW on error + -- + -- Copyright (c) 1992 Regents of the University of California. + -- All rights reserved. + -- + -- Redistribution and use in source and binary forms, with or without + -- modification, are permitted provided that the following conditions + -- are met: + -- 1. Redistributions of source code must retain the above copyright + -- notice, this list of conditions and the following disclaimer. + -- 2. Redistributions in binary form must reproduce the above copyright + -- notice, this list of conditions and the following disclaimer in the + -- documentation and/or other materials provided with the distribution. + -- 3. All advertising materials mentioning features or use of this + -- software must display the following acknowledgement: + -- This product includes software developed by the University of + -- California, Berkeley and its contributors. + -- 4. Neither the name of the University nor the names of its + -- contributors may be used to endorse or promote products derived + -- from this software without specific prior written permission. + -- + -- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' + -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + -- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR + -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + -- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + -- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + -- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + -- DAMAGE. + -- + -- NOTE: This VHDL version was generated using the C version of the + -- original function by the IEEE VHDL Mathematical Package + -- Working Group (CS/JT) + + constant N: INTEGER := 128; + + -- Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128. + -- Used for generation of extend precision logarithms. + -- The constant 35184372088832 is 2^45, so the divide is exact. + -- It ensures correct reading of logF_head, even for inaccurate + -- decimal-to-binary conversion routines. (Everybody gets the + -- right answer for INTEGERs less than 2^53.) + -- Values for LOG(F) were generated using error < 10^-57 absolute + -- with the bc -l package. + + type REAL_VECTOR is array (NATURAL range <>) of REAL; + + constant A1:REAL := 0.08333333333333178827; + constant A2:REAL := 0.01250000000377174923; + constant A3:REAL := 0.002232139987919447809; + constant A4:REAL := 0.0004348877777076145742; + + constant LOGF_HEAD: REAL_VECTOR(0 TO N) := ( + 0.0, + 0.007782140442060381246, + 0.015504186535963526694, + 0.023167059281547608406, + 0.030771658666765233647, + 0.038318864302141264488, + 0.045809536031242714670, + 0.053244514518837604555, + 0.060624621816486978786, + 0.067950661908525944454, + 0.075223421237524235039, + 0.082443669210988446138, + 0.089612158689760690322, + 0.096729626458454731618, + 0.103796793681567578460, + 0.110814366340264314203, + 0.117783035656430001836, + 0.124703478501032805070, + 0.131576357788617315236, + 0.138402322859292326029, + 0.145182009844575077295, + 0.151916042025732167530, + 0.158605030176659056451, + 0.165249572895390883786, + 0.171850256926518341060, + 0.178407657472689606947, + 0.184922338493834104156, + 0.191394852999565046047, + 0.197825743329758552135, + 0.204215541428766300668, + 0.210564769107350002741, + 0.216873938300523150246, + 0.223143551314024080056, + 0.229374101064877322642, + 0.235566071312860003672, + 0.241719936886966024758, + 0.247836163904594286577, + 0.253915209980732470285, + 0.259957524436686071567, + 0.265963548496984003577, + 0.271933715484010463114, + 0.277868451003087102435, + 0.283768173130738432519, + 0.289633292582948342896, + 0.295464212893421063199, + 0.301261330578199704177, + 0.307025035294827830512, + 0.312755710004239517729, + 0.318453731118097493890, + 0.324119468654316733591, + 0.329753286372579168528, + 0.335355541920762334484, + 0.340926586970454081892, + 0.346466767346100823488, + 0.351976423156884266063, + 0.357455888922231679316, + 0.362905493689140712376, + 0.368325561158599157352, + 0.373716409793814818840, + 0.379078352934811846353, + 0.384411698910298582632, + 0.389716751140440464951, + 0.394993808240542421117, + 0.400243164127459749579, + 0.405465108107819105498, + 0.410659924985338875558, + 0.415827895143593195825, + 0.420969294644237379543, + 0.426084395310681429691, + 0.431173464818130014464, + 0.436236766774527495726, + 0.441274560805140936281, + 0.446287102628048160113, + 0.451274644139630254358, + 0.456237433481874177232, + 0.461175715122408291790, + 0.466089729924533457960, + 0.470979715219073113985, + 0.475845904869856894947, + 0.480688529345570714212, + 0.485507815781602403149, + 0.490303988045525329653, + 0.495077266798034543171, + 0.499827869556611403822, + 0.504556010751912253908, + 0.509261901790523552335, + 0.513945751101346104405, + 0.518607764208354637958, + 0.523248143765158602036, + 0.527867089620485785417, + 0.532464798869114019908, + 0.537041465897345915436, + 0.541597282432121573947, + 0.546132437597407260909, + 0.550647117952394182793, + 0.555141507540611200965, + 0.559615787935399566777, + 0.564070138285387656651, + 0.568504735352689749561, + 0.572919753562018740922, + 0.577315365035246941260, + 0.581691739635061821900, + 0.586049045003164792433, + 0.590387446602107957005, + 0.594707107746216934174, + 0.599008189645246602594, + 0.603290851438941899687, + 0.607555250224322662688, + 0.611801541106615331955, + 0.616029877215623855590, + 0.620240409751204424537, + 0.624433288012369303032, + 0.628608659422752680256, + 0.632766669570628437213, + 0.636907462236194987781, + 0.641031179420679109171, + 0.645137961373620782978, + 0.649227946625615004450, + 0.653301272011958644725, + 0.657358072709030238911, + 0.661398482245203922502, + 0.665422632544505177065, + 0.669430653942981734871, + 0.673422675212350441142, + 0.677398823590920073911, + 0.681359224807238206267, + 0.685304003098281100392, + 0.689233281238557538017, + 0.693147180560117703862); + + constant LOGF_TAIL: REAL_VECTOR(0 TO N) := ( + 0.0, + -0.00000000000000543229938420049, + 0.00000000000000172745674997061, + -0.00000000000001323017818229233, + -0.00000000000001154527628289872, + -0.00000000000000466529469958300, + 0.00000000000005148849572685810, + -0.00000000000002532168943117445, + -0.00000000000005213620639136504, + -0.00000000000001819506003016881, + 0.00000000000006329065958724544, + 0.00000000000008614512936087814, + -0.00000000000007355770219435028, + 0.00000000000009638067658552277, + 0.00000000000007598636597194141, + 0.00000000000002579999128306990, + -0.00000000000004654729747598444, + -0.00000000000007556920687451336, + 0.00000000000010195735223708472, + -0.00000000000017319034406422306, + -0.00000000000007718001336828098, + 0.00000000000010980754099855238, + -0.00000000000002047235780046195, + -0.00000000000008372091099235912, + 0.00000000000014088127937111135, + 0.00000000000012869017157588257, + 0.00000000000017788850778198106, + 0.00000000000006440856150696891, + 0.00000000000016132822667240822, + -0.00000000000007540916511956188, + -0.00000000000000036507188831790, + 0.00000000000009120937249914984, + 0.00000000000018567570959796010, + -0.00000000000003149265065191483, + -0.00000000000009309459495196889, + 0.00000000000017914338601329117, + -0.00000000000001302979717330866, + 0.00000000000023097385217586939, + 0.00000000000023999540484211737, + 0.00000000000015393776174455408, + -0.00000000000036870428315837678, + 0.00000000000036920375082080089, + -0.00000000000009383417223663699, + 0.00000000000009433398189512690, + 0.00000000000041481318704258568, + -0.00000000000003792316480209314, + 0.00000000000008403156304792424, + -0.00000000000034262934348285429, + 0.00000000000043712191957429145, + -0.00000000000010475750058776541, + -0.00000000000011118671389559323, + 0.00000000000037549577257259853, + 0.00000000000013912841212197565, + 0.00000000000010775743037572640, + 0.00000000000029391859187648000, + -0.00000000000042790509060060774, + 0.00000000000022774076114039555, + 0.00000000000010849569622967912, + -0.00000000000023073801945705758, + 0.00000000000015761203773969435, + 0.00000000000003345710269544082, + -0.00000000000041525158063436123, + 0.00000000000032655698896907146, + -0.00000000000044704265010452446, + 0.00000000000034527647952039772, + -0.00000000000007048962392109746, + 0.00000000000011776978751369214, + -0.00000000000010774341461609578, + 0.00000000000021863343293215910, + 0.00000000000024132639491333131, + 0.00000000000039057462209830700, + -0.00000000000026570679203560751, + 0.00000000000037135141919592021, + -0.00000000000017166921336082431, + -0.00000000000028658285157914353, + -0.00000000000023812542263446809, + 0.00000000000006576659768580062, + -0.00000000000028210143846181267, + 0.00000000000010701931762114254, + 0.00000000000018119346366441110, + 0.00000000000009840465278232627, + -0.00000000000033149150282752542, + -0.00000000000018302857356041668, + -0.00000000000016207400156744949, + 0.00000000000048303314949553201, + -0.00000000000071560553172382115, + 0.00000000000088821239518571855, + -0.00000000000030900580513238244, + -0.00000000000061076551972851496, + 0.00000000000035659969663347830, + 0.00000000000035782396591276383, + -0.00000000000046226087001544578, + 0.00000000000062279762917225156, + 0.00000000000072838947272065741, + 0.00000000000026809646615211673, + -0.00000000000010960825046059278, + 0.00000000000002311949383800537, + -0.00000000000058469058005299247, + -0.00000000000002103748251144494, + -0.00000000000023323182945587408, + -0.00000000000042333694288141916, + -0.00000000000043933937969737844, + 0.00000000000041341647073835565, + 0.00000000000006841763641591466, + 0.00000000000047585534004430641, + 0.00000000000083679678674757695, + -0.00000000000085763734646658640, + 0.00000000000021913281229340092, + -0.00000000000062242842536431148, + -0.00000000000010983594325438430, + 0.00000000000065310431377633651, + -0.00000000000047580199021710769, + -0.00000000000037854251265457040, + 0.00000000000040939233218678664, + 0.00000000000087424383914858291, + 0.00000000000025218188456842882, + -0.00000000000003608131360422557, + -0.00000000000050518555924280902, + 0.00000000000078699403323355317, + -0.00000000000067020876961949060, + 0.00000000000016108575753932458, + 0.00000000000058527188436251509, + -0.00000000000035246757297904791, + -0.00000000000018372084495629058, + 0.00000000000088606689813494916, + 0.00000000000066486268071468700, + 0.00000000000063831615170646519, + 0.00000000000025144230728376072, + -0.00000000000017239444525614834); + + variable M, J:INTEGER; + variable F1, F2, G, Q, U, U2, V: REAL; + variable ZERO: REAL := 0.0;--Made variable so no constant folding occurs + variable ONE: REAL := 1.0; --Made variable so no constant folding occurs + + -- double logb(), ldexp(); + + variable U1:REAL; + + begin + + -- Check validity of argument + if ( X <= 0.0 ) then + assert FALSE + report "X <= 0.0 in LOG(X)" + severity ERROR; + return(REAL'LOW); + end if; + + -- Compute value for special cases + if ( X = 1.0 ) then + return 0.0; + end if; + + if ( X = MATH_E ) then + return 1.0; + end if; + + -- Argument reduction: 1 <= g < 2; x/2^m = g; + -- y = F*(1 + f/F) for |f| <= 2^-8 + + M := ILOGB(X); + G := LDEXP(X, -M); + J := INTEGER(REAL(N)*(G-1.0)); -- C code adds 0.5 for rounding + F1 := (1.0/REAL(N)) * REAL(J) + 1.0; --F1*128 is an INTEGER in [128,512] + F2 := G - F1; + + -- Approximate expansion for log(1+f2/F1) ~= u + q + G := 1.0/(2.0*F1+F2); + U := 2.0*F2*G; + V := U*U; + Q := U*V*(A1 + V*(A2 + V*(A3 + V*A4))); + + -- Case 1: u1 = u rounded to 2^-43 absolute. Since u < 2^-8, + -- u1 has at most 35 bits, and F1*u1 is exact, as F1 has < 8 bits. + -- It also adds exactly to |m*log2_hi + log_F_head[j] | < 750. + -- + if ( J /= 0 or M /= 0) then + U1 := U + 513.0; + U1 := U1 - 513.0; + + -- Case 2: |1-x| < 1/256. The m- and j- dependent terms are zero + -- u1 = u to 24 bits. + -- + else + U1 := U; + --TRUNC(U1); --In c this is u1 = (double) (float) (u1) + end if; + + U2 := (2.0*(F2 - F1*U1) - U1*F2) * G; + -- u1 + u2 = 2f/(2F+f) to extra precision. + + -- log(x) = log(2^m*F1*(1+f2/F1)) = + -- (m*log2_hi+LOGF_HEAD(j)+u1) + (m*log2_lo+LOGF_TAIL(j)+q); + -- (exact) + (tiny) + + U1 := U1 + REAL(M)*LOGF_HEAD(N) + LOGF_HEAD(J); -- Exact + U2 := (U2 + LOGF_TAIL(J)) + Q; -- Tiny + U2 := U2 + LOGF_TAIL(N)*REAL(M); + return (U1 + U2); + end function LOG; + + + function LOG2 (X: in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns REAL'LOW on error + begin + -- Check validity of arguments + if ( X <= 0.0 ) then + assert FALSE + report "X <= 0.0 in LOG2(X)" + severity ERROR; + return(REAL'LOW); + end if; + + -- Compute value for special cases + if ( X = 1.0 ) then + return 0.0; + end if; + + if ( X = 2.0 ) then + return 1.0; + end if; + + -- Compute value for general case + return ( MATH_LOG2_OF_E*LOG(X) ); + end function LOG2; + + + function LOG10 (X: in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns REAL'LOW on error + begin + -- Check validity of arguments + if ( X <= 0.0 ) then + assert FALSE + report "X <= 0.0 in LOG10(X)" + severity ERROR; + return(REAL'LOW); + end if; + + -- Compute value for special cases + if ( X = 1.0 ) then + return 0.0; + end if; + + if ( X = 10.0 ) then + return 1.0; + end if; + + -- Compute value for general case + return ( MATH_LOG10_OF_E*LOG(X) ); + end function LOG10; + + + function LOG (X: in REAL; BASE: in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns REAL'LOW on error + begin + -- Check validity of arguments + if ( X <= 0.0 ) then + assert FALSE + report "X <= 0.0 in LOG(X, BASE)" + severity ERROR; + return(REAL'LOW); + end if; + + if ( BASE <= 0.0 or BASE = 1.0 ) then + assert FALSE + report "BASE <= 0.0 or BASE = 1.0 in LOG(X, BASE)" + severity ERROR; + return(REAL'LOW); + end if; + + -- Compute value for special cases + if ( X = 1.0 ) then + return 0.0; + end if; + + if ( X = BASE ) then + return 1.0; + end if; + + -- Compute value for general case + return ( LOG(X)/LOG(BASE)); + end function LOG; + + + function SIN (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) SIN(-X) = -SIN(X) + -- b) SIN(X) = X if ABS(X) < EPS + -- c) SIN(X) = X - X**3/3! if EPS < ABS(X) < BASE_EPS + -- d) SIN(MATH_PI_OVER_2 - X) = COS(X) + -- e) COS(X) = 1.0 - 0.5*X**2 if ABS(X) < EPS + -- f) COS(X) = 1.0 - 0.5*X**2 + (X**4)/4! if + -- EPS< ABS(X) MATH_2_PI then + TEMP := FLOOR(XLOCAL/MATH_2_PI); + XLOCAL := XLOCAL - TEMP*MATH_2_PI; + end if; + + if XLOCAL < 0.0 then + -- adjust for rounding error + XLOCAL := 0.0; + end if; + + -- Compute value for special cases + if XLOCAL = 0.0 or XLOCAL = MATH_2_PI or XLOCAL = MATH_PI then + return 0.0; + end if; + + if XLOCAL = MATH_PI_OVER_2 then + if NEGATIVE then + return -1.0; + else + return 1.0; + end if; + end if; + + if XLOCAL = MATH_3_PI_OVER_2 then + if NEGATIVE then + return 1.0; + else + return -1.0; + end if; + end if; + + if XLOCAL < EPS then + if NEGATIVE then + return -XLOCAL; + else + return XLOCAL; + end if; + else + if XLOCAL < BASE_EPS then + TEMP := XLOCAL - (XLOCAL*XLOCAL*XLOCAL)/6.0; + if NEGATIVE then + return -TEMP; + else + return TEMP; + end if; + end if; + end if; + + TEMP := MATH_PI - XLOCAL; + if ABS(TEMP) < EPS then + if NEGATIVE then + return -TEMP; + else + return TEMP; + end if; + else + if ABS(TEMP) < BASE_EPS then + TEMP := TEMP - (TEMP*TEMP*TEMP)/6.0; + if NEGATIVE then + return -TEMP; + else + return TEMP; + end if; + end if; + end if; + + TEMP := MATH_2_PI - XLOCAL; + if ABS(TEMP) < EPS then + if NEGATIVE then + return TEMP; + else + return -TEMP; + end if; + else + if ABS(TEMP) < BASE_EPS then + TEMP := TEMP - (TEMP*TEMP*TEMP)/6.0; + if NEGATIVE then + return TEMP; + else + return -TEMP; + end if; + end if; + end if; + + TEMP := ABS(MATH_PI_OVER_2 - XLOCAL); + if TEMP < EPS then + TEMP := 1.0 - TEMP*TEMP*0.5; + if NEGATIVE then + return -TEMP; + else + return TEMP; + end if; + else + if TEMP < BASE_EPS then + TEMP := 1.0 -TEMP*TEMP*0.5 + TEMP*TEMP*TEMP*TEMP/24.0; + if NEGATIVE then + return -TEMP; + else + return TEMP; + end if; + end if; + end if; + + TEMP := ABS(MATH_3_PI_OVER_2 - XLOCAL); + if TEMP < EPS then + TEMP := 1.0 - TEMP*TEMP*0.5; + if NEGATIVE then + return TEMP; + else + return -TEMP; + end if; + else + if TEMP < BASE_EPS then + TEMP := 1.0 -TEMP*TEMP*0.5 + TEMP*TEMP*TEMP*TEMP/24.0; + if NEGATIVE then + return TEMP; + else + return -TEMP; + end if; + end if; + end if; + + -- Compute value for general cases + if ((XLOCAL < MATH_PI_OVER_2 ) and (XLOCAL > 0.0)) then + VALUE:= CORDIC( KC, 0.0, x, 27, ROTATION)(1); + end if; + + N := INTEGER ( FLOOR(XLOCAL/MATH_PI_OVER_2)); + case QUADRANT( N mod 4) is + when 0 => + VALUE := CORDIC( KC, 0.0, XLOCAL, 27, ROTATION)(1); + when 1 => + VALUE := CORDIC( KC, 0.0, XLOCAL - MATH_PI_OVER_2, 27, + ROTATION)(0); + when 2 => + VALUE := -CORDIC( KC, 0.0, XLOCAL - MATH_PI, 27, ROTATION)(1); + when 3 => + VALUE := -CORDIC( KC, 0.0, XLOCAL - MATH_3_PI_OVER_2, 27, + ROTATION)(0); + end case; + + if NEGATIVE then + return -VALUE; + else + return VALUE; + end if; + end function SIN; + + + function COS (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) COS(-X) = COS(X) + -- b) COS(X) = SIN(MATH_PI_OVER_2 - X) + -- c) COS(MATH_PI + X) = -COS(X) + -- d) COS(X) = 1.0 - X*X/2.0 if ABS(X) < EPS + -- e) COS(X) = 1.0 - 0.5*X**2 + (X**4)/4! if + -- EPS< ABS(X) MATH_2_PI then + TEMP := FLOOR(XLOCAL/MATH_2_PI); + XLOCAL := XLOCAL - TEMP*MATH_2_PI; + end if; + + if XLOCAL < 0.0 then + -- adjust for rounding error + XLOCAL := 0.0; + end if; + + -- Compute value for special cases + if XLOCAL = 0.0 or XLOCAL = MATH_2_PI then + return 1.0; + end if; + + if XLOCAL = MATH_PI then + return -1.0; + end if; + + if XLOCAL = MATH_PI_OVER_2 or XLOCAL = MATH_3_PI_OVER_2 then + return 0.0; + end if; + + TEMP := ABS(XLOCAL); + if ( TEMP < EPS) then + return (1.0 - 0.5*TEMP*TEMP); + else + if (TEMP < BASE_EPS) then + return (1.0 -0.5*TEMP*TEMP + TEMP*TEMP*TEMP*TEMP/24.0); + end if; + end if; + + TEMP := ABS(XLOCAL -MATH_2_PI); + if ( TEMP < EPS) then + return (1.0 - 0.5*TEMP*TEMP); + else + if (TEMP < BASE_EPS) then + return (1.0 -0.5*TEMP*TEMP + TEMP*TEMP*TEMP*TEMP/24.0); + end if; + end if; + + TEMP := ABS (XLOCAL - MATH_PI); + if TEMP < EPS then + return (-1.0 + 0.5*TEMP*TEMP); + else + if (TEMP < BASE_EPS) then + return (-1.0 +0.5*TEMP*TEMP - TEMP*TEMP*TEMP*TEMP/24.0); + end if; + end if; + + -- Compute value for general cases + return SIN(MATH_PI_OVER_2 - XLOCAL); + end function COS; + + function TAN (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) TAN(0.0) = 0.0 + -- b) TAN(-X) = -TAN(X) + -- c) Returns REAL'LOW on error if X < 0.0 + -- d) Returns REAL'HIGH on error if X > 0.0 + + variable NEGATIVE : BOOLEAN := X < 0.0; + variable XLOCAL : REAL := ABS(X) ; + variable VALUE: REAL; + variable TEMP : REAL; + + begin + -- Make 0.0 <= XLOCAL <= MATH_2_PI + if XLOCAL > MATH_2_PI then + TEMP := FLOOR(XLOCAL/MATH_2_PI); + XLOCAL := XLOCAL - TEMP*MATH_2_PI; + end if; + + if XLOCAL < 0.0 then + -- adjust for rounding error + XLOCAL := 0.0; + end if; + + -- Check validity of argument + if XLOCAL = MATH_PI_OVER_2 then + assert FALSE + report "X is a multiple of MATH_PI_OVER_2 in TAN(X)" + severity ERROR; + if NEGATIVE then + return(REAL'LOW); + else + return(REAL'HIGH); + end if; + end if; + + if XLOCAL = MATH_3_PI_OVER_2 then + assert FALSE + report "X is a multiple of MATH_3_PI_OVER_2 in TAN(X)" + severity ERROR; + if NEGATIVE then + return(REAL'HIGH); + else + return(REAL'LOW); + end if; + end if; + + -- Compute value for special cases + if XLOCAL = 0.0 or XLOCAL = MATH_PI then + return 0.0; + end if; + + -- Compute value for general cases + VALUE := SIN(XLOCAL)/COS(XLOCAL); + if NEGATIVE then + return -VALUE; + else + return VALUE; + end if; + end function TAN; + + function ARCSIN (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) ARCSIN(-X) = -ARCSIN(X) + -- b) Returns X on error + + variable NEGATIVE : BOOLEAN := X < 0.0; + variable XLOCAL : REAL := ABS(X); + variable VALUE : REAL; + + begin + -- Check validity of arguments + if XLOCAL > 1.0 then + assert FALSE + report "ABS(X) > 1.0 in ARCSIN(X)" + severity ERROR; + return X; + end if; + + -- Compute value for special cases + if XLOCAL = 0.0 then + return 0.0; + elsif XLOCAL = 1.0 then + if NEGATIVE then + return -MATH_PI_OVER_2; + else + return MATH_PI_OVER_2; + end if; + end if; + + -- Compute value for general cases + if XLOCAL < 0.9 then + VALUE := ARCTAN(XLOCAL/(SQRT(1.0 - XLOCAL*XLOCAL))); + else + VALUE := MATH_PI_OVER_2 - ARCTAN(SQRT(1.0 - XLOCAL*XLOCAL)/XLOCAL); + end if; + + if NEGATIVE then + VALUE := -VALUE; + end if; + + return VALUE; + end function ARCSIN; + + function ARCCOS (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) ARCCOS(-X) = MATH_PI - ARCCOS(X) + -- b) Returns X on error + + variable NEGATIVE : BOOLEAN := X < 0.0; + variable XLOCAL : REAL := ABS(X); + variable VALUE : REAL; + + begin + -- Check validity of argument + if XLOCAL > 1.0 then + assert FALSE + report "ABS(X) > 1.0 in ARCCOS(X)" + severity ERROR; + return X; + end if; + + -- Compute value for special cases + if X = 1.0 then + return 0.0; + elsif X = 0.0 then + return MATH_PI_OVER_2; + elsif X = -1.0 then + return MATH_PI; + end if; + + -- Compute value for general cases + if XLOCAL > 0.9 then + VALUE := ARCTAN(SQRT(1.0 - XLOCAL*XLOCAL)/XLOCAL); + else + VALUE := MATH_PI_OVER_2 - ARCTAN(XLOCAL/SQRT(1.0 - XLOCAL*XLOCAL)); + end if; + + + if NEGATIVE then + VALUE := MATH_PI - VALUE; + end if; + + return VALUE; + end function ARCCOS; + + + function ARCTAN (Y : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) ARCTAN(-Y) = -ARCTAN(Y) + -- b) ARCTAN(Y) = -ARCTAN(1.0/Y) + MATH_PI_OVER_2 for |Y| > 1.0 + -- c) ARCTAN(Y) = Y for |Y| < EPS + + constant EPS : REAL := BASE_EPS*BASE_EPS*BASE_EPS; + + variable NEGATIVE : BOOLEAN := Y < 0.0; + variable RECIPROCAL : BOOLEAN; + variable YLOCAL : REAL := ABS(Y); + variable VALUE : REAL; + + begin + -- Make argument |Y| <=1.0 + if YLOCAL > 1.0 then + YLOCAL := 1.0/YLOCAL; + RECIPROCAL := TRUE; + else + RECIPROCAL := FALSE; + end if; + + -- Compute value for special cases + if YLOCAL = 0.0 then + if RECIPROCAL then + if NEGATIVE then + return (-MATH_PI_OVER_2); + else + return (MATH_PI_OVER_2); + end if; + else + return 0.0; + end if; + end if; + + if YLOCAL < EPS then + if NEGATIVE then + if RECIPROCAL then + return (-MATH_PI_OVER_2 + YLOCAL); + else + return -YLOCAL; + end if; + else + if RECIPROCAL then + return (MATH_PI_OVER_2 - YLOCAL); + else + return YLOCAL; + end if; + end if; + end if; + + -- Compute value for general cases + VALUE := CORDIC( 1.0, YLOCAL, 0.0, 27, VECTORING )(2); + + if RECIPROCAL then + VALUE := MATH_PI_OVER_2 - VALUE; + end if; + + if NEGATIVE then + VALUE := -VALUE; + end if; + + return VALUE; + end function ARCTAN; + + + function ARCTAN (Y : in REAL; X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 on error + + variable YLOCAL : REAL; + variable VALUE : REAL; + begin + + -- Check validity of arguments + if (Y = 0.0 and X = 0.0 ) then + assert FALSE report + "ARCTAN(0.0, 0.0) is undetermined" + severity ERROR; + return 0.0; + end if; + + -- Compute value for special cases + if Y = 0.0 then + if X > 0.0 then + return 0.0; + else + return MATH_PI; + end if; + end if; + + if X = 0.0 then + if Y > 0.0 then + return MATH_PI_OVER_2; + else + return -MATH_PI_OVER_2; + end if; + end if; + + + -- Compute value for general cases + YLOCAL := ABS(Y/X); + + VALUE := ARCTAN(YLOCAL); + + if X < 0.0 then + VALUE := MATH_PI - VALUE; + end if; + + if Y < 0.0 then + VALUE := -VALUE; + end if; + + return VALUE; + end function ARCTAN; + + + function SINH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns (EXP(X) - EXP(-X))/2.0 + -- b) SINH(-X) = SINH(X) + + variable NEGATIVE : BOOLEAN := X < 0.0; + variable XLOCAL : REAL := ABS(X); + variable TEMP : REAL; + variable VALUE : REAL; + + begin + -- Compute value for special cases + if XLOCAL = 0.0 then + return 0.0; + end if; + + -- Compute value for general cases + TEMP := EXP(XLOCAL); + VALUE := (TEMP - 1.0/TEMP)*0.5; + + if NEGATIVE then + VALUE := -VALUE; + end if; + + return VALUE; + end function SINH; + + function COSH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns (EXP(X) + EXP(-X))/2.0 + -- b) COSH(-X) = COSH(X) + + variable XLOCAL : REAL := ABS(X); + variable TEMP : REAL; + variable VALUE : REAL; + begin + -- Compute value for special cases + if XLOCAL = 0.0 then + return 1.0; + end if; + + + -- Compute value for general cases + TEMP := EXP(XLOCAL); + VALUE := (TEMP + 1.0/TEMP)*0.5; + + return VALUE; + end function COSH; + + function TANH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns (EXP(X) - EXP(-X))/(EXP(X) + EXP(-X)) + -- b) TANH(-X) = -TANH(X) + + variable NEGATIVE : BOOLEAN := X < 0.0; + variable XLOCAL : REAL := ABS(X); + variable TEMP : REAL; + variable VALUE : REAL; + + begin + -- Compute value for special cases + if XLOCAL = 0.0 then + return 0.0; + end if; + + -- Compute value for general cases + TEMP := EXP(XLOCAL); + VALUE := (TEMP - 1.0/TEMP)/(TEMP + 1.0/TEMP); + + if NEGATIVE then + return -VALUE; + else + return VALUE; + end if; + end function TANH; + + function ARCSINH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns LOG( X + SQRT( X*X + 1.0)) + + begin + -- Compute value for special cases + if X = 0.0 then + return 0.0; + end if; + + -- Compute value for general cases + return ( LOG( X + SQRT( X*X + 1.0)) ); + end function ARCSINH; + + + + function ARCCOSH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns LOG( X + SQRT( X*X - 1.0)); X >= 1.0 + -- b) Returns X on error + + begin + -- Check validity of arguments + if X < 1.0 then + assert FALSE + report "X < 1.0 in ARCCOSH(X)" + severity ERROR; + return X; + end if; + + -- Compute value for special cases + if X = 1.0 then + return 0.0; + end if; + + -- Compute value for general cases + return ( LOG( X + SQRT( X*X - 1.0))); + end function ARCCOSH; + + function ARCTANH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns (LOG( (1.0 + X)/(1.0 - X)))/2.0 ; | X | < 1.0 + -- b) Returns X on error + begin + -- Check validity of arguments + if ABS(X) >= 1.0 then + assert FALSE + report "ABS(X) >= 1.0 in ARCTANH(X)" + severity ERROR; + return X; + end if; + + -- Compute value for special cases + if X = 0.0 then + return 0.0; + end if; + + -- Compute value for general cases + return( 0.5*LOG( (1.0+X)/(1.0-X) ) ); + end function ARCTANH; + +end package body MATH_REAL;
trunk/sim/rtl_sim/src/math_real.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/sim/rtl_sim/bin/testroundings.sh =================================================================== --- trunk/sim/rtl_sim/bin/testroundings.sh (nonexistent) +++ trunk/sim/rtl_sim/bin/testroundings.sh (revision 2) @@ -0,0 +1,11 @@ +#!/bin/bash + +vsim -c -do "testroundings.do" +if [ "$SECONDS" -eq 1 ] +then + units=second +else + units=seconds +fi +echo "This script has been running for $SECONDS $units." +exit 0
trunk/sim/rtl_sim/bin/testroundings.sh Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/sim/rtl_sim/bin/testroundingu.sh =================================================================== --- trunk/sim/rtl_sim/bin/testroundingu.sh (nonexistent) +++ trunk/sim/rtl_sim/bin/testroundingu.sh (revision 2) @@ -0,0 +1,11 @@ +#!/bin/bash + +vsim -c -do "testroundingu.do" +if [ "$SECONDS" -eq 1 ] +then + units=second +else + units=seconds +fi +echo "This script has been running for $SECONDS $units." +exit 0
trunk/sim/rtl_sim/bin/testroundingu.sh Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/sim/rtl_sim/bin/testroundings.do =================================================================== --- trunk/sim/rtl_sim/bin/testroundings.do (nonexistent) +++ trunk/sim/rtl_sim/bin/testroundings.do (revision 2) @@ -0,0 +1,13 @@ +# Author: Nikolaos Kavvadias (C) 2009, 2010, 2011 +vlib work +vcom ../src/math_real.vhd +vcom ../src/fixed_float_types_custom.vhd +vcom ../src/fixed_pkg_c.vhd +vcom ../../../rtl/vhdl/fixed_extensions_pkg_sim.vhd +vcom ../../../gen/vhdl/testroundings.vhd +vcom ../../../bench/vhdl/testrounding_tb.vhd +vsim testrounding_tb +vcd dumpports -file testrounding_fsmd.vcd /testrounding_tb/uut/* -unique +onbreak {quit -f} +run -all +exit -f
trunk/sim/rtl_sim/bin/testroundings.do Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/sim/rtl_sim/bin/testroundingu.do =================================================================== --- trunk/sim/rtl_sim/bin/testroundingu.do (nonexistent) +++ trunk/sim/rtl_sim/bin/testroundingu.do (revision 2) @@ -0,0 +1,13 @@ +# Author: Nikolaos Kavvadias (C) 2009, 2010, 2011 +vlib work +vcom ../src/math_real.vhd +vcom ../src/fixed_float_types_custom.vhd +vcom ../src/fixed_pkg_c.vhd +vcom ../../../rtl/vhdl/fixed_extensions_pkg_sim.vhd +vcom ../../../gen/vhdl/testroundingu.vhd +vcom ../../../bench/vhdl/testrounding_tb.vhd +vsim testrounding_tb +vcd dumpports -file testrounding_fsmd.vcd /testrounding_tb/uut/* -unique +onbreak {quit -f} +run -all +exit -f
trunk/sim/rtl_sim/bin/testroundingu.do Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/sim/rtl_sim/bin/run.sh =================================================================== --- trunk/sim/rtl_sim/bin/run.sh (nonexistent) +++ trunk/sim/rtl_sim/bin/run.sh (revision 2) @@ -0,0 +1,18 @@ +#!/bin/bash + +# Test sfixed rounding +#../../../sw/gentestround -signed -iw 4 -fw 4 -step 0.25 ../../../gen/vhdl/testroundings.vhd +#./testroundings.sh + +# Test ufixed rounding +../../../sw/gentestround -unsigned -iw 4 -fw 4 -step 0.25 ../../../gen/vhdl/testroundingu.vhd +./testroundingu.sh + +if [ "$SECONDS" -eq 1 ] +then + units=second +else + units=seconds +fi +echo "This script has been running for $SECONDS $units." +exit 0
trunk/sim/rtl_sim/bin/run.sh Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/sw/gentestround.c =================================================================== --- trunk/sw/gentestround.c (nonexistent) +++ trunk/sw/gentestround.c (revision 2) @@ -0,0 +1,493 @@ +/* + * File : gentestround.c + * Description: Generator for test designs for evaluating signed/unsigned + * fixed-point (sfixed/ufixed) rounding operators. + * Author : Nikolaos Kavvadias + * Copyright : (C) Nikolaos Kavvadias 2011 + * Website : http://www.nkavvadias.com + * + * This file is part of fixed_extensions, and is distributed under the terms + * of the Modified BSD License. + * + * A copy of the Modified BSD License is included with this distrubution + * in the files /doc/COPYING.BSD. + * fixed_extensions is free software: you can redistribute it and/or modify + * it under the terms of the Modified BSD License. + * fixed_extensions is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the Modified BSD License for more + * details. + * + * You should have received a copy of the Modified BSD License along with + * fixed_extensions. If not, see . + */ + +#include +#include +#include +#include + +/* Absolute value of an integer. */ +#define ABS(x) ((x) > 0 ? (x) : (-x)) + +int enable_debug=0; +int iw_val=4, fw_val=4; +double step_val=0.25; +int enable_signed=0, enable_unsigned=1; + + +/* print_spaces: + * Print a configurable number of space characters to an output file (specified + * by the given filename; the file is assumed already opened). + */ +void print_spaces(FILE *f, int nspaces) +{ + int i; + for (i = 0; i < nspaces; i++) + { + fprintf(f, " "); + } +} + +/* pfprintf: + * fprintf prefixed by a number of space characters. + */ +void pfprintf(FILE *f, int nspaces, char *fmt, ...) +{ + va_list args; + print_spaces(f, nspaces); + va_start(args, fmt); + vfprintf(f, fmt, args); + va_end(args); +} + +/* ipowul: + * Calculate integer power supporting results up to 64-bits. + */ +unsigned long long int ipowul(int base, int exponent) +{ + unsigned long long int temp; + int i; + + temp = 1; + + for (i = 0; i < exponent; i++) + { + temp *= (unsigned int)base; + } + + return (temp); +} + +/* calculate_samples: + * Calculate the number of samples needed for the test design. + */ +unsigned long long int calculate_samples(int iw, int fw, int step) +{ + unsigned long long int nsamples; + + /* FIXME: Should be the same for both cases! */ + /* Samples range: 0 to 2^IW-2^FW. */ + if (enable_unsigned == 1) + { +// nsamples = (ipowul(2, iw) - ipowul(2, -fw)) / ipowul(2, -fw) + 1; + nsamples = ipowul(2, iw+fw); + } + /* Samples range: -2^(IW-1) to 2^(IW-1)-2^FW. */ + else if (enable_signed == 1) + { +// nsamples = ipowul(2, iw) / ipowul(2, fw); + nsamples = ipowul(2, iw+fw); + } + + return nsamples; +} + +/* print_test_prologue: + * Prints the prologue for the generated test design file. + */ +void print_test_prologue(FILE *infile) +{ + pfprintf(infile, 0, "library IEEE;\n"); + pfprintf(infile, 0, "use IEEE.std_logic_1164.all;\n"); + pfprintf(infile, 0, "use IEEE.numeric_std.all;\n"); + pfprintf(infile, 0, "use WORK.fixed_float_types.all;\n"); + pfprintf(infile, 0, "use WORK.fixed_pkg.all;\n"); + pfprintf(infile, 0, "use WORK.fixed_extensions_pkg.all;\n"); + fprintf(infile, "\n"); +} + +/* print_test_entity: + * Prints the entity of the generated test design file. + */ +void print_test_entity(FILE *infile, unsigned int iw, unsigned int fw) +{ + pfprintf(infile, 0, "entity testrounding is\n"); + pfprintf(infile, 2, "port (\n"); + pfprintf(infile, 4, "clk : in std_logic;\n"); + pfprintf(infile, 4, "reset : in std_logic;\n"); + pfprintf(infile, 4, "start : in std_logic;\n"); + pfprintf(infile, 4, "ok : out sfixed(%d downto -%d)\n", iw-1, fw); + pfprintf(infile, 2, ");\n"); + pfprintf(infile, 0, "end testrounding;\n\n"); +} + +/* print_test_architecture_prologue: + * Prints the declaration part of the architecture for the generated test design + * file. + */ +void print_test_architecture_prologue(FILE *infile, unsigned int iw, unsigned int fw, unsigned int step) +{ + long long int i; + unsigned long long int nsteps = calculate_samples(iw, fw, step); + char c = 'X'; + if (enable_unsigned == 1) + { + c = 'u'; + } + else if (enable_signed == 1) + { + c = 's'; + } + + pfprintf(infile, 0, "architecture fsmd of testrounding is\n"); + pfprintf(infile, 2, "type state_type is (S_ENTRY, S_EXIT,\n"); + + for (i = 0; i < nsteps; i++) + { + pfprintf(infile, 4, "S_%08d_1,", i); + fprintf(infile, " S_%08d_2", i); + fprintf(infile, ", S_%08d_3", i); + if (enable_signed == 1) + { + fprintf(infile, ", S_%08d_4", i); + } + if (i < nsteps-1) + { + fprintf(infile, ","); + } + fprintf(infile, "\n"); + } + pfprintf(infile, 2, ");\n"); + pfprintf(infile, 2, "signal current_state, next_state: state_type;\n"); + pfprintf(infile, 2, "signal a_reg, a_next : %cfixed(%d downto -%d);\n", c, iw-1, fw); + pfprintf(infile, 2, "signal y_ceil_reg, y_ceil_next : %cfixed(%d downto -%d);\n", c, iw-1, fw); + pfprintf(infile, 2, "signal y_fix_reg, y_fix_next : %cfixed(%d downto -%d);\n", c, iw-1, fw); + pfprintf(infile, 2, "signal y_floor_reg, y_floor_next : %cfixed(%d downto -%d);\n", c, iw-1, fw); + pfprintf(infile, 2, "signal y_round_reg, y_round_next : %cfixed(%d downto -%d);\n", c, iw-1, fw); + pfprintf(infile, 2, "signal y_nearest_reg, y_nearest_next : %cfixed(%d downto -%d);\n", c, iw-1, fw); + pfprintf(infile, 2, "signal y_convergent_reg, y_convergent_next : %cfixed(%d downto -%d);\n", c, iw-1, fw); + pfprintf(infile, 2, "signal ok_reg, ok_next : sfixed(%d downto -%d);\n", iw-1, fw); + + pfprintf(infile, 0, "begin\n"); +} + +/* print_test_architecture_csl: + * Prints the current state logic process of the architecture for the generated + * test design file. + */ +void print_test_architecture_csl(FILE *infile) +{ + pfprintf(infile, 2, "-- current state logic\n"); + pfprintf(infile, 2, "process (clk, reset)\n"); + pfprintf(infile, 4, "begin\n"); + pfprintf(infile, 6, "if (reset = '1') then\n"); + pfprintf(infile, 6, "current_state <= S_ENTRY;\n"); + pfprintf(infile, 6, "a_reg <= (others => '0');\n"); + pfprintf(infile, 6, "y_ceil_reg <= (others => '0');\n"); + pfprintf(infile, 6, "y_fix_reg <= (others => '0');\n"); + pfprintf(infile, 6, "y_floor_reg <= (others => '0');\n"); + pfprintf(infile, 6, "y_round_reg <= (others => '0');\n"); + pfprintf(infile, 6, "y_nearest_reg <= (others => '0');\n"); + pfprintf(infile, 6, "y_convergent_reg <= (others => '0');\n"); + pfprintf(infile, 6, "ok_reg <= (others => '0');\n"); + pfprintf(infile, 4, "elsif (clk = '1' and clk'EVENT) then\n"); + pfprintf(infile, 6, "current_state <= next_state;\n"); + pfprintf(infile, 6, "a_reg <= a_next;\n"); + pfprintf(infile, 6, "y_ceil_reg <= y_ceil_next;\n"); + pfprintf(infile, 6, "y_fix_reg <= y_fix_next;\n"); + pfprintf(infile, 6, "y_floor_reg <= y_floor_next;\n"); + pfprintf(infile, 6, "y_round_reg <= y_round_next;\n"); + pfprintf(infile, 6, "y_nearest_reg <= y_nearest_next;\n"); + pfprintf(infile, 6, "y_convergent_reg <= y_convergent_next;\n"); + pfprintf(infile, 6, "ok_reg <= ok_next;\n"); + pfprintf(infile, 4, "end if;\n"); + pfprintf(infile, 2, "end process;\n\n"); +} + +/* print_test_architecture_nsol_prologue: + * Prints the next state and output logic process prologue of the architecture + * for the generated test design file. + */ +void print_test_architecture_nsol_prologue(FILE *infile) +{ + pfprintf(infile, 2, "-- next state and output logic\n"); + pfprintf(infile, 2, "process (current_state, start,\n"); + pfprintf(infile, 4, "ok_reg,\n"); + pfprintf(infile, 4, "a_reg, a_next,\n"); + pfprintf(infile, 4, "y_ceil_reg, y_ceil_next,\n"); + pfprintf(infile, 4, "y_fix_reg, y_fix_next,\n"); + pfprintf(infile, 4, "y_floor_reg, y_floor_next,\n"); + pfprintf(infile, 4, "y_round_reg, y_round_next,\n"); + pfprintf(infile, 4, "y_nearest_reg, y_nearest_next,\n"); + pfprintf(infile, 4, "y_convergent_reg, y_convergent_next\n"); + pfprintf(infile, 2, ")\n"); + pfprintf(infile, 2, "begin\n"); + pfprintf(infile, 4, "a_next <= a_reg;\n"); + pfprintf(infile, 4, "y_ceil_next <= y_ceil_reg;\n"); + pfprintf(infile, 4, "y_fix_next <= y_fix_reg;\n"); + pfprintf(infile, 4, "y_floor_next <= y_floor_reg;\n"); + pfprintf(infile, 4, "y_round_next <= y_round_reg;\n"); + pfprintf(infile, 4, "y_nearest_next <= y_nearest_reg;\n"); + pfprintf(infile, 4, "y_convergent_next <= y_convergent_reg;\n"); + pfprintf(infile, 4, "ok_next <= ok_reg;\n"); +} + +/* print_test_architecture_nsol_csdec: + * Prints the current state decoding part. It resides in the next state and + * output logic process of the architecture for the generated test design file. + */ +void print_test_architecture_nsol_csdec(FILE *infile, unsigned int iw, unsigned int fw, unsigned int step) +{ + long long int i; + int k; + unsigned long long int nsteps = calculate_samples(iw, fw, step); + double val = 0.0; + char c = 'X'; + if (enable_unsigned == 1) + { + c = 'u'; + } + else if (enable_signed == 1) + { + c = 's'; + } + + pfprintf(infile, 4, "case current_state is\n"); + pfprintf(infile, 6, "when S_ENTRY =>\n"); + pfprintf(infile, 8, "if (start = '1') then\n"); + pfprintf(infile, 10, "next_state <= S_00000001_1;\n"); + pfprintf(infile, 8, "else\n"); + pfprintf(infile, 10, "next_state <= S_ENTRY;\n"); + pfprintf(infile, 8, "end if;\n"); + + if (enable_unsigned == 1) + { + val = 0.0; + } + else if (enable_signed == 1) + { + val = - 1.0 * ipowul(2, iw-1); + } + for (i = 0; i < nsteps; i++) + { + pfprintf(infile, 6, "when S_%08d_1 =>\n", i); + pfprintf(infile, 8, "a_next <= to_%cfixed(%lf, %d, -%d);\n", c, val, iw-1, fw); + val += 1.0/(float)ipowul(2, fw); + pfprintf(infile, 8, "next_state <= S_%08d_2;\n", i); + // + if (enable_signed == 1) + { + pfprintf(infile, 6, "when S_%08d_2 =>\n", i); + if (val < 0.0) + { + pfprintf(infile, 8, "a_next <= resize(-a_reg, a_next'high, a_next'low);\n"); + } + pfprintf(infile, 8, "next_state <= S_%08d_3;\n", i); + k++; + } + // + if (enable_unsigned == 1) + { + pfprintf(infile, 6, "when S_%08d_2 =>\n", i); + } + else if (enable_signed == 1) + { + pfprintf(infile, 6, "when S_%08d_3 =>\n", i); + } + pfprintf(infile, 8, "y_ceil_next <= ceil(a_reg);\n"); + pfprintf(infile, 8, "y_fix_next <= fix(a_reg);\n"); + pfprintf(infile, 8, "y_floor_next <= floor(a_reg);\n"); + pfprintf(infile, 8, "y_round_next <= round(a_reg);\n"); + pfprintf(infile, 8, "y_nearest_next <= nearest(a_reg);\n"); + pfprintf(infile, 8, "y_convergent_next <= convergent(a_reg);\n"); + if (enable_unsigned == 1) + { + pfprintf(infile, 8, "next_state <= S_%08d_3;\n", i); + } + else if (enable_signed == 1) + { + pfprintf(infile, 8, "next_state <= S_%08d_4;\n", i); + } + // + if (enable_unsigned == 1) + { + pfprintf(infile, 6, "when S_%08d_3 =>\n", i); + } + else if (enable_signed == 1) + { + pfprintf(infile, 6, "when S_%08d_4 =>\n", i); + } + pfprintf(infile, 8, "assert false report \"a_reg = \" & to_bstring(a_reg) severity note;\n"); + pfprintf(infile, 8, "assert false report \"y_ceil_reg = \" & to_bstring(y_ceil_reg) severity note;\n"); + pfprintf(infile, 8, "assert false report \"y_fix_reg = \" & to_bstring(y_fix_reg) severity note;\n"); + pfprintf(infile, 8, "assert false report \"y_floor_reg = \" & to_bstring(y_floor_reg) severity note;\n"); + pfprintf(infile, 8, "assert false report \"y_round_reg = \" & to_bstring(y_round_reg) severity note;\n"); + pfprintf(infile, 8, "assert false report \"y_nearest_reg = \" & to_bstring(y_nearest_reg) severity note;\n"); + pfprintf(infile, 8, "assert false report \"y_convergent_reg = \" & to_bstring(y_convergent_reg) severity note;\n"); + if (i == nsteps-1) + { + pfprintf(infile, 8, "next_state <= S_EXIT;\n"); + } + else + { + pfprintf(infile, 8, "next_state <= S_%08d_1;\n", i+1); + } + } + pfprintf(infile, 6, "when S_EXIT =>\n"); + pfprintf(infile, 8, "ok_next <= to_sfixed(%lf, %d, %d);\n", 1.0, iw-1, -fw); + pfprintf(infile, 8, "assert false report \"DONE!\" severity note;\n"); + pfprintf(infile, 8, "next_state <= S_ENTRY;\n"); + pfprintf(infile, 4, "end case;\n"); +} + +/* print_test_architecture_epilogue: + * Prints the epilogue of the architecture for the generated test design file. + */ +void print_test_architecture_epilogue(FILE *infile) +{ + pfprintf(infile, 2, "end process;\n\n"); + pfprintf(infile, 2, "ok <= ok_reg;\n\n"); + pfprintf(infile, 0, "end fsmd;\n"); +} + +/* print_test_design: + * Prints the generated test design file. + */ +void print_test_design(FILE *infile, unsigned int iw, unsigned int fw, unsigned step) +{ + print_test_prologue(infile); + print_test_entity(infile, iw, fw); + print_test_architecture_prologue(infile, iw, fw, step); + print_test_architecture_csl(infile); + print_test_architecture_nsol_prologue(infile); + print_test_architecture_nsol_csdec(infile, iw, fw, step); + print_test_architecture_epilogue(infile); +} + +/* print_usage: + * Print usage instructions for the "gentestround" program. + */ +static void print_usage() +{ + printf("\n"); + printf("* Usage:\n"); + printf("* gentestround [options]\n"); + printf("* \n"); + printf("* Options:\n"); + printf("* \n"); + printf("* -h:\n"); + printf("* Print this help.\n"); + printf("* -d:\n"); + printf("* Enable debug/diagnostic output.\n"); + printf("* -iw :\n"); + printf("* Set the integral part width of the fixed-point numbers. Default: 4.\n"); + printf("* -fw :\n"); + printf("* Set the fractional part width of the fixed-point numbers. Default: 4.\n"); + printf("* -step :\n"); + printf("* Set the step value indicating the difference between two consecutive\n"); + printf("* samples. Default: 0.25\n"); + printf("* -signed:\n"); + printf("* Generate test design for sfixed vectors.\n"); + printf("* -unsigned:\n"); + printf("* Generate test design for ufixed vectors (default).\n"); + printf("* \n"); + printf("* For further information, please refer to the website:\n"); + printf("* http://www.nkavvadias.com\n"); +} + +/* main: + * Program entry. + */ +int main(int argc, char *argv[]) +{ + int i; + FILE *file_o; + + // Read input arguments + for (i=1; i < argc; i++) + { + if (strcmp("-h", argv[i]) == 0) + { + print_usage(); + exit(1); + } + else if (strcmp("-d", argv[i]) == 0) + { + enable_debug = 1; + } + else if (strcmp("-unsigned", argv[i]) == 0) + { + enable_unsigned = 1; + enable_signed = 0; + } + else if (strcmp("-signed", argv[i]) == 0) + { + enable_unsigned = 0; + enable_signed = 1; + } + else if (strcmp("-iw",argv[i]) == 0) + { + if ((i+1) < argc) + { + i++; + iw_val = atoi(argv[i]); + } + } + else if (strcmp("-fw",argv[i]) == 0) + { + if ((i+1) < argc) + { + i++; + fw_val = atoi(argv[i]); + } + } + else if (strcmp("-step",argv[i]) == 0) + { + if ((i+1) < argc) + { + i++; + step_val = atof(argv[i]); + } + } + else + { + if (argv[i][0] != '-') + { + file_o = fopen(argv[i], "wb"); + if (file_o == NULL) + { + fprintf(stderr,"Error: Can't write %s!\n", argv[i]); + return -1; + } + } + } + } + + if (iw_val <= 0) + { + fprintf(stderr, "Error: IW must be greater than zero.\n"); + exit(1); + } + if (fw_val < 0) + { + fprintf(stderr, "Error: FW must be greater than or equal to zero.\n"); + exit(1); + } + + /* Generate the test design. */ + print_test_design(file_o, iw_val, fw_val, step_val); + fclose(file_o); + + return 0; +}
trunk/sw/gentestround.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/sw/Makefile =================================================================== --- trunk/sw/Makefile (nonexistent) +++ trunk/sw/Makefile (revision 2) @@ -0,0 +1,14 @@ +CC = gcc +CFLAGS = -Wall -O2 +EXE = .exe + +all: gentestround + +gentestround: gentestround.o + $(CC) gentestround.o -o gentestround + +tidy: + rm -f *.o + +clean: + rm -f *.o gentestround$(EXE)
trunk/sw/Makefile Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.