+
diff --git a/common_components/common_delay.vhd b/common_components/common_delay.vhd
index 523cbf99..1f6b1383 100644
--- a/common_components/common_delay.vhd
+++ b/common_components/common_delay.vhd
@@ -25,7 +25,11 @@
library ieee;
use IEEE.STD_LOGIC_1164.all;
-
+use IEEE.numeric_std.all;
+library common_pkg_lib;
+use common_pkg_lib.common_pkg.all;
+library casper_ram_lib;
+use casper_ram_lib.common_ram_pkg.all;
entity common_delay is
generic(
g_dat_w : NATURAL := 8; --! need g_dat_w to be able to use (others=>'') assignments for two dimensional unconstraint vector arrays
@@ -45,15 +49,23 @@ architecture rtl of common_delay is
-- delay, in this way the t_dly_arr type can support all g_depth >= 0
type t_dly_arr is array (0 to g_depth) of STD_LOGIC_VECTOR(g_dat_w - 1 downto 0);
- signal shift_reg : t_dly_arr := (others => (others => '0'));
-
+
+ type t_mem_arr is array (0 to (((2**ceil_log2(g_depth))-1))) of STD_LOGIC_VECTOR(g_dat_w - 1 downto 0);
+ --signal shift_reg : t_dly_arr := (others => (others => '0'));
begin
- shift_reg(0) <= in_dat;
-
- out_dat <= shift_reg(g_depth);
-
- gen_reg : if g_depth > 0 generate
+ gen_zero : if g_depth = 0 generate
+ signal shift_reg : t_dly_arr := (others => (others => '0'));
+ begin
+ shift_reg(0) <= in_dat;
+ out_dat <= shift_reg(g_depth);
+ end generate;
+ gen_regSR : if g_depth > 0 and g_depth<128 generate -- Use a shift register implementation
+ signal shift_reg : t_dly_arr := (others => (others => '0'));
+ begin
+
+ shift_reg(0) <= in_dat;
+ out_dat <= shift_reg(g_depth);
p_clk : process(clk)
begin
if rising_edge(clk) then
@@ -63,5 +75,89 @@ begin
end if;
end process;
end generate;
+ gen_regMEM : if g_depth >= 128 generate -- Use a Memory implementation
+ signal mem_addr_wr : unsigned(ceil_log2(g_depth-1)-1 downto 0) := to_unsigned(g_depth-5,ceil_log2(g_depth));
+ signal mem_addr_rd : unsigned(ceil_log2(g_depth-1)-1 downto 0) := to_unsigned(0,ceil_log2(g_depth));
+ signal out_datmem : STD_LOGIC_VECTOR(g_dat_w - 1 downto 0) := (others => '0'); --! Output value
+ signal out_dat_p : STD_LOGIC_VECTOR(g_dat_w - 1 downto 0) := (others => '0'); --! Output value
+ signal in_dat_d1 : STD_LOGIC_VECTOR(g_dat_w - 1 downto 0) := (others => '0'); --! Output value
+ signal in_dat_d2 : STD_LOGIC_VECTOR(g_dat_w - 1 downto 0) := (others => '0'); --! Output value
+ attribute DONT_TOUCH : string;
+ attribute KEEP : string;
+ attribute KEEP of out_dat_p : signal is "TRUE"; -- try to prevent this signal from being absorbed into the block
+ attribute DONT_TOUCH of out_dat_p : signal is "TRUE"; -- try to prevent this signal from being absorbed into the block
+
+
+ begin
+ --out_dat <= out_datmem;
+ --shift_reg(0) <= in_dat;
+ --out_shift <= shift_reg(g_depth);
+ --assert out_datmem = shift_reg(g_depth-2) report "non matching data" severity failure;
+ --p_clk : process(clk)
+ --begin
+ -- if rising_edge(clk) then
+ -- if in_val = '1' then
+ -- out_datmem <= memory(to_integer(mem_addr_rd));
+ -- memory(to_integer(mem_addr_wr)) <= in_dat;
+ -- --shift_reg(1 to g_depth) <= shift_reg(0 to g_depth - 1);
+ -- end if;
+ -- end if;
+ --end process;
+ RamInst : entity casper_ram_lib.tech_memory_ram_cr_cw
+ generic map(
+ g_adr_w => ceil_log2(g_depth-1),
+ g_dat_w => g_dat_w,
+ g_nof_words => 2**ceil_log2(g_depth),
+ g_rd_latency => 1
+ --g_init_file => g_init_file,
+ --g_ram_primitive => g_ram_primitive
+ )
+ port map(
+ data => in_dat_d2,
+ rdaddress => std_logic_vector(mem_addr_rd),
+ rdclock => clk,
+ rdclocken => in_val,
+ wraddress => std_logic_vector(mem_addr_wr),
+ wrclock => clk,
+ wrclocken => in_val,
+ wren => in_val,
+ q => out_datmem
+ );
+
+ --RamInst : entity casper_ram_lib.common_ram_r_w
+ -- generic map(
+ -- g_ram => c_mem_settings,
+ -- --g_init_file => g_init_file,
+ -- g_true_dual_port => false
+ -- --g_ram_primitive => g_ram_primitive
+ -- )
+ -- port map(
+ -- clk => clk,
+ -- clken => in_val,
+ -- wr_en => in_val,
+ -- wr_adr => std_logic_vector(mem_addr_wr),
+ -- wr_dat => in_dat,
+ -- rd_en => in_val,
+ -- rd_adr => std_logic_vector(mem_addr_rd),
+ -- rd_dat => out_datmem,
+ -- rd_val => open
+ -- );
+
+ reg_data : process (clk)
+ begin
+ if rising_edge(clk) then
+ if in_val='1' then
+ in_dat_d1 <= in_dat;
+ in_dat_d2 <= in_dat_d1;
+ out_dat_p <= out_datmem;
+ out_dat <= out_dat_p;
+ mem_addr_wr <= mem_addr_wr + 1;
+ mem_addr_rd <= mem_addr_rd + 1;
+ end if;
+ end if;
+ end process;
+
+
+ end generate;
end rtl;
diff --git a/common_pkg/common_pkg.vhd b/common_pkg/common_pkg.vhd
index b997c09d..a085d51e 100644
--- a/common_pkg/common_pkg.vhd
+++ b/common_pkg/common_pkg.vhd
@@ -1,2612 +1,2705 @@
--------------------------------------------------------------------------------
---
--- Copyright 2020
--- ASTRON (Netherlands Institute for Radio Astronomy)
--- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- http://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an "AS IS" BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
---
--------------------------------------------------------------------------------
-
--- Author:
--- . Eric Kooistra
--- Purpose:
--- . Collection of commonly used base funtions
--- Interface:
--- . [n/a]
--- Description:
--- . This is a package containing generic constants and functions.
--- . More information can be found in the comments near the code.
-
-LIBRARY IEEE;
-USE IEEE.STD_LOGIC_1164.ALL;
-USE IEEE.NUMERIC_STD.ALL;
-USE IEEE.MATH_REAL.ALL;
-
-PACKAGE common_pkg IS
-
- -- CONSTANT DECLARATIONS ----------------------------------------------------
-
- -- some integers
- CONSTANT c_0 : NATURAL := 0;
- CONSTANT c_zero : NATURAL := 0;
- CONSTANT c_1 : NATURAL := 1;
- CONSTANT c_one : NATURAL := 1;
- CONSTANT c_2 : NATURAL := 2;
- CONSTANT c_4 : NATURAL := 4;
- CONSTANT c_quad : NATURAL := 4;
- CONSTANT c_8 : NATURAL := 8;
- CONSTANT c_16 : NATURAL := 16;
- CONSTANT c_32 : NATURAL := 32;
- CONSTANT c_64 : NATURAL := 64;
- CONSTANT c_128 : NATURAL := 128;
- CONSTANT c_256 : NATURAL := 256;
-
- -- widths and sizes
- CONSTANT c_halfword_sz : NATURAL := 2;
- CONSTANT c_word_sz : NATURAL := 4;
- CONSTANT c_longword_sz : NATURAL := 8;
- CONSTANT c_nibble_w : NATURAL := 4;
- CONSTANT c_byte_w : NATURAL := 8;
- CONSTANT c_octet_w : NATURAL := 8;
- CONSTANT c_halfword_w : NATURAL := c_byte_w * c_halfword_sz;
- CONSTANT c_word_w : NATURAL := c_byte_w * c_word_sz;
- CONSTANT c_integer_w : NATURAL := 32; -- unfortunately VHDL integer type is limited to 32 bit values
- CONSTANT c_natural_w : NATURAL := c_integer_w - 1; -- unfortunately VHDL natural type is limited to 31 bit values (0 and the positive subset of the VHDL integer type0
- CONSTANT c_longword_w : NATURAL := c_byte_w * c_longword_sz;
-
- -- logic
- CONSTANT c_sl0 : STD_LOGIC := '0';
- CONSTANT c_sl1 : STD_LOGIC := '1';
- CONSTANT c_unsigned_0 : UNSIGNED(0 DOWNTO 0) := TO_UNSIGNED(0, 1);
- CONSTANT c_unsigned_1 : UNSIGNED(0 DOWNTO 0) := TO_UNSIGNED(1, 1);
- CONSTANT c_signed_0 : SIGNED(1 DOWNTO 0) := TO_SIGNED(0, 2);
- CONSTANT c_signed_1 : SIGNED(1 DOWNTO 0) := TO_SIGNED(1, 2);
- CONSTANT c_slv0 : STD_LOGIC_VECTOR(255 DOWNTO 0) := (OTHERS => '0');
- CONSTANT c_slv1 : STD_LOGIC_VECTOR(255 DOWNTO 0) := (OTHERS => '1');
- CONSTANT c_word_01 : STD_LOGIC_VECTOR(31 DOWNTO 0) := "01010101010101010101010101010101";
- CONSTANT c_word_10 : STD_LOGIC_VECTOR(31 DOWNTO 0) := "10101010101010101010101010101010";
- CONSTANT c_slv01 : STD_LOGIC_VECTOR(255 DOWNTO 0) := c_word_01 & c_word_01 & c_word_01 & c_word_01 & c_word_01 & c_word_01 & c_word_01 & c_word_01;
- CONSTANT c_slv10 : STD_LOGIC_VECTOR(255 DOWNTO 0) := c_word_10 & c_word_10 & c_word_10 & c_word_10 & c_word_10 & c_word_10 & c_word_10 & c_word_10;
-
- -- math
- CONSTANT c_nof_complex : NATURAL := 2; -- Real and imaginary part of complex number
- CONSTANT c_sign_w : NATURAL := 1; -- Sign bit, can be used to skip one of the double sign bits of a product
- CONSTANT c_sum_of_prod_w : NATURAL := 1; -- Bit growth for sum of 2 products, can be used in case complex multiply has normalized real and imag inputs instead of normalized amplitude inputs
-
- -- FF, block RAM, FIFO
- CONSTANT c_meta_delay_len : NATURAL := 3; -- default nof flipflops (FF) in meta stability recovery delay line (e.g. for clock domain crossing)
- CONSTANT c_meta_fifo_depth : NATURAL := 16; -- default use 16 word deep FIFO to cross clock domain, typically > 2*c_meta_delay_len or >~ 8 is enough
-
- CONSTANT c_bram_m9k_nof_bits : NATURAL := 1024 * 9; -- size of 1 Altera M9K block RAM in bits
- CONSTANT c_bram_m9k_max_w : NATURAL := 36; -- maximum width of 1 Altera M9K block RAM, so the size is then 256 words of 36 bits
- CONSTANT c_bram_m9k_fifo_depth : NATURAL := c_bram_m9k_nof_bits / c_bram_m9k_max_w; -- using a smaller FIFO depth than this leaves part of the RAM unused
-
- CONSTANT c_fifo_afull_margin : NATURAL := 4; -- default or minimal FIFO almost full margin
-
- -- DSP
- CONSTANT c_dsp_mult_w : NATURAL := 18; -- Width of the embedded multipliers in Stratix IV
-
- -- TYPE DECLARATIONS --------------------------------------------------------
- TYPE t_boolean_arr IS ARRAY (INTEGER RANGE <>) OF BOOLEAN; -- INTEGER left index starts default at -2**31
- TYPE t_integer_arr IS ARRAY (INTEGER RANGE <>) OF INTEGER; -- INTEGER left index starts default at -2**31
- TYPE t_natural_arr IS ARRAY (INTEGER RANGE <>) OF NATURAL; -- INTEGER left index starts default at -2**31
- TYPE t_nat_boolean_arr IS ARRAY (NATURAL RANGE <>) OF BOOLEAN; -- NATURAL left index starts default at 0
- TYPE t_nat_integer_arr IS ARRAY (NATURAL RANGE <>) OF INTEGER; -- NATURAL left index starts default at 0
- TYPE t_nat_natural_arr IS ARRAY (NATURAL RANGE <>) OF NATURAL; -- NATURAL left index starts default at 0
- TYPE t_sl_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC;
- TYPE t_slv_1_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(0 DOWNTO 0);
- TYPE t_slv_2_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(1 DOWNTO 0);
- TYPE t_slv_4_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(3 DOWNTO 0);
- TYPE t_slv_8_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
- TYPE t_slv_12_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(11 DOWNTO 0);
- TYPE t_slv_16_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(15 DOWNTO 0);
- TYPE t_slv_18_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(17 DOWNTO 0);
- TYPE t_slv_24_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(23 DOWNTO 0);
- TYPE t_slv_32_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(31 DOWNTO 0);
- TYPE t_slv_44_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(43 DOWNTO 0);
- TYPE t_slv_48_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(47 DOWNTO 0);
- TYPE t_slv_64_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(63 DOWNTO 0);
- TYPE t_slv_128_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(127 DOWNTO 0);
- TYPE t_slv_256_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(255 DOWNTO 0);
- TYPE t_slv_512_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(511 DOWNTO 0);
- TYPE t_slv_1024_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(1023 DOWNTO 0);
-
- CONSTANT c_boolean_arr : t_boolean_arr := (TRUE, FALSE); -- array all possible values that can be iterated over
- CONSTANT c_nat_boolean_arr : t_nat_boolean_arr := (TRUE, FALSE); -- array all possible values that can be iterated over
-
- TYPE t_integer_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF INTEGER;
- TYPE t_boolean_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF BOOLEAN;
- TYPE t_sl_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF STD_LOGIC;
- TYPE t_slv_8_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
- TYPE t_slv_16_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF STD_LOGIC_VECTOR(15 DOWNTO 0);
- TYPE t_slv_32_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF STD_LOGIC_VECTOR(31 DOWNTO 0);
- TYPE t_slv_64_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF STD_LOGIC_VECTOR(63 DOWNTO 0);
-
- TYPE t_natural_2arr_2 IS ARRAY (INTEGER RANGE <>) OF t_natural_arr(1 DOWNTO 0);
-
- -- STRUCTURE DECLARATIONS ---------------------------------------------------
-
- -- Clock and Reset
- --
- -- . rst = Reset. Can be used asynchronously to take effect immediately
- -- when used before the clk'EVENT section. May also be used as
- -- synchronous reset using it as first condition in the clk'EVENT
- -- section. As synchronous reset it requires clock activity to take
- -- effect. A synchronous rst may or may not depend on clken,
- -- however typically rst should take priority over clken.
- -- . clk = Clock. Used in clk'EVENT line via rising_edge(clk) or sometimes
- -- as falling_edge(clk).
- -- . clken = Clock Enable. Used for the whole clk'EVENT section.
- TYPE t_sys_rce IS RECORD
- rst : STD_LOGIC;
- clk : STD_LOGIC;
- clken : STD_LOGIC; -- := '1';
- END RECORD;
-
- TYPE t_sys_ce IS RECORD
- clk : STD_LOGIC;
- clken : STD_LOGIC; -- := '1';
- END RECORD;
-
- -- FUNCTION DECLARATIONS ----------------------------------------------------
-
- -- All functions assume [high downto low] input ranges
-
- FUNCTION pow2(n : NATURAL) RETURN NATURAL; -- = 2**n
- FUNCTION ceil_pow2(n : INTEGER) RETURN NATURAL; -- = 2**n, returns 1 for n<0
-
- FUNCTION true_log2(n : NATURAL) RETURN NATURAL; -- true_log2(n) = log2(n)
- FUNCTION ceil_log2(n : NATURAL) RETURN NATURAL; -- ceil_log2(n) = log2(n), but force ceil_log2(1) = 1
-
- FUNCTION floor_log10(n : NATURAL) RETURN NATURAL;
-
- FUNCTION is_pow2(n : NATURAL) RETURN BOOLEAN; -- return TRUE when n is a power of 2, so 0, 1, 2, 4, 8, 16, ...
- FUNCTION true_log_pow2(n : NATURAL) RETURN NATURAL; -- 2**true_log2(n), return power of 2 that is >= n
-
- FUNCTION ratio(n, d : NATURAL) RETURN NATURAL; -- return n/d when n MOD d = 0 else return 0, so ratio * d = n only when integer ratio > 0
- FUNCTION ratio2(n, m : NATURAL) RETURN NATURAL; -- return integer ratio of n/m or m/n, whichever is the largest
-
- FUNCTION ceil_div(n, d : NATURAL) RETURN NATURAL; -- ceil_div = n/d + (n MOD d)/=0
- FUNCTION ceil_value(n, d : NATURAL) RETURN NATURAL; -- ceil_value = ceil_div(n, d) * d
- FUNCTION floor_value(n, d : NATURAL) RETURN NATURAL; -- floor_value = (n/d) * d
- FUNCTION ceil_div(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED;
- FUNCTION ceil_value(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED;
- FUNCTION floor_value(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED;
-
- FUNCTION slv(n : IN STD_LOGIC) RETURN STD_LOGIC_VECTOR; -- standard logic to 1 element standard logic vector
- FUNCTION sl(n : IN STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- 1 element standard logic vector to standard logic
-
- FUNCTION to_natural_arr(n : t_integer_arr; to_zero : BOOLEAN) RETURN t_natural_arr; -- if to_zero=TRUE then negative numbers are forced to zero, otherwise they will give a compile range error
- FUNCTION to_natural_arr(n : t_nat_natural_arr) RETURN t_natural_arr;
- FUNCTION to_integer_arr(n : t_natural_arr) RETURN t_integer_arr;
- FUNCTION to_integer_arr(n : t_nat_natural_arr) RETURN t_integer_arr;
- FUNCTION to_slv_32_arr(n : t_integer_arr) RETURN t_slv_32_arr;
- FUNCTION to_slv_32_arr(n : t_natural_arr) RETURN t_slv_32_arr;
-
- FUNCTION vector_tree(slv : STD_LOGIC_VECTOR; operation : STRING) RETURN STD_LOGIC; -- Core operation tree function for vector "AND", "OR", "XOR"
- FUNCTION vector_and(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- '1' when all slv bits are '1' else '0'
- FUNCTION vector_or(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- '0' when all slv bits are '0' else '1'
- FUNCTION vector_xor(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- '1' when the slv has an odd number of '1' bits else '0'
- FUNCTION vector_one_hot(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- Returns slv when it contains one hot bit, else returns 0.
-
- FUNCTION andv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- alias of vector_and
- FUNCTION orv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- alias of vector_or
- FUNCTION xorv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- alias of vector_xor
-
- FUNCTION matrix_and(mat : t_sl_matrix; wi, wj : NATURAL) RETURN STD_LOGIC; -- '1' when all matrix bits are '1' else '0'
- FUNCTION matrix_or(mat : t_sl_matrix; wi, wj : NATURAL) RETURN STD_LOGIC; -- '0' when all matrix bits are '0' else '1'
-
- FUNCTION smallest(n, m : INTEGER) RETURN INTEGER;
- FUNCTION smallest(n, m, l : INTEGER) RETURN INTEGER;
- FUNCTION smallest(n : t_natural_arr) RETURN NATURAL;
-
- FUNCTION largest(n, m : INTEGER) RETURN INTEGER;
- FUNCTION largest(n : t_natural_arr) RETURN NATURAL;
-
- FUNCTION func_sum(n : t_natural_arr) RETURN NATURAL; -- sum of all elements in array
- FUNCTION func_sum(n : t_nat_natural_arr) RETURN NATURAL;
- FUNCTION func_product(n : t_natural_arr) RETURN NATURAL; -- product of all elements in array
- FUNCTION func_product(n : t_nat_natural_arr) RETURN NATURAL;
-
- FUNCTION "+"(L, R : t_natural_arr) RETURN t_natural_arr; -- element wise sum
- FUNCTION "+"(L : t_natural_arr; R : INTEGER) RETURN t_natural_arr; -- element wise sum
- FUNCTION "+"(L : INTEGER; R : t_natural_arr) RETURN t_natural_arr; -- element wise sum
-
- FUNCTION "-"(L, R : t_natural_arr) RETURN t_natural_arr; -- element wise subtract
- FUNCTION "-"(L, R : t_natural_arr) RETURN t_integer_arr; -- element wise subtract, support negative result
- FUNCTION "-"(L : t_natural_arr; R : INTEGER) RETURN t_natural_arr; -- element wise subtract
- FUNCTION "-"(L : INTEGER; R : t_natural_arr) RETURN t_natural_arr; -- element wise subtract
-
- FUNCTION "*"(L, R : t_natural_arr) RETURN t_natural_arr; -- element wise product
- FUNCTION "*"(L : t_natural_arr; R : NATURAL) RETURN t_natural_arr; -- element wise product
- FUNCTION "*"(L : NATURAL; R : t_natural_arr) RETURN t_natural_arr; -- element wise product
-
- FUNCTION "/"(L, R : t_natural_arr) RETURN t_natural_arr; -- element wise division
- FUNCTION "/"(L : t_natural_arr; R : POSITIVE) RETURN t_natural_arr; -- element wise division
- FUNCTION "/"(L : NATURAL; R : t_natural_arr) RETURN t_natural_arr; -- element wise division
-
- FUNCTION is_true(a : STD_LOGIC) RETURN BOOLEAN;
- FUNCTION is_true(a : STD_LOGIC) RETURN NATURAL;
- FUNCTION is_true(a : BOOLEAN) RETURN STD_LOGIC;
- FUNCTION is_true(a : BOOLEAN) RETURN NATURAL;
- FUNCTION is_true(a : INTEGER) RETURN BOOLEAN; -- also covers NATURAL because it is a subtype of INTEGER
- FUNCTION is_true(a : INTEGER) RETURN STD_LOGIC; -- also covers NATURAL because it is a subtype of INTEGER
-
- FUNCTION is_all(vec : STD_LOGIC_VECTOR; val : STD_LOGIC) return BOOLEAN;
-
- FUNCTION sel_a_b(sel, a, b : BOOLEAN) RETURN BOOLEAN;
- FUNCTION sel_a_b(sel, a, b : INTEGER) RETURN INTEGER;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : INTEGER) RETURN INTEGER;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : REAL) RETURN REAL;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : STD_LOGIC) RETURN STD_LOGIC;
- FUNCTION sel_a_b(sel : INTEGER; a, b : STD_LOGIC) RETURN STD_LOGIC;
- FUNCTION sel_a_b(sel : INTEGER; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : SIGNED) RETURN SIGNED;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : UNSIGNED) RETURN UNSIGNED;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_integer_arr) RETURN t_integer_arr;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_natural_arr) RETURN t_natural_arr;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_nat_integer_arr) RETURN t_nat_integer_arr;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_nat_natural_arr) RETURN t_nat_natural_arr;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : STRING) RETURN STRING;
- FUNCTION sel_a_b(sel : INTEGER; a, b : STRING) RETURN STRING;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : TIME) RETURN TIME;
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : SEVERITY_LEVEL) RETURN SEVERITY_LEVEL;
-
- -- sel_n() index sel = 0, 1, 2, ... will return a, b, c, ...
- FUNCTION sel_n(sel : NATURAL; a, b, c : BOOLEAN) RETURN BOOLEAN; -- 3
- FUNCTION sel_n(sel : NATURAL; a, b, c, d : BOOLEAN) RETURN BOOLEAN; -- 4
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : BOOLEAN) RETURN BOOLEAN; -- 5
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : BOOLEAN) RETURN BOOLEAN; -- 6
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : BOOLEAN) RETURN BOOLEAN; -- 7
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : BOOLEAN) RETURN BOOLEAN; -- 8
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : BOOLEAN) RETURN BOOLEAN; -- 9
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : BOOLEAN) RETURN BOOLEAN; -- 10
-
- FUNCTION sel_n(sel : NATURAL; a, b, c : INTEGER) RETURN INTEGER; -- 3
- FUNCTION sel_n(sel : NATURAL; a, b, c, d : INTEGER) RETURN INTEGER; -- 4
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : INTEGER) RETURN INTEGER; -- 5
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : INTEGER) RETURN INTEGER; -- 6
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : INTEGER) RETURN INTEGER; -- 7
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : INTEGER) RETURN INTEGER; -- 8
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : INTEGER) RETURN INTEGER; -- 9
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : INTEGER) RETURN INTEGER; -- 10
-
- FUNCTION sel_n(sel : NATURAL; a, b : STRING) RETURN STRING; -- 2
- FUNCTION sel_n(sel : NATURAL; a, b, c : STRING) RETURN STRING; -- 3
- FUNCTION sel_n(sel : NATURAL; a, b, c, d : STRING) RETURN STRING; -- 4
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : STRING) RETURN STRING; -- 5
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : STRING) RETURN STRING; -- 6
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : STRING) RETURN STRING; -- 7
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : STRING) RETURN STRING; -- 8
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : STRING) RETURN STRING; -- 9
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : STRING) RETURN STRING; -- 10
-
- FUNCTION array_init(init : STD_LOGIC; nof : NATURAL) RETURN STD_LOGIC_VECTOR; -- useful to init a unconstrained array of size 1
- FUNCTION array_init(init, nof : NATURAL) RETURN t_natural_arr; -- useful to init a unconstrained array of size 1
- FUNCTION array_init(init, nof : NATURAL) RETURN t_nat_natural_arr; -- useful to init a unconstrained array of size 1
- FUNCTION array_init(init, nof, incr : NATURAL) RETURN t_natural_arr; -- useful to init an array with incrementing numbers
- FUNCTION array_init(init, nof, incr : NATURAL) RETURN t_nat_natural_arr;
- FUNCTION array_init(init, nof, incr : INTEGER) RETURN t_slv_16_arr;
- FUNCTION array_init(init, nof, incr : INTEGER) RETURN t_slv_32_arr;
- FUNCTION array_init(init, nof, width : NATURAL) RETURN STD_LOGIC_VECTOR; -- useful to init an unconstrained std_logic_vector with repetitive content
- FUNCTION array_init(init, nof, width, incr : NATURAL) RETURN STD_LOGIC_VECTOR; -- useful to init an unconstrained std_logic_vector with incrementing content
- FUNCTION array_sinit(init : INTEGER; nof, width : NATURAL) RETURN STD_LOGIC_VECTOR; -- useful to init an unconstrained std_logic_vector with repetitive content
-
- FUNCTION init_slv_64_matrix(nof_a, nof_b, k : INTEGER) RETURN t_slv_64_matrix; -- initialize all elements in t_slv_64_matrix to value k
-
- -- Concatenate two or more STD_LOGIC_VECTORs into a single STD_LOGIC_VECTOR or extract one of them from a concatenated STD_LOGIC_VECTOR
- FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
- FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a, b, c, d, e, f : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
- FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a, b, c, d, e : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
- FUNCTION func_slv_concat(use_a, use_b, use_c, use_d : BOOLEAN; a, b, c, d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
- FUNCTION func_slv_concat(use_a, use_b, use_c : BOOLEAN; a, b, c : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
- FUNCTION func_slv_concat(use_a, use_b : BOOLEAN; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
- FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL) RETURN NATURAL;
- FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL) RETURN NATURAL;
- FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL) RETURN NATURAL;
- FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL) RETURN NATURAL;
- FUNCTION func_slv_concat_w(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL) RETURN NATURAL;
- FUNCTION func_slv_concat_w(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL) RETURN NATURAL;
- FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
- FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
- FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
- FUNCTION func_slv_extract(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
- FUNCTION func_slv_extract(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
- FUNCTION func_slv_extract(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
-
- FUNCTION TO_UINT(vec : STD_LOGIC_VECTOR) RETURN NATURAL; -- beware: NATURAL'HIGH = 2**31-1, not 2*32-1, use TO_SINT to avoid warning
- FUNCTION TO_SINT(vec : STD_LOGIC_VECTOR) RETURN INTEGER;
-
- FUNCTION TO_UVEC(dec, w : NATURAL) RETURN STD_LOGIC_VECTOR;
- FUNCTION TO_SVEC(dec, w : INTEGER) RETURN STD_LOGIC_VECTOR;
-
- FUNCTION TO_SVEC_32(dec : INTEGER) RETURN STD_LOGIC_VECTOR; -- = TO_SVEC() with w=32 for t_slv_32_arr slv elements
-
- -- The RESIZE for SIGNED in IEEE.NUMERIC_STD extends the sign bit or it keeps the sign bit and LS part. This
- -- behaviour of preserving the sign bit is less suitable for DSP and not necessary in general. A more
- -- appropriate approach is to ignore the MSbit sign and just keep the LS part. For too large values this
- -- means that the result gets wrapped, but that is fine for default behaviour, because that is also what
- -- happens for RESIZE of UNSIGNED. Therefor this is what the RESIZE_NUM for SIGNED and the RESIZE_SVEC do
- -- and better not use RESIZE for SIGNED anymore.
- FUNCTION RESIZE_NUM(u : UNSIGNED; w : NATURAL) RETURN UNSIGNED; -- left extend with '0' or keep LS part (same as RESIZE for UNSIGNED)
- FUNCTION RESIZE_NUM(s : SIGNED; w : NATURAL) RETURN SIGNED; -- extend sign bit or keep LS part
- FUNCTION RESIZE_UVEC(sl : STD_LOGIC; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- left extend with '0' into slv
- FUNCTION RESIZE_UVEC(vec : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- left extend with '0' or keep LS part
- FUNCTION RESIZE_SVEC(vec : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- extend sign bit or keep LS part
- FUNCTION RESIZE_UINT(u : INTEGER; w : NATURAL) RETURN INTEGER; -- left extend with '0' or keep LS part
- FUNCTION RESIZE_SINT(s : INTEGER; w : NATURAL) RETURN INTEGER; -- extend sign bit or keep LS part
-
- FUNCTION RESIZE_UVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- = RESIZE_UVEC() with w=32 for t_slv_32_arr slv elements
- FUNCTION RESIZE_SVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- = RESIZE_SVEC() with w=32 for t_slv_32_arr slv elements
-
- FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR;
- FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : UNSIGNED) RETURN STD_LOGIC_VECTOR;
- FUNCTION INCR_SVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR;
- FUNCTION INCR_SVEC(vec : STD_LOGIC_VECTOR; dec : SIGNED) RETURN STD_LOGIC_VECTOR;
-
- -- Used in common_add_sub.vhd
- FUNCTION ADD_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR; -- l_vec + r_vec, treat slv operands as signed, slv output width is res_w
- FUNCTION SUB_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR; -- l_vec - r_vec, treat slv operands as signed, slv output width is res_w
- FUNCTION ADD_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR; -- l_vec + r_vec, treat slv operands as unsigned, slv output width is res_w
- FUNCTION SUB_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR; -- l_vec - r_vec, treat slv operands as unsigned, slv output width is res_w
-
- FUNCTION ADD_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- l_vec + r_vec, treat slv operands as signed, slv output width is l_vec'LENGTH
- FUNCTION SUB_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- l_vec - r_vec, treat slv operands as signed, slv output width is l_vec'LENGTH
- FUNCTION ADD_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- l_vec + r_vec, treat slv operands as unsigned, slv output width is l_vec'LENGTH
- FUNCTION SUB_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- l_vec - r_vec, treat slv operands as unsigned, slv output width is l_vec'LENGTH
-
- FUNCTION COMPLEX_MULT_REAL(a_re, a_im, b_re, b_im : INTEGER) RETURN INTEGER; -- Calculate real part of complex multiplication: a_re*b_re - a_im*b_im
- FUNCTION COMPLEX_MULT_IMAG(a_re, a_im, b_re, b_im : INTEGER) RETURN INTEGER; -- Calculate imag part of complex multiplication: a_im*b_re + a_re*b_im
-
- FUNCTION S_ADD_OVFLW_DET (a, b, sum_a_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- Preempt whether there is addition overflow for signed values
- FUNCTION S_SUB_OVFLW_DET (a, b, sub_a_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- Preempt whether there is subtraction overflow for signed values
-
- FUNCTION SHIFT_UVEC(vec : STD_LOGIC_VECTOR; shift : INTEGER) RETURN STD_LOGIC_VECTOR; -- < 0 shift left, > 0 shift right
- FUNCTION SHIFT_SVEC(vec : STD_LOGIC_VECTOR; shift : INTEGER) RETURN STD_LOGIC_VECTOR; -- < 0 shift left, > 0 shift right
-
- FUNCTION offset_binary(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
-
- FUNCTION truncate(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR; -- remove n LSBits from vec, so result has width vec'LENGTH-n
- FUNCTION truncate_and_resize_uvec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR; -- remove n LSBits from vec and then resize to width w
- FUNCTION truncate_and_resize_svec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR; -- idem for signed values
- FUNCTION scale(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR; -- add n '0' LSBits to vec
- FUNCTION scale_and_resize_uvec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR; -- add n '0' LSBits to vec and then resize to width w
- FUNCTION scale_and_resize_svec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR; -- idem for signed values
- FUNCTION truncate_or_resize_uvec(vec : STD_LOGIC_VECTOR; b : BOOLEAN; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- when b=TRUE then truncate to width w, else resize to width w
- FUNCTION truncate_or_resize_svec(vec : STD_LOGIC_VECTOR; b : BOOLEAN; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- idem for signed values
-
- FUNCTION s_round(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR; -- remove n LSBits from vec by rounding away from 0, so result has width vec'LENGTH-n, and clip to avoid wrap
- FUNCTION s_round(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR; -- remove n LSBits from vec by rounding away from 0, so result has width vec'LENGTH-n
- FUNCTION s_round_up(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR; -- idem but round up to +infinity (s_round_up = u_round)
- FUNCTION s_round_up(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR; -- idem but round up to +infinity (s_round_up = u_round)
- FUNCTION u_round(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR; -- idem round up for unsigned values
- FUNCTION u_round(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR; -- idem round up for unsigned values
-
- FUNCTION u_to_s(u : NATURAL; w : NATURAL) RETURN INTEGER; -- interpret w bit unsigned u as w bit signed, and remove any MSbits
- FUNCTION s_to_u(s : INTEGER; w : NATURAL) RETURN NATURAL; -- interpret w bit signed s as w bit unsigned, and remove any MSbits
-
- FUNCTION u_wrap(u : NATURAL; w : NATURAL) RETURN NATURAL; -- return u & 2**w-1 (bit wise and), so keep w LSbits of unsigned u, and remove MSbits
- FUNCTION s_wrap(s : INTEGER; w : NATURAL) RETURN INTEGER; -- return s & 2**w-1 (bit wise and), so keep w LSbits of signed s, and remove MSbits
-
- FUNCTION u_clip(u : NATURAL; max : NATURAL) RETURN NATURAL; -- if s < max return s, else return n
- FUNCTION s_clip(s : INTEGER; max : NATURAL; min : INTEGER) RETURN INTEGER; -- if s <= min return min, else if s >= max return max, else return s
- FUNCTION s_clip(s : INTEGER; max : NATURAL) RETURN INTEGER; -- if s <= -max return -max, else if s >= max return max, else return s
-
- FUNCTION hton(a : STD_LOGIC_VECTOR; w, sz : NATURAL) RETURN STD_LOGIC_VECTOR; -- convert endianity from host to network, sz in symbols of width w
- FUNCTION hton(a : STD_LOGIC_VECTOR; sz : NATURAL) RETURN STD_LOGIC_VECTOR; -- convert endianity from host to network, sz in bytes
- FUNCTION hton(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- convert endianity from host to network, for all bytes in a
- FUNCTION ntoh(a : STD_LOGIC_VECTOR; sz : NATURAL) RETURN STD_LOGIC_VECTOR; -- convert endianity from network to host, sz in bytes, ntoh() = hton()
- FUNCTION ntoh(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- convert endianity from network to host, for all bytes in a, ntoh() = hton()
-
- FUNCTION flip(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- bit flip a vector, map a[h:0] to [0:h]
- FUNCTION flip(a, w : NATURAL) RETURN NATURAL; -- bit flip a vector, map a[h:0] to [0:h], h = w-1
- FUNCTION flip(a : t_slv_32_arr) RETURN t_slv_32_arr;
- FUNCTION flip(a : t_integer_arr) RETURN t_integer_arr;
- FUNCTION flip(a : t_natural_arr) RETURN t_natural_arr;
- FUNCTION flip(a : t_nat_natural_arr) RETURN t_nat_natural_arr;
-
- FUNCTION transpose(a : STD_LOGIC_VECTOR; row, col : NATURAL) RETURN STD_LOGIC_VECTOR; -- transpose a vector, map a[i*row+j] to output index [j*col+i]
- FUNCTION transpose(a, row, col : NATURAL) RETURN NATURAL; -- transpose index a = [i*row+j] to output index [j*col+i]
-
- FUNCTION split_w(input_w : NATURAL; min_out_w : NATURAL; max_out_w : NATURAL) RETURN NATURAL;
-
- FUNCTION pad(str : STRING; width : NATURAL; pad_char : CHARACTER) RETURN STRING;
-
- FUNCTION slice_up(str : STRING; width : NATURAL; i : NATURAL) RETURN STRING;
- FUNCTION slice_up(str : STRING; width : NATURAL; i : NATURAL; pad_char : CHARACTER) RETURN STRING;
- FUNCTION slice_dn(str : STRING; width : NATURAL; i : NATURAL) RETURN STRING;
-
- FUNCTION nat_arr_to_concat_slv(nat_arr : t_natural_arr; nof_elements : NATURAL) RETURN STD_LOGIC_VECTOR;
-
- ------------------------------------------------------------------------------
- -- Component specific functions
- ------------------------------------------------------------------------------
-
- -- common_fifo_*
- PROCEDURE proc_common_fifo_asserts(CONSTANT c_fifo_name : IN STRING;
- CONSTANT c_note_is_ful : IN BOOLEAN;
- CONSTANT c_fail_rd_emp : IN BOOLEAN;
- SIGNAL wr_rst : IN STD_LOGIC;
- SIGNAL wr_clk : IN STD_LOGIC;
- SIGNAL wr_full : IN STD_LOGIC;
- SIGNAL wr_en : IN STD_LOGIC;
- SIGNAL rd_clk : IN STD_LOGIC;
- SIGNAL rd_empty : IN STD_LOGIC;
- SIGNAL rd_en : IN STD_LOGIC);
-
- -- common_fanout_tree
- FUNCTION func_common_fanout_tree_pipelining(c_nof_stages, c_nof_output_per_cell, c_nof_output : NATURAL;
- c_cell_pipeline_factor_arr, c_cell_pipeline_arr : t_natural_arr) RETURN t_natural_arr;
-
- -- common_reorder_symbol
- FUNCTION func_common_reorder2_is_there(I, J : NATURAL) RETURN BOOLEAN;
- FUNCTION func_common_reorder2_is_active(I, J, N : NATURAL) RETURN BOOLEAN;
- FUNCTION func_common_reorder2_get_select_index(I, J, N : NATURAL) RETURN INTEGER;
- FUNCTION func_common_reorder2_get_select(I, J, N : NATURAL; select_arr : t_natural_arr) RETURN NATURAL;
- FUNCTION func_common_reorder2_inverse_select(N : NATURAL; select_arr : t_natural_arr) RETURN t_natural_arr;
-
- -- Generate faster sample SCLK from digital DCLK for sim only
- PROCEDURE proc_common_dclk_generate_sclk(CONSTANT Pfactor : IN POSITIVE;
- SIGNAL dclk : IN STD_LOGIC;
- SIGNAL sclk : INOUT STD_LOGIC);
-
-END common_pkg;
-
-PACKAGE BODY common_pkg IS
-
- FUNCTION pow2(n : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN 2**n;
- END;
-
- FUNCTION ceil_pow2(n : INTEGER) RETURN NATURAL IS
- -- Also allows negative exponents and rounds up before returning the value
- BEGIN
- RETURN natural(integer(ceil(2**real(n))));
- END;
-
- FUNCTION true_log2(n : NATURAL) RETURN NATURAL IS
- -- Purpose: For calculating extra vector width of existing vector
- -- Description: Return mathematical ceil(log2(n))
- -- n log2()
- -- 0 -> -oo --> FAILURE
- -- 1 -> 0
- -- 2 -> 1
- -- 3 -> 2
- -- 4 -> 2
- -- 5 -> 3
- -- 6 -> 3
- -- 7 -> 3
- -- 8 -> 3
- -- 9 -> 4
- -- etc, up to n = NATURAL'HIGH = 2**31-1
- BEGIN
- RETURN natural(integer(ceil(log2(real(n)))));
- END;
-
- FUNCTION ceil_log2(n : NATURAL) RETURN NATURAL IS
- -- Purpose: For calculating vector width of new vector
- -- Description:
- -- Same as true_log2() except ceil_log2(1) = 1, which is needed to support
- -- the vector width width for 1 address, to avoid NULL array for single
- -- word register address.
- -- If n = 0, return 0 so we get a NULL array when using
- -- STD_LOGIC_VECTOR(ceil_log2(g_addr_w)-1 DOWNTO 0), instead of an error.
- BEGIN
- IF n = 0 THEN
- RETURN 0; -- Get NULL array
- ELSIF n = 1 THEN
- RETURN 1; -- avoid NULL array
- ELSE
- RETURN true_log2(n);
- END IF;
- END;
-
- FUNCTION floor_log10(n : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN natural(integer(floor(log10(real(n)))));
- END;
-
- FUNCTION is_pow2(n : NATURAL) RETURN BOOLEAN IS
- BEGIN
- RETURN n = 2**true_log2(n);
- END;
-
- FUNCTION true_log_pow2(n : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN 2**true_log2(n);
- END;
-
- FUNCTION ratio(n, d : NATURAL) RETURN NATURAL IS
- BEGIN
- IF n MOD d = 0 THEN
- RETURN n / d;
- ELSE
- RETURN 0;
- END IF;
- END;
-
- FUNCTION ratio2(n, m : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN largest(ratio(n, m), ratio(m, n));
- END;
-
- FUNCTION ceil_div(n, d : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN n / d + sel_a_b(n MOD d = 0, 0, 1);
- END;
-
- FUNCTION ceil_value(n, d : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN ceil_div(n, d) * d;
- END;
-
- FUNCTION floor_value(n, d : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN (n / d) * d;
- END;
-
- FUNCTION ceil_div(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED IS
- BEGIN
- RETURN n / d + sel_a_b(n MOD d = 0, 0, 1); -- "/" returns same width as n
- END;
-
- FUNCTION ceil_value(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED IS
- CONSTANT w : NATURAL := n'LENGTH;
- VARIABLE p : UNSIGNED(2 * w - 1 DOWNTO 0);
- BEGIN
- p := ceil_div(n, d) * d;
- RETURN p(w - 1 DOWNTO 0); -- return same width as n
- END;
-
- FUNCTION floor_value(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED IS
- CONSTANT w : NATURAL := n'LENGTH;
- VARIABLE p : UNSIGNED(2 * w - 1 DOWNTO 0);
- BEGIN
- p := (n / d) * d;
- RETURN p(w - 1 DOWNTO 0); -- return same width as n
- END;
-
- FUNCTION slv(n : IN STD_LOGIC) RETURN STD_LOGIC_VECTOR IS
- VARIABLE r : STD_LOGIC_VECTOR(0 DOWNTO 0);
- BEGIN
- r(0) := n;
- RETURN r;
- END;
-
- FUNCTION sl(n : IN STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
- VARIABLE r : STD_LOGIC;
- BEGIN
- r := n(n'LOW);
- RETURN r;
- END;
-
- FUNCTION to_natural_arr(n : t_integer_arr; to_zero : BOOLEAN) RETURN t_natural_arr IS
- VARIABLE vN : t_integer_arr(n'LENGTH - 1 DOWNTO 0);
- VARIABLE vR : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
- BEGIN
- vN := n;
- FOR I IN vN'RANGE LOOP
- IF to_zero = FALSE THEN
- vR(I) := vN(I);
- ELSE
- vR(I) := 0;
- IF vN(I) > 0 THEN
- vR(I) := vN(I);
- END IF;
- END IF;
- END LOOP;
- RETURN vR;
- END;
-
- FUNCTION to_natural_arr(n : t_nat_natural_arr) RETURN t_natural_arr IS
- VARIABLE vN : t_nat_natural_arr(n'LENGTH - 1 DOWNTO 0);
- VARIABLE vR : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
- BEGIN
- vN := n;
- FOR I IN vN'RANGE LOOP
- vR(I) := vN(I);
- END LOOP;
- RETURN vR;
- END;
-
- FUNCTION to_integer_arr(n : t_natural_arr) RETURN t_integer_arr IS
- VARIABLE vN : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
- VARIABLE vR : t_integer_arr(n'LENGTH - 1 DOWNTO 0);
- BEGIN
- vN := n;
- FOR I IN vN'RANGE LOOP
- vR(I) := vN(I);
- END LOOP;
- RETURN vR;
- END;
-
- FUNCTION to_integer_arr(n : t_nat_natural_arr) RETURN t_integer_arr IS
- VARIABLE vN : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
- BEGIN
- vN := to_natural_arr(n);
- RETURN to_integer_arr(vN);
- END;
-
- FUNCTION to_slv_32_arr(n : t_integer_arr) RETURN t_slv_32_arr IS
- VARIABLE vN : t_integer_arr(n'LENGTH - 1 DOWNTO 0);
- VARIABLE vR : t_slv_32_arr(n'LENGTH - 1 DOWNTO 0);
- BEGIN
- vN := n;
- FOR I IN vN'RANGE LOOP
- vR(I) := TO_SVEC(vN(I), 32);
- END LOOP;
- RETURN vR;
- END;
-
- FUNCTION to_slv_32_arr(n : t_natural_arr) RETURN t_slv_32_arr IS
- VARIABLE vN : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
- VARIABLE vR : t_slv_32_arr(n'LENGTH - 1 DOWNTO 0);
- BEGIN
- vN := n;
- FOR I IN vN'RANGE LOOP
- vR(I) := TO_UVEC(vN(I), 32);
- END LOOP;
- RETURN vR;
- END;
-
- FUNCTION vector_tree(slv : STD_LOGIC_VECTOR; operation : STRING) RETURN STD_LOGIC IS
- -- Linear loop to determine result takes combinatorial delay that is proportional to slv'LENGTH:
- -- FOR I IN slv'RANGE LOOP
- -- v_result := v_result OPERATION slv(I);
- -- END LOOP;
- -- RETURN v_result;
- -- Instead use binary tree to determine result with smallest combinatorial delay that depends on log2(slv'LENGTH)
- CONSTANT c_slv_w : NATURAL := slv'LENGTH;
- CONSTANT c_nof_stages : NATURAL := ceil_log2(c_slv_w);
- CONSTANT c_w : NATURAL := 2**c_nof_stages; -- extend the input slv to a vector with length power of 2 to ease using binary tree
- TYPE t_stage_arr IS ARRAY (-1 TO c_nof_stages - 1) OF STD_LOGIC_VECTOR(c_w - 1 DOWNTO 0);
- VARIABLE v_stage_arr : t_stage_arr;
- VARIABLE v_result : STD_LOGIC := '0';
- BEGIN
- -- default any unused, the stage results will be kept in the LSBits and the last result in bit 0
- IF operation = "AND" THEN
- v_stage_arr := (OTHERS => (OTHERS => '1'));
- ELSIF operation = "OR" THEN
- v_stage_arr := (OTHERS => (OTHERS => '0'));
- ELSIF operation = "XOR" THEN
- v_stage_arr := (OTHERS => (OTHERS => '0'));
- ELSE
- ASSERT TRUE REPORT "common_pkg: Unsupported vector_tree operation" SEVERITY FAILURE;
- END IF;
- v_stage_arr(-1)(c_slv_w - 1 DOWNTO 0) := slv; -- any unused input c_w : c_slv_w bits have void default value
- FOR J IN 0 TO c_nof_stages - 1 LOOP
- FOR I IN 0 TO c_w / (2**(J + 1)) - 1 LOOP
- IF operation = "AND" THEN
- v_stage_arr(J)(I) := v_stage_arr(J - 1)(2 * I) AND v_stage_arr(J - 1)(2 * I + 1);
- ELSIF operation = "OR" THEN
- v_stage_arr(J)(I) := v_stage_arr(J - 1)(2 * I) OR v_stage_arr(J - 1)(2 * I + 1);
- ELSIF operation = "XOR" THEN
- v_stage_arr(J)(I) := v_stage_arr(J - 1)(2 * I) XOR v_stage_arr(J - 1)(2 * I + 1);
- END IF;
- END LOOP;
- END LOOP;
- RETURN v_stage_arr(c_nof_stages - 1)(0);
- END;
-
- FUNCTION vector_and(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
- BEGIN
- RETURN vector_tree(slv, "AND");
- END;
-
- FUNCTION vector_or(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
- BEGIN
- RETURN vector_tree(slv, "OR");
- END;
-
- FUNCTION vector_xor(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
- BEGIN
- RETURN vector_tree(slv, "XOR");
- END;
-
- FUNCTION vector_one_hot(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_one_hot : BOOLEAN := FALSE;
- VARIABLE v_zeros : STD_LOGIC_VECTOR(slv'RANGE) := (OTHERS => '0');
- BEGIN
- FOR i IN slv'RANGE LOOP
- IF slv(i) = '1' THEN
- IF NOT (v_one_hot) THEN
- -- No hot bits found so far
- v_one_hot := TRUE;
- ELSE
- -- This is the second hot bit found; return zeros.
- RETURN v_zeros;
- END IF;
- END IF;
- END LOOP;
- -- No or a single hot bit found in slv; return slv.
- RETURN slv;
- END;
-
- FUNCTION andv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
- BEGIN
- RETURN vector_tree(slv, "AND");
- END;
-
- FUNCTION orv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
- BEGIN
- RETURN vector_tree(slv, "OR");
- END;
-
- FUNCTION xorv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
- BEGIN
- RETURN vector_tree(slv, "XOR");
- END;
-
- FUNCTION matrix_and(mat : t_sl_matrix; wi, wj : NATURAL) RETURN STD_LOGIC IS
- VARIABLE v_mat : t_sl_matrix(0 TO wi - 1, 0 TO wj - 1) := mat; -- map to fixed range
- VARIABLE v_result : STD_LOGIC := '1';
- BEGIN
- FOR I IN 0 TO wi - 1 LOOP
- FOR J IN 0 TO wj - 1 LOOP
- v_result := v_result AND v_mat(I, J);
- END LOOP;
- END LOOP;
- RETURN v_result;
- END;
-
- FUNCTION matrix_or(mat : t_sl_matrix; wi, wj : NATURAL) RETURN STD_LOGIC IS
- VARIABLE v_mat : t_sl_matrix(0 TO wi - 1, 0 TO wj - 1) := mat; -- map to fixed range
- VARIABLE v_result : STD_LOGIC := '0';
- BEGIN
- FOR I IN 0 TO wi - 1 LOOP
- FOR J IN 0 TO wj - 1 LOOP
- v_result := v_result OR v_mat(I, J);
- END LOOP;
- END LOOP;
- RETURN v_result;
- END;
-
- FUNCTION smallest(n, m : INTEGER) RETURN INTEGER IS
- BEGIN
- IF n < m THEN
- RETURN n;
- ELSE
- RETURN m;
- END IF;
- END;
-
- FUNCTION smallest(n, m, l : INTEGER) RETURN INTEGER IS
- VARIABLE v : NATURAL;
- BEGIN
- v := n;
- IF v > m THEN
- v := m;
- END IF;
- IF v > l THEN
- v := l;
- END IF;
- RETURN v;
- END;
-
- FUNCTION smallest(n : t_natural_arr) RETURN NATURAL IS
- VARIABLE m : NATURAL := 0;
- BEGIN
- FOR I IN n'RANGE LOOP
- IF n(I) < m THEN
- m := n(I);
- END IF;
- END LOOP;
- RETURN m;
- END;
-
- FUNCTION largest(n, m : INTEGER) RETURN INTEGER IS
- BEGIN
- IF n > m THEN
- RETURN n;
- ELSE
- RETURN m;
- END IF;
- END;
-
- FUNCTION largest(n : t_natural_arr) RETURN NATURAL IS
- VARIABLE m : NATURAL := 0;
- BEGIN
- FOR I IN n'RANGE LOOP
- IF n(I) > m THEN
- m := n(I);
- END IF;
- END LOOP;
- RETURN m;
- END;
-
- FUNCTION func_sum(n : t_natural_arr) RETURN NATURAL IS
- VARIABLE vS : NATURAL;
- BEGIN
- vS := 0;
- FOR I IN n'RANGE LOOP
- vS := vS + n(I);
- END LOOP;
- RETURN vS;
- END;
-
- FUNCTION func_sum(n : t_nat_natural_arr) RETURN NATURAL IS
- VARIABLE vN : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
- BEGIN
- vN := to_natural_arr(n);
- RETURN func_sum(vN);
- END;
-
- FUNCTION func_product(n : t_natural_arr) RETURN NATURAL IS
- VARIABLE vP : NATURAL;
- BEGIN
- vP := 1;
- FOR I IN n'RANGE LOOP
- vP := vP * n(I);
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION func_product(n : t_nat_natural_arr) RETURN NATURAL IS
- VARIABLE vN : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
- BEGIN
- vN := to_natural_arr(n);
- RETURN func_product(vN);
- END;
-
- FUNCTION "+"(L, R : t_natural_arr) RETURN t_natural_arr IS
- CONSTANT w : NATURAL := L'LENGTH;
- VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
- BEGIN
- vL := L;
- vR := R;
- FOR I IN vL'RANGE LOOP
- vP(I) := vL(I) + vR(I);
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION "+"(L : t_natural_arr; R : INTEGER) RETURN t_natural_arr IS
- CONSTANT w : NATURAL := L'LENGTH;
- VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
- BEGIN
- vL := L;
- FOR I IN vL'RANGE LOOP
- vP(I) := vL(I) + R;
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION "+"(L : INTEGER; R : t_natural_arr) RETURN t_natural_arr IS
- BEGIN
- RETURN R + L;
- END;
-
- FUNCTION "-"(L, R : t_natural_arr) RETURN t_natural_arr IS
- CONSTANT w : NATURAL := L'LENGTH;
- VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
- BEGIN
- vL := L;
- vR := R;
- FOR I IN vL'RANGE LOOP
- vP(I) := vL(I) - vR(I);
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION "-"(L, R : t_natural_arr) RETURN t_integer_arr IS
- CONSTANT w : NATURAL := L'LENGTH;
- VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vP : t_integer_arr(w - 1 DOWNTO 0);
- BEGIN
- vL := L;
- vR := R;
- FOR I IN vL'RANGE LOOP
- vP(I) := vL(I) - vR(I);
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION "-"(L : t_natural_arr; R : INTEGER) RETURN t_natural_arr IS
- CONSTANT w : NATURAL := L'LENGTH;
- VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
- BEGIN
- vL := L;
- FOR I IN vL'RANGE LOOP
- vP(I) := vL(I) - R;
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION "-"(L : INTEGER; R : t_natural_arr) RETURN t_natural_arr IS
- CONSTANT w : NATURAL := R'LENGTH;
- VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
- BEGIN
- vR := R;
- FOR I IN vR'RANGE LOOP
- vP(I) := L - vR(I);
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION "*"(L, R : t_natural_arr) RETURN t_natural_arr IS
- CONSTANT w : NATURAL := L'LENGTH;
- VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
- BEGIN
- vL := L;
- vR := R;
- FOR I IN vL'RANGE LOOP
- vP(I) := vL(I) * vR(I);
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION "*"(L : t_natural_arr; R : NATURAL) RETURN t_natural_arr IS
- CONSTANT w : NATURAL := L'LENGTH;
- VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
- BEGIN
- vL := L;
- FOR I IN vL'RANGE LOOP
- vP(I) := vL(I) * R;
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION "*"(L : NATURAL; R : t_natural_arr) RETURN t_natural_arr IS
- BEGIN
- RETURN R * L;
- END;
-
- FUNCTION "/"(L, R : t_natural_arr) RETURN t_natural_arr IS
- CONSTANT w : NATURAL := L'LENGTH;
- VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
- BEGIN
- vL := L;
- vR := R;
- FOR I IN vL'RANGE LOOP
- vP(I) := vL(I) / vR(I);
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION "/"(L : t_natural_arr; R : POSITIVE) RETURN t_natural_arr IS
- CONSTANT w : NATURAL := L'LENGTH;
- VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
- BEGIN
- vL := L;
- FOR I IN vL'RANGE LOOP
- vP(I) := vL(I) / R;
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION "/"(L : NATURAL; R : t_natural_arr) RETURN t_natural_arr IS
- CONSTANT w : NATURAL := R'LENGTH;
- VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
- VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
- BEGIN
- vR := R;
- FOR I IN vR'RANGE LOOP
- vP(I) := L / vR(I);
- END LOOP;
- RETURN vP;
- END;
-
- FUNCTION is_true(a : STD_LOGIC) RETURN BOOLEAN IS
- BEGIN
- IF a = '1' THEN
- RETURN TRUE;
- ELSE
- RETURN FALSE;
- END IF;
- END;
- FUNCTION is_true(a : STD_LOGIC) RETURN NATURAL IS
- BEGIN
- IF a = '1' THEN
- RETURN 1;
- ELSE
- RETURN 0;
- END IF;
- END;
- FUNCTION is_true(a : BOOLEAN) RETURN STD_LOGIC IS
- BEGIN
- IF a = TRUE THEN
- RETURN '1';
- ELSE
- RETURN '0';
- END IF;
- END;
- FUNCTION is_true(a : BOOLEAN) RETURN NATURAL IS
- BEGIN
- IF a = TRUE THEN
- RETURN 1;
- ELSE
- RETURN 0;
- END IF;
- END;
- FUNCTION is_true(a : INTEGER) RETURN BOOLEAN IS
- BEGIN
- IF a /= 0 THEN
- RETURN TRUE;
- ELSE
- RETURN FALSE;
- END IF;
- END;
- FUNCTION is_true(a : INTEGER) RETURN STD_LOGIC IS
- BEGIN
- IF a /= 0 THEN
- RETURN '1';
- ELSE
- RETURN '0';
- END IF;
- END;
-
- FUNCTION is_all(vec : STD_LOGIC_VECTOR; val : STD_LOGIC) RETURN BOOLEAN IS
- CONSTANT all_bits : STD_LOGIC_VECTOR(vec'RANGE) := (OTHERS => val);
- BEGIN
- RETURN vec = all_bits;
- END FUNCTION;
-
- FUNCTION sel_a_b(sel, a, b : INTEGER) RETURN INTEGER IS
- BEGIN
- IF sel /= 0 THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel, a, b : BOOLEAN) RETURN BOOLEAN IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : INTEGER) RETURN INTEGER IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : REAL) RETURN REAL IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : STD_LOGIC) RETURN STD_LOGIC IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : INTEGER; a, b : STD_LOGIC) RETURN STD_LOGIC IS
- BEGIN
- IF sel /= 0 THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : INTEGER; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- IF sel /= 0 THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : SIGNED) RETURN SIGNED IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : UNSIGNED) RETURN UNSIGNED IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_integer_arr) RETURN t_integer_arr IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_natural_arr) RETURN t_natural_arr IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_nat_integer_arr) RETURN t_nat_integer_arr IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_nat_natural_arr) RETURN t_nat_natural_arr IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : STRING) RETURN STRING IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : INTEGER; a, b : STRING) RETURN STRING IS
- BEGIN
- IF sel /= 0 THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : TIME) RETURN TIME IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- FUNCTION sel_a_b(sel : BOOLEAN; a, b : SEVERITY_LEVEL) RETURN SEVERITY_LEVEL IS
- BEGIN
- IF sel = TRUE THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
-
- -- sel_n : boolean
- FUNCTION sel_n(sel : NATURAL; a, b, c : BOOLEAN) RETURN BOOLEAN IS
- CONSTANT c_arr : t_nat_boolean_arr := (a, b, c);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d : BOOLEAN) RETURN BOOLEAN IS
- CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : BOOLEAN) RETURN BOOLEAN IS
- CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : BOOLEAN) RETURN BOOLEAN IS
- CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e, f);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : BOOLEAN) RETURN BOOLEAN IS
- CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e, f, g);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : BOOLEAN) RETURN BOOLEAN IS
- CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e, f, g, h);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : BOOLEAN) RETURN BOOLEAN IS
- CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e, f, g, h, i);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : BOOLEAN) RETURN BOOLEAN IS
- CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e, f, g, h, i, j);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- -- sel_n : integer
- FUNCTION sel_n(sel : NATURAL; a, b, c : INTEGER) RETURN INTEGER IS
- CONSTANT c_arr : t_nat_integer_arr := (a, b, c);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d : INTEGER) RETURN INTEGER IS
- CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : INTEGER) RETURN INTEGER IS
- CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : INTEGER) RETURN INTEGER IS
- CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e, f);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : INTEGER) RETURN INTEGER IS
- CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e, f, g);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : INTEGER) RETURN INTEGER IS
- CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e, f, g, h);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : INTEGER) RETURN INTEGER IS
- CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e, f, g, h, i);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : INTEGER) RETURN INTEGER IS
- CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e, f, g, h, i, j);
- BEGIN
- RETURN c_arr(sel);
- END;
-
- -- sel_n : string
- FUNCTION sel_n(sel : NATURAL; a, b : STRING) RETURN STRING IS
- BEGIN
- IF sel = 0 THEN
- RETURN a;
- ELSE
- RETURN b;
- END IF;
- END;
- FUNCTION sel_n(sel : NATURAL; a, b, c : STRING) RETURN STRING IS
- BEGIN
- IF sel < 2 THEN
- RETURN sel_n(sel, a, b);
- ELSE
- RETURN c;
- END IF;
- END;
- FUNCTION sel_n(sel : NATURAL; a, b, c, d : STRING) RETURN STRING IS
- BEGIN
- IF sel < 3 THEN
- RETURN sel_n(sel, a, b, c);
- ELSE
- RETURN d;
- END IF;
- END;
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : STRING) RETURN STRING IS
- BEGIN
- IF sel < 4 THEN
- RETURN sel_n(sel, a, b, c, d);
- ELSE
- RETURN e;
- END IF;
- END;
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : STRING) RETURN STRING IS
- BEGIN
- IF sel < 5 THEN
- RETURN sel_n(sel, a, b, c, d, e);
- ELSE
- RETURN f;
- END IF;
- END;
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : STRING) RETURN STRING IS
- BEGIN
- IF sel < 6 THEN
- RETURN sel_n(sel, a, b, c, d, e, f);
- ELSE
- RETURN g;
- END IF;
- END;
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : STRING) RETURN STRING IS
- BEGIN
- IF sel < 7 THEN
- RETURN sel_n(sel, a, b, c, d, e, f, g);
- ELSE
- RETURN h;
- END IF;
- END;
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : STRING) RETURN STRING IS
- BEGIN
- IF sel < 8 THEN
- RETURN sel_n(sel, a, b, c, d, e, f, g, h);
- ELSE
- RETURN i;
- END IF;
- END;
- FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : STRING) RETURN STRING IS
- BEGIN
- IF sel < 9 THEN
- RETURN sel_n(sel, a, b, c, d, e, f, g, h, i);
- ELSE
- RETURN j;
- END IF;
- END;
-
- FUNCTION array_init(init : STD_LOGIC; nof : NATURAL) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_arr : STD_LOGIC_VECTOR(0 TO nof - 1);
- BEGIN
- FOR I IN v_arr'RANGE LOOP
- v_arr(I) := init;
- END LOOP;
- RETURN v_arr;
- END;
-
- FUNCTION array_init(init, nof : NATURAL) RETURN t_natural_arr IS
- VARIABLE v_arr : t_natural_arr(0 TO nof - 1);
- BEGIN
- FOR I IN v_arr'RANGE LOOP
- v_arr(I) := init;
- END LOOP;
- RETURN v_arr;
- END;
-
- FUNCTION array_init(init, nof : NATURAL) RETURN t_nat_natural_arr IS
- VARIABLE v_arr : t_nat_natural_arr(0 TO nof - 1);
- BEGIN
- FOR I IN v_arr'RANGE LOOP
- v_arr(I) := init;
- END LOOP;
- RETURN v_arr;
- END;
-
- FUNCTION array_init(init, nof, incr : NATURAL) RETURN t_natural_arr IS
- VARIABLE v_arr : t_natural_arr(0 TO nof - 1);
- VARIABLE v_i : NATURAL;
- BEGIN
- v_i := 0;
- FOR I IN v_arr'RANGE LOOP
- v_arr(I) := init + v_i * incr;
- v_i := v_i + 1;
- END LOOP;
- RETURN v_arr;
- END;
-
- FUNCTION array_init(init, nof, incr : NATURAL) RETURN t_nat_natural_arr IS
- VARIABLE v_arr : t_nat_natural_arr(0 TO nof - 1);
- VARIABLE v_i : NATURAL;
- BEGIN
- v_i := 0;
- FOR I IN v_arr'RANGE LOOP
- v_arr(I) := init + v_i * incr;
- v_i := v_i + 1;
- END LOOP;
- RETURN v_arr;
- END;
-
- FUNCTION array_init(init, nof, incr : INTEGER) RETURN t_slv_16_arr IS
- VARIABLE v_arr : t_slv_16_arr(0 TO nof - 1);
- VARIABLE v_i : NATURAL;
- BEGIN
- v_i := 0;
- FOR I IN v_arr'RANGE LOOP
- v_arr(I) := TO_SVEC(init + v_i * incr, 16);
- v_i := v_i + 1;
- END LOOP;
- RETURN v_arr;
- END;
-
- FUNCTION array_init(init, nof, incr : INTEGER) RETURN t_slv_32_arr IS
- VARIABLE v_arr : t_slv_32_arr(0 TO nof - 1);
- VARIABLE v_i : NATURAL;
- BEGIN
- v_i := 0;
- FOR I IN v_arr'RANGE LOOP
- v_arr(I) := TO_SVEC(init + v_i * incr, 32);
- v_i := v_i + 1;
- END LOOP;
- RETURN v_arr;
- END;
-
- FUNCTION array_init(init, nof, width : NATURAL) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_arr : STD_LOGIC_VECTOR(nof * width - 1 DOWNTO 0);
- BEGIN
- FOR I IN 0 TO nof - 1 LOOP
- v_arr(width * (I + 1) - 1 DOWNTO width * I) := TO_UVEC(init, width);
- END LOOP;
- RETURN v_arr;
- END;
-
- FUNCTION array_init(init, nof, width, incr : NATURAL) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_arr : STD_LOGIC_VECTOR(nof * width - 1 DOWNTO 0);
- VARIABLE v_i : NATURAL;
- BEGIN
- v_i := 0;
- FOR I IN 0 TO nof - 1 LOOP
- v_arr(width * (I + 1) - 1 DOWNTO width * I) := TO_UVEC(init + v_i * incr, width);
- v_i := v_i + 1;
- END LOOP;
- RETURN v_arr;
- END;
-
- FUNCTION array_sinit(init : INTEGER; nof, width : NATURAL) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_arr : STD_LOGIC_VECTOR(nof * width - 1 DOWNTO 0);
- BEGIN
- FOR I IN 0 TO nof - 1 LOOP
- v_arr(width * (I + 1) - 1 DOWNTO width * I) := TO_SVEC(init, width);
- END LOOP;
- RETURN v_arr;
- END;
-
- FUNCTION init_slv_64_matrix(nof_a, nof_b, k : INTEGER) RETURN t_slv_64_matrix IS
- VARIABLE v_mat : t_slv_64_matrix(nof_a - 1 DOWNTO 0, nof_b - 1 DOWNTO 0);
- BEGIN
- FOR I IN 0 TO nof_a - 1 LOOP
- FOR J IN 0 TO nof_b - 1 LOOP
- v_mat(I, J) := TO_SVEC(k, 64);
- END LOOP;
- END LOOP;
- RETURN v_mat;
- END;
-
- -- Support concatenation of up to 7 slv into 1 slv
- FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- CONSTANT c_max_w : NATURAL := a'LENGTH + b'LENGTH + c'LENGTH + d'LENGTH + e'LENGTH + f'LENGTH + g'LENGTH;
- VARIABLE v_res : STD_LOGIC_VECTOR(c_max_w - 1 DOWNTO 0) := (OTHERS => '0');
- VARIABLE v_len : NATURAL := 0;
- BEGIN
- IF use_a = TRUE THEN
- v_res(a'LENGTH - 1 + v_len DOWNTO v_len) := a;
- v_len := v_len + a'LENGTH;
- END IF;
- IF use_b = TRUE THEN
- v_res(b'LENGTH - 1 + v_len DOWNTO v_len) := b;
- v_len := v_len + b'LENGTH;
- END IF;
- IF use_c = TRUE THEN
- v_res(c'LENGTH - 1 + v_len DOWNTO v_len) := c;
- v_len := v_len + c'LENGTH;
- END IF;
- IF use_d = TRUE THEN
- v_res(d'LENGTH - 1 + v_len DOWNTO v_len) := d;
- v_len := v_len + d'LENGTH;
- END IF;
- IF use_e = TRUE THEN
- v_res(e'LENGTH - 1 + v_len DOWNTO v_len) := e;
- v_len := v_len + e'LENGTH;
- END IF;
- IF use_f = TRUE THEN
- v_res(f'LENGTH - 1 + v_len DOWNTO v_len) := f;
- v_len := v_len + f'LENGTH;
- END IF;
- IF use_g = TRUE THEN
- v_res(g'LENGTH - 1 + v_len DOWNTO v_len) := g;
- v_len := v_len + g'LENGTH;
- END IF;
- RETURN v_res(v_len - 1 DOWNTO 0);
- END func_slv_concat;
-
- FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a, b, c, d, e, f : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, a, b, c, d, e, f, "0");
- END func_slv_concat;
-
- FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a, b, c, d, e : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN func_slv_concat(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, a, b, c, d, e, "0", "0");
- END func_slv_concat;
-
- FUNCTION func_slv_concat(use_a, use_b, use_c, use_d : BOOLEAN; a, b, c, d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN func_slv_concat(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, a, b, c, d, "0", "0", "0");
- END func_slv_concat;
-
- FUNCTION func_slv_concat(use_a, use_b, use_c : BOOLEAN; a, b, c : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN func_slv_concat(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, a, b, c, "0", "0", "0", "0");
- END func_slv_concat;
-
- FUNCTION func_slv_concat(use_a, use_b : BOOLEAN; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN func_slv_concat(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, a, b, "0", "0", "0", "0", "0");
- END func_slv_concat;
-
- FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL) RETURN NATURAL IS
- VARIABLE v_len : NATURAL := 0;
- BEGIN
- IF use_a = TRUE THEN
- v_len := v_len + a_w;
- END IF;
- IF use_b = TRUE THEN
- v_len := v_len + b_w;
- END IF;
- IF use_c = TRUE THEN
- v_len := v_len + c_w;
- END IF;
- IF use_d = TRUE THEN
- v_len := v_len + d_w;
- END IF;
- IF use_e = TRUE THEN
- v_len := v_len + e_w;
- END IF;
- IF use_f = TRUE THEN
- v_len := v_len + f_w;
- END IF;
- IF use_g = TRUE THEN
- v_len := v_len + g_w;
- END IF;
- RETURN v_len;
- END func_slv_concat_w;
-
- FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, 0);
- END func_slv_concat_w;
-
- FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, a_w, b_w, c_w, d_w, e_w, 0, 0);
- END func_slv_concat_w;
-
- FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, a_w, b_w, c_w, d_w, 0, 0, 0);
- END func_slv_concat_w;
-
- FUNCTION func_slv_concat_w(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN func_slv_concat_w(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, a_w, b_w, c_w, 0, 0, 0, 0);
- END func_slv_concat_w;
-
- FUNCTION func_slv_concat_w(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN func_slv_concat_w(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, a_w, b_w, 0, 0, 0, 0, 0);
- END func_slv_concat_w;
-
- -- extract slv
- FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_w : NATURAL := 0;
- VARIABLE v_lo : NATURAL := 0;
- BEGIN
- -- if the selected slv is not used in vec, then return dummy, else return the selected slv from vec
- CASE sel IS
- WHEN 0 =>
- IF use_a = TRUE THEN
- v_w := a_w;
- ELSE
- RETURN c_slv0(a_w - 1 DOWNTO 0);
- END IF;
- WHEN 1 =>
- IF use_b = TRUE THEN
- v_w := b_w;
- ELSE
- RETURN c_slv0(b_w - 1 DOWNTO 0);
- END IF;
- IF use_a = TRUE THEN
- v_lo := v_lo + a_w;
- END IF;
- WHEN 2 =>
- IF use_c = TRUE THEN
- v_w := c_w;
- ELSE
- RETURN c_slv0(c_w - 1 DOWNTO 0);
- END IF;
- IF use_a = TRUE THEN
- v_lo := v_lo + a_w;
- END IF;
- IF use_b = TRUE THEN
- v_lo := v_lo + b_w;
- END IF;
- WHEN 3 =>
- IF use_d = TRUE THEN
- v_w := d_w;
- ELSE
- RETURN c_slv0(d_w - 1 DOWNTO 0);
- END IF;
- IF use_a = TRUE THEN
- v_lo := v_lo + a_w;
- END IF;
- IF use_b = TRUE THEN
- v_lo := v_lo + b_w;
- END IF;
- IF use_c = TRUE THEN
- v_lo := v_lo + c_w;
- END IF;
- WHEN 4 =>
- IF use_e = TRUE THEN
- v_w := e_w;
- ELSE
- RETURN c_slv0(e_w - 1 DOWNTO 0);
- END IF;
- IF use_a = TRUE THEN
- v_lo := v_lo + a_w;
- END IF;
- IF use_b = TRUE THEN
- v_lo := v_lo + b_w;
- END IF;
- IF use_c = TRUE THEN
- v_lo := v_lo + c_w;
- END IF;
- IF use_d = TRUE THEN
- v_lo := v_lo + d_w;
- END IF;
- WHEN 5 =>
- IF use_f = TRUE THEN
- v_w := f_w;
- ELSE
- RETURN c_slv0(f_w - 1 DOWNTO 0);
- END IF;
- IF use_a = TRUE THEN
- v_lo := v_lo + a_w;
- END IF;
- IF use_b = TRUE THEN
- v_lo := v_lo + b_w;
- END IF;
- IF use_c = TRUE THEN
- v_lo := v_lo + c_w;
- END IF;
- IF use_d = TRUE THEN
- v_lo := v_lo + d_w;
- END IF;
- IF use_e = TRUE THEN
- v_lo := v_lo + e_w;
- END IF;
- WHEN 6 =>
- IF use_g = TRUE THEN
- v_w := g_w;
- ELSE
- RETURN c_slv0(g_w - 1 DOWNTO 0);
- END IF;
- IF use_a = TRUE THEN
- v_lo := v_lo + a_w;
- END IF;
- IF use_b = TRUE THEN
- v_lo := v_lo + b_w;
- END IF;
- IF use_c = TRUE THEN
- v_lo := v_lo + c_w;
- END IF;
- IF use_d = TRUE THEN
- v_lo := v_lo + d_w;
- END IF;
- IF use_e = TRUE THEN
- v_lo := v_lo + e_w;
- END IF;
- IF use_f = TRUE THEN
- v_lo := v_lo + f_w;
- END IF;
- WHEN OTHERS => REPORT "Unknown common_pkg func_slv_extract argument" SEVERITY FAILURE;
- END CASE;
- RETURN vec(v_w - 1 + v_lo DOWNTO v_lo); -- extracted slv
- END func_slv_extract;
-
- FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, 0, vec, sel);
- END func_slv_extract;
-
- FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN func_slv_extract(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, a_w, b_w, c_w, d_w, e_w, 0, 0, vec, sel);
- END func_slv_extract;
-
- FUNCTION func_slv_extract(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN func_slv_extract(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, a_w, b_w, c_w, d_w, 0, 0, 0, vec, sel);
- END func_slv_extract;
-
- FUNCTION func_slv_extract(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN func_slv_extract(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, a_w, b_w, c_w, 0, 0, 0, 0, vec, sel);
- END func_slv_extract;
-
- FUNCTION func_slv_extract(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN func_slv_extract(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, a_w, b_w, 0, 0, 0, 0, 0, vec, sel);
- END func_slv_extract;
-
- FUNCTION TO_UINT(vec : STD_LOGIC_VECTOR) RETURN NATURAL IS
- BEGIN
- RETURN TO_INTEGER(UNSIGNED(vec));
- END;
-
- FUNCTION TO_SINT(vec : STD_LOGIC_VECTOR) RETURN INTEGER IS
- BEGIN
- RETURN TO_INTEGER(SIGNED(vec));
- END;
-
- FUNCTION TO_UVEC(dec, w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN STD_LOGIC_VECTOR(TO_UNSIGNED(dec, w));
- END;
-
- FUNCTION TO_SVEC(dec, w : INTEGER) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN STD_LOGIC_VECTOR(TO_SIGNED(dec, w));
- END;
-
- FUNCTION TO_SVEC_32(dec : INTEGER) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN TO_SVEC(dec, 32);
- END;
-
- FUNCTION RESIZE_NUM(u : UNSIGNED; w : NATURAL) RETURN UNSIGNED IS
- BEGIN
- -- left extend with '0' or keep LS part (same as RESIZE for UNSIGNED)
- RETURN RESIZE(u, w);
- END;
-
- FUNCTION RESIZE_NUM(s : SIGNED; w : NATURAL) RETURN SIGNED IS
- BEGIN
- -- left extend with sign bit or keep sign bit and LS part (same as RESIZE for SIGNED)
- -- If w < s'LENGTH then assume caller ensures that the actual s values
- -- will still fit in the w bits. Otherwise the result will wrap and
- -- there is nothing more that this RESIZE_NUM() can improve compared
- -- to RESIZE().
- RETURN RESIZE(s, w);
- END;
-
- FUNCTION RESIZE_UVEC(sl : STD_LOGIC; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_slv0 : STD_LOGIC_VECTOR(w - 1 DOWNTO 1) := (OTHERS => '0');
- BEGIN
- RETURN v_slv0 & sl;
- END;
-
- FUNCTION RESIZE_UVEC(vec : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN STD_LOGIC_VECTOR(RESIZE_NUM(UNSIGNED(vec), w));
- END;
-
- FUNCTION RESIZE_SVEC(vec : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN STD_LOGIC_VECTOR(RESIZE_NUM(SIGNED(vec), w));
- END;
-
- FUNCTION RESIZE_UINT(u : INTEGER; w : NATURAL) RETURN INTEGER IS
- VARIABLE v : STD_LOGIC_VECTOR(c_word_w - 1 DOWNTO 0);
- BEGIN
- v := TO_UVEC(u, c_word_w);
- RETURN TO_UINT(v(w - 1 DOWNTO 0));
- END;
-
- FUNCTION RESIZE_SINT(s : INTEGER; w : NATURAL) RETURN INTEGER IS
- VARIABLE v : STD_LOGIC_VECTOR(c_word_w - 1 DOWNTO 0);
- BEGIN
- v := TO_SVEC(s, c_word_w);
- RETURN TO_SINT(v(w - 1 DOWNTO 0));
- END;
-
- FUNCTION RESIZE_UVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN RESIZE_UVEC(vec, 32);
- END;
-
- FUNCTION RESIZE_SVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN RESIZE_SVEC(vec, 32);
- END;
-
- FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_dec : INTEGER;
- BEGIN
- IF dec < 0 THEN
- v_dec := -dec;
- RETURN STD_LOGIC_VECTOR(UNSIGNED(vec) - v_dec); -- uses function "-" (L : UNSIGNED, R : NATURAL), there is no function + with R : INTEGER argument
- ELSE
- v_dec := dec;
- RETURN STD_LOGIC_VECTOR(UNSIGNED(vec) + v_dec); -- uses function "+" (L : UNSIGNED, R : NATURAL)
- END IF;
- END;
-
- FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : UNSIGNED) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN STD_LOGIC_VECTOR(UNSIGNED(vec) + dec);
- END;
-
- FUNCTION INCR_SVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_dec : INTEGER;
- BEGIN
- RETURN STD_LOGIC_VECTOR(SIGNED(vec) + v_dec); -- uses function "+" (L : SIGNED, R : INTEGER)
- END;
-
- FUNCTION INCR_SVEC(vec : STD_LOGIC_VECTOR; dec : SIGNED) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN STD_LOGIC_VECTOR(SIGNED(vec) + dec);
- END;
-
- FUNCTION ADD_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN STD_LOGIC_VECTOR(RESIZE_NUM(SIGNED(l_vec), res_w) + SIGNED(r_vec));
- END;
-
- FUNCTION SUB_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN STD_LOGIC_VECTOR(RESIZE_NUM(SIGNED(l_vec), res_w) - SIGNED(r_vec));
- END;
-
- FUNCTION ADD_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN STD_LOGIC_VECTOR(RESIZE_NUM(UNSIGNED(l_vec), res_w) + UNSIGNED(r_vec));
- END;
-
- FUNCTION SUB_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN STD_LOGIC_VECTOR(RESIZE_NUM(UNSIGNED(l_vec), res_w) - UNSIGNED(r_vec));
- END;
-
- FUNCTION ADD_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN ADD_SVEC(l_vec, r_vec, l_vec'LENGTH);
- END;
-
- FUNCTION SUB_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN SUB_SVEC(l_vec, r_vec, l_vec'LENGTH);
- END;
-
- FUNCTION ADD_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN ADD_UVEC(l_vec, r_vec, l_vec'LENGTH);
- END;
-
- FUNCTION SUB_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN SUB_UVEC(l_vec, r_vec, l_vec'LENGTH);
- END;
-
- FUNCTION COMPLEX_MULT_REAL(a_re, a_im, b_re, b_im : INTEGER) RETURN INTEGER IS
- BEGIN
- RETURN (a_re * b_re - a_im * b_im);
- END;
-
- FUNCTION COMPLEX_MULT_IMAG(a_re, a_im, b_re, b_im : INTEGER) RETURN INTEGER IS
- BEGIN
- RETURN (a_im * b_re + a_re * b_im);
- END;
-
- FUNCTION S_ADD_OVFLW_DET(a, b, sum_a_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC is
- VARIABLE a_sign : SIGNED(a'RANGE) := SIGNED(a);
- VARIABLE b_sign : SIGNED(a'RANGE) := SIGNED(b);
- VARIABLE sum_a_b_sign : SIGNED(sum_a_b'RANGE) := SIGNED(sum_a_b);
- BEGIN
- IF (a_sign >= 0 xor b_sign >= 0) THEN
- RETURN '0'; -- no overflow from addition can occur when signed values have different signs
- ELSIF (sum_a_b_sign >= 0 xor a_sign >= 0) THEN -- signs are same so use either a_sign|b_sign
- RETURN '1'; -- overflow has occured - note sum wrapped to a different sign than inputs
- ELSE
- RETURN '0';
- END IF;
- END;
-
- FUNCTION S_SUB_OVFLW_DET(a, b, sub_a_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC is
- VARIABLE a_sign : SIGNED(a'RANGE) := SIGNED(a);
- VARIABLE b_sign : SIGNED(a'RANGE) := SIGNED(b);
- VARIABLE sub_a_b_sign: SIGNED(sub_a_b'RANGE) := SIGNED(sub_a_b);
- BEGIN
- IF not (a_sign >= 0 xor b_sign >= 0) THEN
- RETURN '0'; -- no overflow from subtraction can occur when signed values have same signs
- ELSIF not (sub_a_b_sign >= 0 xor b_sign >= 0) THEN
- RETURN '1'; -- overflow occurs if the result has the same sign as the subtrahend
- ELSE
- RETURN '0';
- END IF;
- END;
-
- FUNCTION SHIFT_UVEC(vec : STD_LOGIC_VECTOR; shift : INTEGER) RETURN STD_LOGIC_VECTOR is
- BEGIN
- IF shift < 0 THEN
- RETURN STD_LOGIC_VECTOR(SHIFT_LEFT(UNSIGNED(vec), -shift)); -- fill zeros from right
- ELSE
- RETURN STD_LOGIC_VECTOR(SHIFT_RIGHT(UNSIGNED(vec), shift)); -- fill zeros from left
- END IF;
- END;
-
- FUNCTION SHIFT_SVEC(vec : STD_LOGIC_VECTOR; shift : INTEGER) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- IF shift < 0 THEN
- RETURN STD_LOGIC_VECTOR(SHIFT_LEFT(SIGNED(vec), -shift)); -- same as SHIFT_LEFT for UNSIGNED
- ELSE
- RETURN STD_LOGIC_VECTOR(SHIFT_RIGHT(SIGNED(vec), shift)); -- extend sign
- END IF;
- END;
-
- --
- -- offset_binary() : maps offset binary to or from two-complement binary.
- --
- -- National ADC08DC1020 offset binary two-complement binary
- -- + full scale = 127.5 : 11111111 = 255 127 = 01111111
- -- ...
- -- + = +0.5 : 10000000 = 128 0 = 00000000
- -- 0
- -- - = -0.5 : 01111111 = 127 -1 = 11111111
- -- ...
- -- - full scale = -127.5 : 00000000 = 0 -128 = 10000000
- --
- -- To map between the offset binary and two complement binary involves
- -- adding 128 to the binary value or equivalently inverting the sign bit.
- -- The offset_binary() mapping can be done and undone both ways.
- -- The offset_binary() mapping to two-complement binary yields a DC offset
- -- of -0.5 Lsb.
- FUNCTION offset_binary(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_res : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0) := a;
- BEGIN
- v_res(v_res'HIGH) := NOT v_res(v_res'HIGH); -- invert MSbit to get to from offset binary to two's complement, or vice versa
- RETURN v_res;
- END;
-
- FUNCTION truncate(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR IS
- CONSTANT c_vec_w : NATURAL := vec'LENGTH;
- CONSTANT c_trunc_w : NATURAL := c_vec_w - n;
- VARIABLE v_vec : STD_LOGIC_VECTOR(c_vec_w - 1 DOWNTO 0) := vec;
- VARIABLE v_res : STD_LOGIC_VECTOR(c_trunc_w - 1 DOWNTO 0);
- BEGIN
- v_res := v_vec(c_vec_w - 1 DOWNTO n); -- keep MS part
- RETURN v_res;
- END;
-
- FUNCTION truncate_and_resize_uvec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- CONSTANT c_vec_w : NATURAL := vec'LENGTH;
- CONSTANT c_trunc_w : NATURAL := c_vec_w - n;
- VARIABLE v_trunc : STD_LOGIC_VECTOR(c_trunc_w - 1 DOWNTO 0);
- VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
- BEGIN
- v_trunc := truncate(vec, n); -- first keep MS part
- v_res := RESIZE_UVEC(v_trunc, w); -- then keep LS part or left extend with '0'
- RETURN v_res;
- END;
-
- FUNCTION truncate_and_resize_svec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- CONSTANT c_vec_w : NATURAL := vec'LENGTH;
- CONSTANT c_trunc_w : NATURAL := c_vec_w - n;
- VARIABLE v_trunc : STD_LOGIC_VECTOR(c_trunc_w - 1 DOWNTO 0);
- VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
- BEGIN
- v_trunc := truncate(vec, n); -- first keep MS part
- v_res := RESIZE_SVEC(v_trunc, w); -- then keep sign bit and LS part or left extend sign bit
- RETURN v_res;
- END;
-
- FUNCTION scale(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR IS
- CONSTANT c_vec_w : NATURAL := vec'LENGTH;
- CONSTANT c_scale_w : NATURAL := c_vec_w + n;
- VARIABLE v_res : STD_LOGIC_VECTOR(c_scale_w - 1 DOWNTO 0) := (OTHERS => '0');
- BEGIN
- v_res(c_scale_w - 1 DOWNTO n) := vec; -- scale by adding n zero bits at the right
- RETURN v_res;
- END;
-
- FUNCTION scale_and_resize_uvec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- CONSTANT c_vec_w : NATURAL := vec'LENGTH;
- CONSTANT c_scale_w : NATURAL := c_vec_w + n;
- VARIABLE v_scale : STD_LOGIC_VECTOR(c_scale_w - 1 DOWNTO 0) := (OTHERS => '0');
- VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
- BEGIN
- v_scale(c_scale_w - 1 DOWNTO n) := vec; -- first scale by adding n zero bits at the right
- v_res := RESIZE_UVEC(v_scale, w); -- then keep LS part or left extend with '0'
- RETURN v_res;
- END;
-
- FUNCTION scale_and_resize_svec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- CONSTANT c_vec_w : NATURAL := vec'LENGTH;
- CONSTANT c_scale_w : NATURAL := c_vec_w + n;
- VARIABLE v_scale : STD_LOGIC_VECTOR(c_scale_w - 1 DOWNTO 0) := (OTHERS => '0');
- VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
- BEGIN
- v_scale(c_scale_w - 1 DOWNTO n) := vec; -- first scale by adding n zero bits at the right
- v_res := RESIZE_SVEC(v_scale, w); -- then keep LS part or left extend sign bit
- RETURN v_res;
- END;
-
- FUNCTION truncate_or_resize_uvec(vec : STD_LOGIC_VECTOR; b : BOOLEAN; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- CONSTANT c_vec_w : NATURAL := vec'LENGTH;
- VARIABLE c_n : INTEGER := c_vec_w - w;
- VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
- BEGIN
- IF b = TRUE AND c_n > 0 THEN
- v_res := truncate_and_resize_uvec(vec, c_n, w);
- ELSE
- v_res := RESIZE_UVEC(vec, w);
- END IF;
- RETURN v_res;
- END;
-
- FUNCTION truncate_or_resize_svec(vec : STD_LOGIC_VECTOR; b : BOOLEAN; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
- CONSTANT c_vec_w : NATURAL := vec'LENGTH;
- VARIABLE c_n : INTEGER := c_vec_w - w;
- VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
- BEGIN
- IF b = TRUE AND c_n > 0 THEN
- v_res := truncate_and_resize_svec(vec, c_n, w);
- ELSE
- v_res := RESIZE_SVEC(vec, w);
- END IF;
- RETURN v_res;
- END;
-
- -- Functions s_round, s_round_up and u_round:
- --
- -- . The returned output width is input width - n.
- -- . If n=0 then the return value is the same as the input value so only
- -- wires (NOP, no operation).
- -- . Both have the same implementation but different c_max and c_clip values.
- -- . Round up for unsigned so +2.5 becomes 3
- -- . Round away from zero for signed so round up for positive and round down for negative, so +2.5 becomes 3 and -2.5 becomes -3.
- -- . Round away from zero is also used by round() in Matlab, Python, TCL
- -- . Rounding up implies adding 0.5 and then truncation, use clip = TRUE to
- -- clip the potential overflow due to adding 0.5 to +max.
- -- . For negative values overflow due to rounding can not occur, because c_half-1 >= 0 for n>0
- -- . If the input comes from a product and is rounded to the input width then
- -- clip can safely be FALSE, because e.g. for unsigned 4b*4b=8b->4b the
- -- maximum product is 15*15=225 <= 255-8, and for signed 4b*4b=8b->4b the
- -- maximum product is -8*-8=+64 <= 127-8, so wrapping due to rounding
- -- overflow will never occur.
-
- FUNCTION s_round(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR IS
- -- Use SIGNED to avoid NATURAL (32 bit range) overflow error
- CONSTANT c_in_w : NATURAL := vec'LENGTH;
- CONSTANT c_out_w : NATURAL := vec'LENGTH - n;
- CONSTANT c_one : SIGNED(c_in_w - 1 DOWNTO 0) := TO_SIGNED(1, c_in_w);
- CONSTANT c_half : SIGNED(c_in_w - 1 DOWNTO 0) := SHIFT_LEFT(c_one, n - 1); -- = 2**(n-1)
- CONSTANT c_max : SIGNED(c_in_w - 1 DOWNTO 0) := SIGNED('0' & c_slv1(c_in_w - 2 DOWNTO 0)) - c_half; -- = 2**(c_in_w-1)-1 - c_half
- CONSTANT c_clip : SIGNED(c_out_w - 1 DOWNTO 0) := SIGNED('0' & c_slv1(c_out_w - 2 DOWNTO 0)); -- = 2**(c_out_w-1)-1
- VARIABLE v_in : SIGNED(c_in_w - 1 DOWNTO 0);
- VARIABLE v_out : SIGNED(c_out_w - 1 DOWNTO 0);
- BEGIN
- v_in := SIGNED(vec);
- IF n > 0 THEN
- IF clip = TRUE AND v_in > c_max THEN
- v_out := c_clip; -- Round clip to maximum positive to avoid wrap to negative
- ELSE
- IF vec(vec'HIGH) = '0' THEN
- v_out := RESIZE_NUM(SHIFT_RIGHT(v_in + c_half + 0, n), c_out_w); -- Round up for positive
- ELSE
- v_out := RESIZE_NUM(SHIFT_RIGHT(v_in + c_half - 1, n), c_out_w); -- Round down for negative
- END IF;
- END IF;
- ELSE
- v_out := RESIZE_NUM(v_in, c_out_w); -- NOP
- END IF;
- RETURN STD_LOGIC_VECTOR(v_out);
- END;
-
- FUNCTION s_round(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN s_round(vec, n, FALSE); -- no round clip
- END;
-
- -- An alternative is to always round up, also for negative numbers (i.e. s_round_up = u_round).
- FUNCTION s_round_up(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN u_round(vec, n, clip);
- END;
-
- FUNCTION s_round_up(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN u_round(vec, n, FALSE); -- no round clip
- END;
-
- -- Unsigned numbers are round up (almost same as s_round, but without the else on negative vec)
- FUNCTION u_round(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR IS
- -- Use UNSIGNED to avoid NATURAL (32 bit range) overflow error
- CONSTANT c_in_w : NATURAL := vec'LENGTH;
- CONSTANT c_out_w : NATURAL := vec'LENGTH - n;
- CONSTANT c_one : UNSIGNED(c_in_w - 1 DOWNTO 0) := TO_UNSIGNED(1, c_in_w);
- CONSTANT c_half : UNSIGNED(c_in_w - 1 DOWNTO 0) := SHIFT_LEFT(c_one, n - 1); -- = 2**(n-1)
- CONSTANT c_max : UNSIGNED(c_in_w - 1 DOWNTO 0) := UNSIGNED(c_slv1(c_in_w - 1 DOWNTO 0)) - c_half; -- = 2**c_in_w-1 - c_half
- CONSTANT c_clip : UNSIGNED(c_out_w - 1 DOWNTO 0) := UNSIGNED(c_slv1(c_out_w - 1 DOWNTO 0)); -- = 2**c_out_w-1
- VARIABLE v_in : UNSIGNED(c_in_w - 1 DOWNTO 0);
- VARIABLE v_out : UNSIGNED(c_out_w - 1 DOWNTO 0);
- BEGIN
- v_in := UNSIGNED(vec);
- IF n > 0 THEN
- IF clip = TRUE AND v_in > c_max THEN
- v_out := c_clip; -- Round clip to +max to avoid wrap to 0
- ELSE
- v_out := RESIZE_NUM(SHIFT_RIGHT(v_in + c_half, n), c_out_w); -- Round up
- END IF;
- ELSE
- v_out := RESIZE_NUM(v_in, c_out_w); -- NOP
- END IF;
- RETURN STD_LOGIC_VECTOR(v_out);
- END;
-
- FUNCTION u_round(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN u_round(vec, n, FALSE); -- no round clip
- END;
-
- FUNCTION u_to_s(u : NATURAL; w : NATURAL) RETURN INTEGER IS
- VARIABLE v_u : STD_LOGIC_VECTOR(31 DOWNTO 0) := TO_UVEC(u, 32); -- via 32 bit word to avoid NUMERIC_STD.TO_SIGNED: vector truncated warming
- BEGIN
- RETURN TO_SINT(v_u(w - 1 DOWNTO 0));
- END;
-
- FUNCTION s_to_u(s : INTEGER; w : NATURAL) RETURN NATURAL IS
- VARIABLE v_s : STD_LOGIC_VECTOR(31 DOWNTO 0) := TO_SVEC(s, 32); -- via 32 bit word to avoid NUMERIC_STD.TO_SIGNED: vector truncated warming
- BEGIN
- RETURN TO_UINT(v_s(w - 1 DOWNTO 0));
- END;
-
- FUNCTION u_wrap(u : NATURAL; w : NATURAL) RETURN NATURAL IS
- VARIABLE v_u : STD_LOGIC_VECTOR(31 DOWNTO 0) := TO_UVEC(u, 32); -- via 32 bit word to avoid NUMERIC_STD.TO_SIGNED: vector truncated warming
- BEGIN
- RETURN TO_UINT(v_u(w - 1 DOWNTO 0));
- END;
-
- FUNCTION s_wrap(s : INTEGER; w : NATURAL) RETURN INTEGER IS
- VARIABLE v_s : STD_LOGIC_VECTOR(31 DOWNTO 0) := TO_SVEC(s, 32); -- via 32 bit word to avoid NUMERIC_STD.TO_SIGNED: vector truncated warming
- BEGIN
- RETURN TO_SINT(v_s(w - 1 DOWNTO 0));
- END;
-
- FUNCTION u_clip(u : NATURAL; max : NATURAL) RETURN NATURAL IS
- BEGIN
- IF u > max THEN
- RETURN max;
- ELSE
- RETURN u;
- END IF;
- END;
-
- FUNCTION s_clip(s : INTEGER; max : NATURAL; min : INTEGER) RETURN INTEGER IS
- BEGIN
- IF s < min THEN
- RETURN min;
- ELSE
- IF s > max THEN
- RETURN max;
- ELSE
- RETURN s;
- END IF;
- END IF;
- END;
-
- FUNCTION s_clip(s : INTEGER; max : NATURAL) RETURN INTEGER IS
- BEGIN
- RETURN s_clip(s, max, -max);
- END;
-
- FUNCTION hton(a : STD_LOGIC_VECTOR; w, sz : NATURAL) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_a : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0) := a; -- map a to range [h:0]
- VARIABLE v_b : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0) := a; -- default b = a
- VARIABLE vL : NATURAL;
- VARIABLE vK : NATURAL;
- BEGIN
- -- Note:
- -- . if sz = 1 then v_b = v_a
- -- . if a'LENGTH > sz*w then v_b(a'LENGTH:sz*w) = v_a(a'LENGTH:sz*w)
- FOR vL IN 0 TO sz - 1 LOOP
- vK := sz - 1 - vL;
- v_b((vL + 1) * w - 1 DOWNTO vL * w) := v_a((vK + 1) * w - 1 DOWNTO vK * w);
- END LOOP;
- RETURN v_b;
- END FUNCTION;
-
- FUNCTION hton(a : STD_LOGIC_VECTOR; sz : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN hton(a, c_byte_w, sz); -- symbol width w = c_byte_w = 8
- END FUNCTION;
-
- FUNCTION hton(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- CONSTANT c_sz : NATURAL := a'LENGTH / c_byte_w;
- BEGIN
- RETURN hton(a, c_byte_w, c_sz); -- symbol width w = c_byte_w = 8
- END FUNCTION;
-
- FUNCTION ntoh(a : STD_LOGIC_VECTOR; sz : NATURAL) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN hton(a, sz); -- i.e. ntoh() = hton()
- END FUNCTION;
-
- FUNCTION ntoh(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- BEGIN
- RETURN hton(a); -- i.e. ntoh() = hton()
- END FUNCTION;
-
- FUNCTION flip(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_a : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0) := a;
- VARIABLE v_b : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0);
- BEGIN
- FOR I IN v_a'RANGE LOOP
- v_b(a'LENGTH - 1 - I) := v_a(I);
- END LOOP;
- RETURN v_b;
- END;
-
- FUNCTION flip(a, w : NATURAL) RETURN NATURAL IS
- BEGIN
- RETURN TO_UINT(flip(TO_UVEC(a, w)));
- END;
-
- FUNCTION flip(a : t_slv_32_arr) RETURN t_slv_32_arr IS
- VARIABLE v_a : t_slv_32_arr(a'LENGTH - 1 DOWNTO 0) := a;
- VARIABLE v_b : t_slv_32_arr(a'LENGTH - 1 DOWNTO 0);
- BEGIN
- FOR I IN v_a'RANGE LOOP
- v_b(a'LENGTH - 1 - I) := v_a(I);
- END LOOP;
- RETURN v_b;
- END;
-
- FUNCTION flip(a : t_integer_arr) RETURN t_integer_arr IS
- VARIABLE v_a : t_integer_arr(a'LENGTH - 1 DOWNTO 0) := a;
- VARIABLE v_b : t_integer_arr(a'LENGTH - 1 DOWNTO 0);
- BEGIN
- FOR I IN v_a'RANGE LOOP
- v_b(a'LENGTH - 1 - I) := v_a(I);
- END LOOP;
- RETURN v_b;
- END;
-
- FUNCTION flip(a : t_natural_arr) RETURN t_natural_arr IS
- VARIABLE v_a : t_natural_arr(a'LENGTH - 1 DOWNTO 0) := a;
- VARIABLE v_b : t_natural_arr(a'LENGTH - 1 DOWNTO 0);
- BEGIN
- FOR I IN v_a'RANGE LOOP
- v_b(a'LENGTH - 1 - I) := v_a(I);
- END LOOP;
- RETURN v_b;
- END;
-
- FUNCTION flip(a : t_nat_natural_arr) RETURN t_nat_natural_arr IS
- VARIABLE v_a : t_nat_natural_arr(a'LENGTH - 1 DOWNTO 0) := a;
- VARIABLE v_b : t_nat_natural_arr(a'LENGTH - 1 DOWNTO 0);
- BEGIN
- FOR I IN v_a'RANGE LOOP
- v_b(a'LENGTH - 1 - I) := v_a(I);
- END LOOP;
- RETURN v_b;
- END;
-
- FUNCTION transpose(a : STD_LOGIC_VECTOR; row, col : NATURAL) RETURN STD_LOGIC_VECTOR IS
- VARIABLE vIn : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0);
- VARIABLE vOut : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0);
- BEGIN
- vIn := a; -- map input vector to h:0 range
- vOut := vIn; -- default leave any unused MSbits the same
- FOR J IN 0 TO row - 1 LOOP
- FOR I IN 0 TO col - 1 LOOP
- vOut(J * col + I) := vIn(I * row + J); -- transpose vector, map input index [i*row+j] to output index [j*col+i]
- END LOOP;
- END LOOP;
- RETURN vOut;
- END FUNCTION;
-
- FUNCTION transpose(a, row, col : NATURAL) RETURN NATURAL IS -- transpose index a = [i*row+j] to output index [j*col+i]
- VARIABLE vI : NATURAL;
- VARIABLE vJ : NATURAL;
- BEGIN
- vI := a / row;
- vJ := a MOD row;
- RETURN vJ * col + vI;
- END;
-
- FUNCTION split_w(input_w : NATURAL; min_out_w : NATURAL; max_out_w : NATURAL) RETURN NATURAL IS -- Calculate input_w in multiples as close as possible to max_out_w
- -- Examples: split_w(256, 8, 32) = 32; split_w(16, 8, 32) = 16; split_w(72, 8, 32) = 18; -- Input_w must be multiple of 2.
- VARIABLE r : NATURAL;
- BEGIN
- r := input_w;
- FOR i IN 1 TO ceil_log2(input_w) LOOP -- Useless to divide the number beyond this
- IF r <= max_out_w AND r >= min_out_w THEN
- RETURN r;
- ELSIF i = ceil_log2(input_w) THEN -- last iteration
- RETURN 0; -- Indicates wrong values were used
- END IF;
- r := r / 2;
- END LOOP;
- END;
-
- FUNCTION pad(str : STRING; width : NATURAL; pad_char : CHARACTER) RETURN STRING IS
- VARIABLE v_str : STRING(1 TO width) := (OTHERS => pad_char);
- BEGIN
- v_str(width - str'LENGTH + 1 TO width) := str;
- RETURN v_str;
- END;
-
- FUNCTION slice_up(str : STRING; width : NATURAL; i : NATURAL) RETURN STRING IS
- BEGIN
- RETURN str(i * width + 1 TO (i + 1) * width);
- END;
-
- -- If the input value is not a multiple of the desired width, the return value is padded with
- -- the passed pad value. E.g. if input='10' and desired width is 4, return value is '0010'.
- FUNCTION slice_up(str : STRING; width : NATURAL; i : NATURAL; pad_char : CHARACTER) RETURN STRING IS
- VARIABLE padded_str : STRING(1 TO width) := (OTHERS => '0');
- BEGIN
- padded_str := pad(str(i * width + 1 TO (i + 1) * width), width, '0');
- RETURN padded_str;
- END;
-
- FUNCTION slice_dn(str : STRING; width : NATURAL; i : NATURAL) RETURN STRING IS
- BEGIN
- RETURN str((i + 1) * width - 1 DOWNTO i * width);
- END;
-
- FUNCTION nat_arr_to_concat_slv(nat_arr : t_natural_arr; nof_elements : NATURAL) RETURN STD_LOGIC_VECTOR IS
- VARIABLE v_concat_slv : STD_LOGIC_VECTOR(nof_elements * 32 - 1 DOWNTO 0) := (OTHERS => '0');
- BEGIN
- FOR i IN 0 TO nof_elements - 1 LOOP
- v_concat_slv(i * 32 + 32 - 1 DOWNTO i * 32) := TO_UVEC(nat_arr(i), 32);
- END LOOP;
- RETURN v_concat_slv;
- END;
-
- ------------------------------------------------------------------------------
- -- common_fifo_*
- ------------------------------------------------------------------------------
-
- PROCEDURE proc_common_fifo_asserts(CONSTANT c_fifo_name : IN STRING;
- CONSTANT c_note_is_ful : IN BOOLEAN;
- CONSTANT c_fail_rd_emp : IN BOOLEAN;
- SIGNAL wr_rst : IN STD_LOGIC;
- SIGNAL wr_clk : IN STD_LOGIC;
- SIGNAL wr_full : IN STD_LOGIC;
- SIGNAL wr_en : IN STD_LOGIC;
- SIGNAL rd_clk : IN STD_LOGIC;
- SIGNAL rd_empty : IN STD_LOGIC;
- SIGNAL rd_en : IN STD_LOGIC) IS
- BEGIN
- -- c_fail_rd_emp : when TRUE report FAILURE when read from an empty FIFO, important when FIFO rd_val is not used
- -- c_note_is_ful : when TRUE report NOTE when FIFO goes full, to note that operation is on the limit
- -- FIFO overflow is always reported as FAILURE
-
- -- The FIFO wr_full goes high at reset to indicate that it can not be written and it goes low a few cycles after reset.
- -- Therefore only check on wr_full going high when wr_rst='0'.
-
- --synthesis translate_off
- ASSERT NOT (c_fail_rd_emp = TRUE AND rising_edge(rd_clk) AND rd_empty = '1' AND rd_en = '1') REPORT c_fifo_name & " : read from empty fifo occurred!" SEVERITY FAILURE;
- ASSERT NOT (c_note_is_ful = TRUE AND rising_edge(wr_full) AND wr_rst = '0') REPORT c_fifo_name & " : fifo is full now" SEVERITY NOTE;
- ASSERT NOT (rising_edge(wr_clk) AND wr_full = '1' AND wr_en = '1') REPORT c_fifo_name & " : fifo overflow occurred!" SEVERITY FAILURE;
- --synthesis translate_on
- END PROCEDURE proc_common_fifo_asserts;
-
- ------------------------------------------------------------------------------
- -- common_fanout_tree
- ------------------------------------------------------------------------------
-
- FUNCTION func_common_fanout_tree_pipelining(c_nof_stages, c_nof_output_per_cell, c_nof_output : NATURAL;
- c_cell_pipeline_factor_arr, c_cell_pipeline_arr : t_natural_arr) RETURN t_natural_arr IS
- CONSTANT k_cell_pipeline_factor_arr : t_natural_arr(c_nof_stages - 1 DOWNTO 0) := c_cell_pipeline_factor_arr;
- CONSTANT k_cell_pipeline_arr : t_natural_arr(c_nof_output_per_cell - 1 DOWNTO 0) := c_cell_pipeline_arr;
- VARIABLE v_stage_pipeline_arr : t_natural_arr(c_nof_output - 1 DOWNTO 0) := (OTHERS => 0);
- VARIABLE v_prev_stage_pipeline_arr : t_natural_arr(c_nof_output - 1 DOWNTO 0) := (OTHERS => 0);
- BEGIN
- loop_stage : FOR j IN 0 TO c_nof_stages - 1 LOOP
- v_prev_stage_pipeline_arr := v_stage_pipeline_arr;
- loop_cell : FOR i IN 0 TO c_nof_output_per_cell**j - 1 LOOP
- v_stage_pipeline_arr((i + 1) * c_nof_output_per_cell - 1 DOWNTO i * c_nof_output_per_cell) := v_prev_stage_pipeline_arr(i) + (k_cell_pipeline_factor_arr(j) * k_cell_pipeline_arr);
- END LOOP;
- END LOOP;
- RETURN v_stage_pipeline_arr;
- END FUNCTION func_common_fanout_tree_pipelining;
-
- ------------------------------------------------------------------------------
- -- common_reorder_symbol
- ------------------------------------------------------------------------------
-
- -- Determine whether the stage I and row J index refer to any (active or redundant) 2-input reorder cell instantiation
- FUNCTION func_common_reorder2_is_there(I, J : NATURAL) RETURN BOOLEAN IS
- VARIABLE v_odd : BOOLEAN;
- VARIABLE v_even : BOOLEAN;
- BEGIN
- v_odd := (I MOD 2 = 1) AND (J MOD 2 = 1); -- for odd stage at each odd row
- v_even := (I MOD 2 = 0) AND (J MOD 2 = 0); -- for even stage at each even row
- RETURN v_odd OR v_even;
- END func_common_reorder2_is_there;
-
- -- Determine whether the stage I and row J index refer to an active 2-input reorder cell instantiation in a reorder network with N stages
- FUNCTION func_common_reorder2_is_active(I, J, N : NATURAL) RETURN BOOLEAN IS
- VARIABLE v_inst : BOOLEAN;
- VARIABLE v_act : BOOLEAN;
- BEGIN
- v_inst := func_common_reorder2_is_there(I, J);
- v_act := (I > 0) AND (I <= N) AND (J > 0) AND (J < N);
- RETURN v_inst AND v_act;
- END func_common_reorder2_is_active;
-
- -- Get the index K in the select setting array for the reorder2 cell on stage I and row J in a reorder network with N stages
- FUNCTION func_common_reorder2_get_select_index(I, J, N : NATURAL) RETURN INTEGER IS
- CONSTANT c_nof_reorder2_per_odd_stage : NATURAL := N / 2;
- CONSTANT c_nof_reorder2_per_even_stage : NATURAL := (N - 1) / 2;
- VARIABLE v_nof_odd_stages : NATURAL;
- VARIABLE v_nof_even_stages : NATURAL;
- VARIABLE v_offset : NATURAL;
- VARIABLE v_K : INTEGER;
- BEGIN
- -- for I, J that do not refer to an reorder cell instance for -1 as dummy return value.
- -- for the redundant two port reorder cells at the border rows for -1 to indicate that the cell should pass on the input.
- v_K := -1;
- IF func_common_reorder2_is_active(I, J, N) THEN
- -- for the active two port reorder cells use the setting at index v_K from the select setting array
- v_nof_odd_stages := I / 2;
- v_nof_even_stages := (I - 1) / 2;
- v_offset := (J - 1) / 2; -- suits both odd stage and even stage
- v_K := v_nof_odd_stages * c_nof_reorder2_per_odd_stage + v_nof_even_stages * c_nof_reorder2_per_even_stage + v_offset;
- END IF;
- RETURN v_K;
- END func_common_reorder2_get_select_index;
-
- -- Get the select setting for the reorder2 cell on stage I and row J in a reorder network with N stages
- FUNCTION func_common_reorder2_get_select(I, J, N : NATURAL; select_arr : t_natural_arr) RETURN NATURAL IS
- CONSTANT c_nof_select : NATURAL := select_arr'LENGTH;
- CONSTANT c_select_arr : t_natural_arr(c_nof_select - 1 DOWNTO 0) := select_arr; -- force range downto 0
- VARIABLE v_sel : NATURAL;
- VARIABLE v_K : INTEGER;
- BEGIN
- v_sel := 0;
- v_K := func_common_reorder2_get_select_index(I, J, N);
- IF v_K >= 0 THEN
- v_sel := c_select_arr(v_K);
- END IF;
- RETURN v_sel;
- END func_common_reorder2_get_select;
-
- -- Determine the inverse of a reorder network by using two reorder networks in series
- FUNCTION func_common_reorder2_inverse_select(N : NATURAL; select_arr : t_natural_arr) RETURN t_natural_arr IS
- CONSTANT c_nof_select : NATURAL := select_arr'LENGTH;
- CONSTANT c_select_arr : t_natural_arr(c_nof_select - 1 DOWNTO 0) := select_arr; -- force range downto 0
- VARIABLE v_sel : NATURAL;
- VARIABLE v_Ki : INTEGER;
- VARIABLE v_Ii : NATURAL;
- VARIABLE v_inverse_arr : t_natural_arr(2 * c_nof_select - 1 DOWNTO 0) := (OTHERS => 0); -- default set identity for the reorder2 cells in both reorder instances
- BEGIN
- -- the inverse select consists of inverse_in reorder and inverse_out reorder in series
- IF N MOD 2 = 1 THEN
- -- N is odd so only need to fill in the inverse_in reorder, the inverse_out reorder remains at default pass on
- FOR I IN 1 TO N LOOP
- FOR J IN 0 TO N - 1 LOOP
- -- get the DUT setting
- v_sel := func_common_reorder2_get_select(I, J, N, c_select_arr);
- -- map DUT I to inverse v_Ii stage index and determine the index for the inverse setting
- v_Ii := 1 + N - I;
- v_Ki := func_common_reorder2_get_select_index(v_Ii, J, N);
- IF v_Ki >= 0 THEN
- v_inverse_arr(v_Ki) := v_sel;
- END IF;
- END LOOP;
- END LOOP;
- ELSE
- -- N is even so only use stage 1 of the inverse_out reorder, the other stages remain at default pass on
- FOR K IN 0 TO N / 2 - 1 LOOP
- v_Ki := c_nof_select + K; -- stage 1 of the inverse_out reorder
- v_inverse_arr(v_Ki) := c_select_arr(K);
- END LOOP;
- -- N is even so leave stage 1 of the inverse_in reorder at default pass on, and do inverse the other stages
- FOR I IN 2 TO N LOOP
- FOR J IN 0 TO N - 1 LOOP
- -- get the DUT setting
- v_sel := func_common_reorder2_get_select(I, J, N, c_select_arr);
- -- map DUT I to inverse v_Ii stage index and determine the index for the inverse setting
- v_Ii := 2 + N - I;
- v_Ki := func_common_reorder2_get_select_index(v_Ii, J, N);
- IF v_Ki >= 0 THEN
- v_inverse_arr(v_Ki) := v_sel;
- END IF;
- END LOOP;
- END LOOP;
- END IF;
- RETURN v_inverse_arr;
- END func_common_reorder2_inverse_select;
-
- ------------------------------------------------------------------------------
- -- PROCEDURE: Generate faster sample SCLK from digital DCLK for sim only
- -- Description:
- -- The SCLK kan be used to serialize Pfactor >= 1 symbols per word and then
- -- view them in a scope component that is use internally in the design.
- -- The scope component is only instantiated for simulation, to view the
- -- serialized symbols, typically with decimal radix and analogue format.
- -- The scope component will not be synthesized, because the SCLK can not
- -- be synthesized.
- --
- -- Pfactor = 4
- -- _______ _______ _______ _______
- -- DCLK ___| |_______| |_______| |_______| |_______
- -- ___________________ _ _ _ _ _ _ _ _ _ _ _ _
- -- SCLK |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_|
- --
- -- The rising edges of SCLK occur after the rising edge of DCLK, to ensure
- -- that they all apply to the same wide data word that was clocked by the
- -- rising edge of the DCLK.
- ------------------------------------------------------------------------------
- PROCEDURE proc_common_dclk_generate_sclk(CONSTANT Pfactor : IN POSITIVE;
- SIGNAL dclk : IN STD_LOGIC;
- SIGNAL sclk : INOUT STD_LOGIC) IS
- VARIABLE v_dperiod : TIME;
- VARIABLE v_speriod : TIME;
- BEGIN
- SCLK <= '1';
- -- Measure DCLK period
- WAIT UNTIL rising_edge(DCLK);
- v_dperiod := NOW;
- WAIT UNTIL rising_edge(DCLK);
- v_dperiod := NOW - v_dperiod;
- v_speriod := v_dperiod / Pfactor;
- -- Generate Pfactor SCLK periods per DCLK period
- WHILE TRUE LOOP
- -- Realign at every DCLK
- WAIT UNTIL rising_edge(DCLK);
- -- Create Pfactor SCLK periods within this DCLK period
- SCLK <= '0';
- IF Pfactor > 1 THEN
- FOR I IN 0 TO 2 * Pfactor - 1 - 2 LOOP
- WAIT FOR v_speriod / 2;
- SCLK <= NOT SCLK;
- END LOOP;
- END IF;
- WAIT FOR v_speriod / 2;
- SCLK <= '1';
- -- Wait for next DCLK
- END LOOP;
- WAIT;
- END proc_common_dclk_generate_sclk;
-
-END common_pkg;
+-------------------------------------------------------------------------------
+--
+-- Copyright 2020
+-- ASTRON (Netherlands Institute for Radio Astronomy)
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+
+-- Author:
+-- . Eric Kooistra
+-- . Talon Myburgh
+-- Purpose:
+-- . Collection of commonly used base funtions
+-- Interface:
+-- . [n/a]
+-- Description:
+-- . This is a package containing generic constants and functions.
+-- . More information can be found in the comments near the code.
+
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE IEEE.MATH_REAL.ALL;
+use work.common_fixed_float_types.all;
+use work.fixed_pkg.all;
+
+PACKAGE common_pkg IS
+
+ -- CONSTANT DECLARATIONS ----------------------------------------------------
+
+ -- some integers
+ CONSTANT c_0 : NATURAL := 0;
+ CONSTANT c_zero : NATURAL := 0;
+ CONSTANT c_1 : NATURAL := 1;
+ CONSTANT c_one : NATURAL := 1;
+ CONSTANT c_2 : NATURAL := 2;
+ CONSTANT c_4 : NATURAL := 4;
+ CONSTANT c_quad : NATURAL := 4;
+ CONSTANT c_8 : NATURAL := 8;
+ CONSTANT c_16 : NATURAL := 16;
+ CONSTANT c_32 : NATURAL := 32;
+ CONSTANT c_64 : NATURAL := 64;
+ CONSTANT c_128 : NATURAL := 128;
+ CONSTANT c_256 : NATURAL := 256;
+
+ -- widths and sizes
+ CONSTANT c_halfword_sz : NATURAL := 2;
+ CONSTANT c_word_sz : NATURAL := 4;
+ CONSTANT c_longword_sz : NATURAL := 8;
+ CONSTANT c_nibble_w : NATURAL := 4;
+ CONSTANT c_byte_w : NATURAL := 8;
+ CONSTANT c_octet_w : NATURAL := 8;
+ CONSTANT c_halfword_w : NATURAL := c_byte_w * c_halfword_sz;
+ CONSTANT c_word_w : NATURAL := c_byte_w * c_word_sz;
+ CONSTANT c_integer_w : NATURAL := 32; -- unfortunately VHDL integer type is limited to 32 bit values
+ CONSTANT c_natural_w : NATURAL := c_integer_w - 1; -- unfortunately VHDL natural type is limited to 31 bit values (0 and the positive subset of the VHDL integer type0
+ CONSTANT c_longword_w : NATURAL := c_byte_w * c_longword_sz;
+
+ -- logic
+ CONSTANT c_sl0 : STD_LOGIC := '0';
+ CONSTANT c_sl1 : STD_LOGIC := '1';
+ CONSTANT c_unsigned_0 : UNSIGNED(0 DOWNTO 0) := TO_UNSIGNED(0, 1);
+ CONSTANT c_unsigned_1 : UNSIGNED(0 DOWNTO 0) := TO_UNSIGNED(1, 1);
+ CONSTANT c_signed_0 : SIGNED(1 DOWNTO 0) := TO_SIGNED(0, 2);
+ CONSTANT c_signed_1 : SIGNED(1 DOWNTO 0) := TO_SIGNED(1, 2);
+ CONSTANT c_slv0 : STD_LOGIC_VECTOR(255 DOWNTO 0) := (OTHERS => '0');
+ CONSTANT c_slv1 : STD_LOGIC_VECTOR(255 DOWNTO 0) := (OTHERS => '1');
+ CONSTANT c_word_01 : STD_LOGIC_VECTOR(31 DOWNTO 0) := "01010101010101010101010101010101";
+ CONSTANT c_word_10 : STD_LOGIC_VECTOR(31 DOWNTO 0) := "10101010101010101010101010101010";
+ CONSTANT c_slv01 : STD_LOGIC_VECTOR(255 DOWNTO 0) := c_word_01 & c_word_01 & c_word_01 & c_word_01 & c_word_01 & c_word_01 & c_word_01 & c_word_01;
+ CONSTANT c_slv10 : STD_LOGIC_VECTOR(255 DOWNTO 0) := c_word_10 & c_word_10 & c_word_10 & c_word_10 & c_word_10 & c_word_10 & c_word_10 & c_word_10;
+
+ -- math
+ CONSTANT c_nof_complex : NATURAL := 2; -- Real and imaginary part of complex number
+ CONSTANT c_sign_w : NATURAL := 1; -- Sign bit, can be used to skip one of the double sign bits of a product
+ CONSTANT c_sum_of_prod_w : NATURAL := 1; -- Bit growth for sum of 2 products, can be used in case complex multiply has normalized real and imag inputs instead of normalized amplitude inputs
+
+ -- FF, block RAM, FIFO
+ CONSTANT c_meta_delay_len : NATURAL := 3; -- default nof flipflops (FF) in meta stability recovery delay line (e.g. for clock domain crossing)
+ CONSTANT c_meta_fifo_depth : NATURAL := 16; -- default use 16 word deep FIFO to cross clock domain, typically > 2*c_meta_delay_len or >~ 8 is enough
+
+ CONSTANT c_bram_m9k_nof_bits : NATURAL := 1024 * 9; -- size of 1 Altera M9K block RAM in bits
+ CONSTANT c_bram_m9k_max_w : NATURAL := 36; -- maximum width of 1 Altera M9K block RAM, so the size is then 256 words of 36 bits
+ CONSTANT c_bram_m9k_fifo_depth : NATURAL := c_bram_m9k_nof_bits / c_bram_m9k_max_w; -- using a smaller FIFO depth than this leaves part of the RAM unused
+
+ CONSTANT c_fifo_afull_margin : NATURAL := 4; -- default or minimal FIFO almost full margin
+
+ -- DSP
+ CONSTANT c_dsp_mult_w : NATURAL := 18; -- Width of the embedded multipliers in Stratix IV
+
+ -- TYPE DECLARATIONS --------------------------------------------------------
+ TYPE t_boolean_arr IS ARRAY (INTEGER RANGE <>) OF BOOLEAN; -- INTEGER left index starts default at -2**31
+ TYPE t_integer_arr IS ARRAY (INTEGER RANGE <>) OF INTEGER; -- INTEGER left index starts default at -2**31
+ TYPE t_natural_arr IS ARRAY (INTEGER RANGE <>) OF NATURAL; -- INTEGER left index starts default at -2**31
+ TYPE t_nat_boolean_arr IS ARRAY (NATURAL RANGE <>) OF BOOLEAN; -- NATURAL left index starts default at 0
+ TYPE t_nat_integer_arr IS ARRAY (NATURAL RANGE <>) OF INTEGER; -- NATURAL left index starts default at 0
+ TYPE t_nat_natural_arr IS ARRAY (NATURAL RANGE <>) OF NATURAL; -- NATURAL left index starts default at 0
+ TYPE t_sl_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC;
+ TYPE t_slv_1_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(0 DOWNTO 0);
+ TYPE t_slv_2_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(1 DOWNTO 0);
+ TYPE t_slv_4_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(3 DOWNTO 0);
+ TYPE t_slv_8_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
+ TYPE t_slv_12_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(11 DOWNTO 0);
+ TYPE t_slv_16_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(15 DOWNTO 0);
+ TYPE t_slv_18_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(17 DOWNTO 0);
+ TYPE t_slv_24_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(23 DOWNTO 0);
+ TYPE t_slv_32_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(31 DOWNTO 0);
+ TYPE t_slv_44_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(43 DOWNTO 0);
+ TYPE t_slv_48_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(47 DOWNTO 0);
+ TYPE t_signed_48_arr IS ARRAY (INTEGER RANGE <>) OF SIGNED(47 DOWNTO 0);
+ TYPE t_slv_64_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(63 DOWNTO 0);
+ TYPE t_signed_96_arr IS ARRAY (INTEGER RANGE <>) OF SIGNED(95 DOWNTO 0);
+ TYPE t_slv_128_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(127 DOWNTO 0);
+ TYPE t_slv_256_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(255 DOWNTO 0);
+ TYPE t_slv_512_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(511 DOWNTO 0);
+ TYPE t_slv_1024_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(1023 DOWNTO 0);
+ --type t_unsigned_array is array(natural range <>) of unsigned;
+ --type t_slv_array is array(natural range <>) of std_logic_vector;
+ --type t_signed_array is array(natural range <>) of signed;
+ TYPE t_rounding_mode is (TRUNCATE, ROUND, ROUNDINF);
+
+ CONSTANT c_boolean_arr : t_boolean_arr := (TRUE, FALSE); -- array all possible values that can be iterated over
+ CONSTANT c_nat_boolean_arr : t_nat_boolean_arr := (TRUE, FALSE); -- array all possible values that can be iterated over
+
+ TYPE t_natural_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF NATURAL;
+ TYPE t_integer_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF INTEGER;
+ TYPE t_nat_integer_matrix IS ARRAY (NATURAL RANGE <>, NATURAL RANGE <>) OF INTEGER;
+ TYPE t_boolean_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF BOOLEAN;
+ TYPE t_sl_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF STD_LOGIC;
+ TYPE t_slv_8_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
+ TYPE t_slv_16_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF STD_LOGIC_VECTOR(15 DOWNTO 0);
+ TYPE t_slv_32_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF STD_LOGIC_VECTOR(31 DOWNTO 0);
+ TYPE t_slv_64_matrix IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF STD_LOGIC_VECTOR(63 DOWNTO 0);
+
+ TYPE t_natural_2arr_2 IS ARRAY (INTEGER RANGE <>) OF t_natural_arr(1 DOWNTO 0);
+
+ -- STRUCTURE DECLARATIONS ---------------------------------------------------
+
+ -- Clock and Reset
+ --
+ -- . rst = Reset. Can be used asynchronously to take effect immediately
+ -- when used before the clk'EVENT section. May also be used as
+ -- synchronous reset using it as first condition in the clk'EVENT
+ -- section. As synchronous reset it requires clock activity to take
+ -- effect. A synchronous rst may or may not depend on clken,
+ -- however typically rst should take priority over clken.
+ -- . clk = Clock. Used in clk'EVENT line via rising_edge(clk) or sometimes
+ -- as falling_edge(clk).
+ -- . clken = Clock Enable. Used for the whole clk'EVENT section.
+ TYPE t_sys_rce IS RECORD
+ rst : STD_LOGIC;
+ clk : STD_LOGIC;
+ clken : STD_LOGIC; -- := '1';
+ END RECORD;
+
+ TYPE t_sys_ce IS RECORD
+ clk : STD_LOGIC;
+ clken : STD_LOGIC; -- := '1';
+ END RECORD;
+
+ -- FUNCTION DECLARATIONS ----------------------------------------------------
+
+ -- All functions assume [high downto low] input ranges
+
+ FUNCTION pow2(n : NATURAL) RETURN NATURAL; -- = 2**n
+ FUNCTION ceil_pow2(n : INTEGER) RETURN NATURAL; -- = 2**n, returns 1 for n<0
+
+ FUNCTION true_log2(n : NATURAL) RETURN NATURAL; -- true_log2(n) = log2(n)
+ FUNCTION ceil_log2(n : NATURAL) RETURN NATURAL; -- ceil_log2(n) = log2(n), but force ceil_log2(1) = 1
+ FUNCTION next_pow2(n : NATURAL) RETURN NATURAL; -- next_pow2(n) = next power of two that is >= n
+
+ FUNCTION floor_log10(n : NATURAL) RETURN NATURAL;
+
+ FUNCTION is_pow2(n : NATURAL) RETURN BOOLEAN; -- return TRUE when n is a power of 2, so 0, 1, 2, 4, 8, 16, ...
+ FUNCTION true_log_pow2(n : NATURAL) RETURN NATURAL; -- 2**true_log2(n), return power of 2 that is >= n
+
+ FUNCTION ratio(n, d : NATURAL) RETURN NATURAL; -- return n/d when n MOD d = 0 else return 0, so ratio * d = n only when integer ratio > 0
+ FUNCTION ratio2(n, m : NATURAL) RETURN NATURAL; -- return integer ratio of n/m or m/n, whichever is the largest
+
+ FUNCTION ceil_div(n, d : NATURAL) RETURN NATURAL; -- ceil_div = n/d + (n MOD d)/=0
+ FUNCTION ceil_value(n, d : NATURAL) RETURN NATURAL; -- ceil_value = ceil_div(n, d) * d
+ FUNCTION floor_value(n, d : NATURAL) RETURN NATURAL; -- floor_value = (n/d) * d
+ FUNCTION ceil_div(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED;
+ FUNCTION ceil_value(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED;
+ FUNCTION floor_value(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED;
+
+ FUNCTION slv(n : IN STD_LOGIC) RETURN STD_LOGIC_VECTOR; -- standard logic to 1 element standard logic vector
+ FUNCTION sl(n : IN STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- 1 element standard logic vector to standard logic
+
+ FUNCTION to_natural_arr(n : t_integer_arr; to_zero : BOOLEAN) RETURN t_natural_arr; -- if to_zero=TRUE then negative numbers are forced to zero, otherwise they will give a compile range error
+ FUNCTION to_natural_arr(n : t_nat_natural_arr) RETURN t_natural_arr;
+ FUNCTION to_integer_arr(n : t_natural_arr) RETURN t_integer_arr;
+ FUNCTION to_integer_arr(n : t_nat_natural_arr) RETURN t_integer_arr;
+ FUNCTION to_slv_32_arr(n : t_integer_arr) RETURN t_slv_32_arr;
+ FUNCTION to_slv_32_arr(n : t_natural_arr) RETURN t_slv_32_arr;
+
+ FUNCTION vector_tree(slv : STD_LOGIC_VECTOR; operation : STRING) RETURN STD_LOGIC; -- Core operation tree function for vector "AND", "OR", "XOR"
+ FUNCTION vector_and(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- '1' when all slv bits are '1' else '0'
+ FUNCTION vector_or(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- '0' when all slv bits are '0' else '1'
+ FUNCTION vector_xor(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- '1' when the slv has an odd number of '1' bits else '0'
+ FUNCTION vector_one_hot(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- Returns slv when it contains one hot bit, else returns 0.
+
+ FUNCTION andv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- alias of vector_and
+ FUNCTION orv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- alias of vector_or
+ FUNCTION xorv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- alias of vector_xor
+
+ FUNCTION matrix_and(mat : t_sl_matrix; wi, wj : NATURAL) RETURN STD_LOGIC; -- '1' when all matrix bits are '1' else '0'
+ FUNCTION matrix_or(mat : t_sl_matrix; wi, wj : NATURAL) RETURN STD_LOGIC; -- '0' when all matrix bits are '0' else '1'
+
+ FUNCTION smallest(n, m : INTEGER) RETURN INTEGER;
+ FUNCTION smallest(n, m, l : INTEGER) RETURN INTEGER;
+ FUNCTION smallest(n : t_natural_arr) RETURN NATURAL;
+
+ FUNCTION largest(n, m : INTEGER) RETURN INTEGER;
+ FUNCTION largest(n : t_natural_arr) RETURN NATURAL;
+
+ FUNCTION func_sum(n : t_natural_arr) RETURN NATURAL; -- sum of all elements in array
+ FUNCTION func_sum(n : t_nat_natural_arr) RETURN NATURAL;
+ FUNCTION func_product(n : t_natural_arr) RETURN NATURAL; -- product of all elements in array
+ FUNCTION func_product(n : t_nat_natural_arr) RETURN NATURAL;
+
+ FUNCTION "+"(L, R : t_natural_arr) RETURN t_natural_arr; -- element wise sum
+ FUNCTION "+"(L : t_natural_arr; R : INTEGER) RETURN t_natural_arr; -- element wise sum
+ FUNCTION "+"(L : INTEGER; R : t_natural_arr) RETURN t_natural_arr; -- element wise sum
+
+ FUNCTION "-"(L, R : t_natural_arr) RETURN t_natural_arr; -- element wise subtract
+ FUNCTION "-"(L, R : t_natural_arr) RETURN t_integer_arr; -- element wise subtract, support negative result
+ FUNCTION "-"(L : t_natural_arr; R : INTEGER) RETURN t_natural_arr; -- element wise subtract
+ FUNCTION "-"(L : INTEGER; R : t_natural_arr) RETURN t_natural_arr; -- element wise subtract
+
+ FUNCTION "*"(L, R : t_natural_arr) RETURN t_natural_arr; -- element wise product
+ FUNCTION "*"(L : t_natural_arr; R : NATURAL) RETURN t_natural_arr; -- element wise product
+ FUNCTION "*"(L : NATURAL; R : t_natural_arr) RETURN t_natural_arr; -- element wise product
+
+ FUNCTION "/"(L, R : t_natural_arr) RETURN t_natural_arr; -- element wise division
+ FUNCTION "/"(L : t_natural_arr; R : POSITIVE) RETURN t_natural_arr; -- element wise division
+ FUNCTION "/"(L : NATURAL; R : t_natural_arr) RETURN t_natural_arr; -- element wise division
+
+ FUNCTION is_true(a : STD_LOGIC) RETURN BOOLEAN;
+ FUNCTION is_true(a : STD_LOGIC) RETURN NATURAL;
+ FUNCTION is_true(a : BOOLEAN) RETURN STD_LOGIC;
+ FUNCTION is_true(a : BOOLEAN) RETURN NATURAL;
+ FUNCTION is_true(a : INTEGER) RETURN BOOLEAN; -- also covers NATURAL because it is a subtype of INTEGER
+ FUNCTION is_true(a : INTEGER) RETURN STD_LOGIC; -- also covers NATURAL because it is a subtype of INTEGER
+
+ FUNCTION is_all(vec : STD_LOGIC_VECTOR; val : STD_LOGIC) return BOOLEAN;
+
+ FUNCTION sel_a_b(sel, a, b : BOOLEAN) RETURN BOOLEAN;
+ FUNCTION sel_a_b(sel, a, b : INTEGER) RETURN INTEGER;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : INTEGER) RETURN INTEGER;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : REAL) RETURN REAL;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : STD_LOGIC) RETURN STD_LOGIC;
+ FUNCTION sel_a_b(sel : INTEGER; a, b : STD_LOGIC) RETURN STD_LOGIC;
+ FUNCTION sel_a_b(sel : INTEGER; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : SIGNED) RETURN SIGNED;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : UNSIGNED) RETURN UNSIGNED;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_integer_arr) RETURN t_integer_arr;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_natural_arr) RETURN t_natural_arr;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_nat_integer_arr) RETURN t_nat_integer_arr;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_nat_natural_arr) RETURN t_nat_natural_arr;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : STRING) RETURN STRING;
+ FUNCTION sel_a_b(sel : INTEGER; a, b : STRING) RETURN STRING;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : TIME) RETURN TIME;
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : SEVERITY_LEVEL) RETURN SEVERITY_LEVEL;
+
+ -- sel_n() index sel = 0, 1, 2, ... will return a, b, c, ...
+ FUNCTION sel_n(sel : NATURAL; a, b, c : BOOLEAN) RETURN BOOLEAN; -- 3
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d : BOOLEAN) RETURN BOOLEAN; -- 4
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : BOOLEAN) RETURN BOOLEAN; -- 5
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : BOOLEAN) RETURN BOOLEAN; -- 6
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : BOOLEAN) RETURN BOOLEAN; -- 7
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : BOOLEAN) RETURN BOOLEAN; -- 8
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : BOOLEAN) RETURN BOOLEAN; -- 9
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : BOOLEAN) RETURN BOOLEAN; -- 10
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c : INTEGER) RETURN INTEGER; -- 3
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d : INTEGER) RETURN INTEGER; -- 4
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : INTEGER) RETURN INTEGER; -- 5
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : INTEGER) RETURN INTEGER; -- 6
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : INTEGER) RETURN INTEGER; -- 7
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : INTEGER) RETURN INTEGER; -- 8
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : INTEGER) RETURN INTEGER; -- 9
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : INTEGER) RETURN INTEGER; -- 10
+
+ FUNCTION sel_n(sel : NATURAL; a, b : STRING) RETURN STRING; -- 2
+ FUNCTION sel_n(sel : NATURAL; a, b, c : STRING) RETURN STRING; -- 3
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d : STRING) RETURN STRING; -- 4
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : STRING) RETURN STRING; -- 5
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : STRING) RETURN STRING; -- 6
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : STRING) RETURN STRING; -- 7
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : STRING) RETURN STRING; -- 8
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : STRING) RETURN STRING; -- 9
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : STRING) RETURN STRING; -- 10
+
+ FUNCTION array_init(init : STD_LOGIC; nof : NATURAL) RETURN STD_LOGIC_VECTOR; -- useful to init a unconstrained array of size 1
+ FUNCTION array_init(init, nof : NATURAL) RETURN t_natural_arr; -- useful to init a unconstrained array of size 1
+ FUNCTION array_init(init, nof : NATURAL) RETURN t_nat_natural_arr; -- useful to init a unconstrained array of size 1
+ FUNCTION array_init(init, nof, incr : NATURAL) RETURN t_natural_arr; -- useful to init an array with incrementing numbers
+ FUNCTION array_init(init, nof, incr : NATURAL) RETURN t_nat_natural_arr;
+ FUNCTION array_init(init, nof, incr : INTEGER) RETURN t_slv_16_arr;
+ FUNCTION array_init(init, nof, incr : INTEGER) RETURN t_slv_32_arr;
+ FUNCTION array_init(init, nof, width : NATURAL) RETURN STD_LOGIC_VECTOR; -- useful to init an unconstrained std_logic_vector with repetitive content
+ FUNCTION array_init(init, nof, width, incr : NATURAL) RETURN STD_LOGIC_VECTOR; -- useful to init an unconstrained std_logic_vector with incrementing content
+ FUNCTION array_sinit(init : INTEGER; nof, width : NATURAL) RETURN STD_LOGIC_VECTOR; -- useful to init an unconstrained std_logic_vector with repetitive content
+
+ FUNCTION init_slv_64_matrix(nof_a, nof_b, k : INTEGER) RETURN t_slv_64_matrix; -- initialize all elements in t_slv_64_matrix to value k
+
+ -- Concatenate two or more STD_LOGIC_VECTORs into a single STD_LOGIC_VECTOR or extract one of them from a concatenated STD_LOGIC_VECTOR
+ FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
+ FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a, b, c, d, e, f : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
+ FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a, b, c, d, e : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
+ FUNCTION func_slv_concat(use_a, use_b, use_c, use_d : BOOLEAN; a, b, c, d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
+ FUNCTION func_slv_concat(use_a, use_b, use_c : BOOLEAN; a, b, c : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
+ FUNCTION func_slv_concat(use_a, use_b : BOOLEAN; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
+ FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL) RETURN NATURAL;
+ FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL) RETURN NATURAL;
+ FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL) RETURN NATURAL;
+ FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL) RETURN NATURAL;
+ FUNCTION func_slv_concat_w(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL) RETURN NATURAL;
+ FUNCTION func_slv_concat_w(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL) RETURN NATURAL;
+ FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
+ FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
+ FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
+ FUNCTION func_slv_extract(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
+ FUNCTION func_slv_extract(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
+ FUNCTION func_slv_extract(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
+
+ FUNCTION func_slv_reverse(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
+
+ FUNCTION TO_UINT(vec : STD_LOGIC_VECTOR) RETURN NATURAL; -- beware: NATURAL'HIGH = 2**31-1, not 2*32-1, use TO_SINT to avoid warning
+ FUNCTION TO_SINT(vec : STD_LOGIC_VECTOR) RETURN INTEGER;
+
+ FUNCTION TO_UVEC(dec, w : NATURAL) RETURN STD_LOGIC_VECTOR;
+ FUNCTION TO_SVEC(dec, w : INTEGER) RETURN STD_LOGIC_VECTOR;
+
+ FUNCTION TO_SVEC_32(dec : INTEGER) RETURN STD_LOGIC_VECTOR; -- = TO_SVEC() with w=32 for t_slv_32_arr slv elements
+
+ -- The RESIZE for SIGNED in IEEE.NUMERIC_STD extends the sign bit or it keeps the sign bit and LS part. This
+ -- behaviour of preserving the sign bit is less suitable for DSP and not necessary in general. A more
+ -- appropriate approach is to ignore the MSbit sign and just keep the LS part. For too large values this
+ -- means that the result gets wrapped, but that is fine for default behaviour, because that is also what
+ -- happens for RESIZE of UNSIGNED. Therefor this is what the RESIZE_NUM for SIGNED and the RESIZE_SVEC do
+ -- and better not use RESIZE for SIGNED anymore.
+ FUNCTION RESIZE_NUM(u : UNSIGNED; w : NATURAL) RETURN UNSIGNED; -- left extend with '0' or keep LS part (same as RESIZE for UNSIGNED)
+ FUNCTION RESIZE_NUM(s : SIGNED; w : NATURAL) RETURN SIGNED; -- extend sign bit or keep LS part
+ FUNCTION RESIZE_UVEC(sl : STD_LOGIC; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- left extend with '0' into slv
+ FUNCTION RESIZE_UVEC(vec : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- left extend with '0' or keep LS part
+ FUNCTION RESIZE_SVEC(vec : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- extend sign bit or keep LS part
+ FUNCTION RESIZE_UINT(u : INTEGER; w : NATURAL) RETURN INTEGER; -- left extend with '0' or keep LS part
+ FUNCTION RESIZE_SINT(s : INTEGER; w : NATURAL) RETURN INTEGER; -- extend sign bit or keep LS part
+
+ FUNCTION RESIZE_UVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- = RESIZE_UVEC() with w=32 for t_slv_32_arr slv elements
+ FUNCTION RESIZE_SVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- = RESIZE_SVEC() with w=32 for t_slv_32_arr slv elements
+
+ FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR;
+ FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : UNSIGNED) RETURN STD_LOGIC_VECTOR;
+ FUNCTION INCR_SVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR;
+ FUNCTION INCR_SVEC(vec : STD_LOGIC_VECTOR; dec : SIGNED) RETURN STD_LOGIC_VECTOR;
+
+ -- Used in common_add_sub.vhd
+ FUNCTION ADD_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR; -- l_vec + r_vec, treat slv operands as signed, slv output width is res_w
+ FUNCTION SUB_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR; -- l_vec - r_vec, treat slv operands as signed, slv output width is res_w
+ FUNCTION ADD_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR; -- l_vec + r_vec, treat slv operands as unsigned, slv output width is res_w
+ FUNCTION SUB_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR; -- l_vec - r_vec, treat slv operands as unsigned, slv output width is res_w
+
+ FUNCTION ADD_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- l_vec + r_vec, treat slv operands as signed, slv output width is l_vec'LENGTH
+ FUNCTION SUB_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- l_vec - r_vec, treat slv operands as signed, slv output width is l_vec'LENGTH
+ FUNCTION ADD_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- l_vec + r_vec, treat slv operands as unsigned, slv output width is l_vec'LENGTH
+ FUNCTION SUB_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- l_vec - r_vec, treat slv operands as unsigned, slv output width is l_vec'LENGTH
+
+ FUNCTION COMPLEX_MULT_REAL(a_re, a_im, b_re, b_im : INTEGER) RETURN INTEGER; -- Calculate real part of complex multiplication: a_re*b_re - a_im*b_im
+ FUNCTION COMPLEX_MULT_IMAG(a_re, a_im, b_re, b_im : INTEGER) RETURN INTEGER; -- Calculate imag part of complex multiplication: a_im*b_re + a_re*b_im
+
+ FUNCTION S_ADD_OVFLW_DET(a, b, sum_a_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- Preempt whether there is addition overflow for signed values
+ FUNCTION S_SUB_OVFLW_DET(a, b, sub_a_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC; -- Preempt whether there is subtraction overflow for signed values
+
+ FUNCTION SHIFT_UVEC(vec : STD_LOGIC_VECTOR; shift : INTEGER) RETURN STD_LOGIC_VECTOR; -- < 0 shift left, > 0 shift right
+ FUNCTION SHIFT_SVEC(vec : STD_LOGIC_VECTOR; shift : INTEGER) RETURN STD_LOGIC_VECTOR; -- < 0 shift left, > 0 shift right
+
+ FUNCTION offset_binary(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
+
+ FUNCTION truncate(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR; -- remove n LSBits from vec, so result has width vec'LENGTH-n
+ FUNCTION truncate_and_resize_uvec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR; -- remove n LSBits from vec and then resize to width w
+ FUNCTION truncate_and_resize_svec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR; -- idem for signed values
+ FUNCTION scale(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR; -- add n '0' LSBits to vec
+ FUNCTION scale_and_resize_uvec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR; -- add n '0' LSBits to vec and then resize to width w
+ FUNCTION scale_and_resize_svec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR; -- idem for signed values
+ FUNCTION truncate_or_resize_uvec(vec : STD_LOGIC_VECTOR; b : BOOLEAN; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- when b=TRUE then truncate to width w, else resize to width w
+ FUNCTION truncate_or_resize_svec(vec : STD_LOGIC_VECTOR; b : BOOLEAN; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- idem for signed values
+
+ FUNCTION s_round_inf(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR; -- remove n LSBits from vec by rounding away from 0, so result has width vec'LENGTH-n, and clip to avoid wrap
+ FUNCTION s_round(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN; round_style : t_rounding_mode) RETURN STD_LOGIC_VECTOR; -- remove n LSBits from vec by rounding away from 0, so result has width vec'LENGTH-n, and clip to avoid wrap
+ FUNCTION s_round(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR; -- remove n LSBits from vec by rounding away from 0, so result has width vec'LENGTH-n
+ FUNCTION s_round_up(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR; -- idem but round up to +infinity (s_round_up = u_round)
+ FUNCTION s_round_up(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR; -- idem but round up to +infinity (s_round_up = u_round)
+ FUNCTION u_round(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR; -- idem round up for unsigned values
+ FUNCTION u_round(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR; -- idem round up for unsigned values
+
+ FUNCTION u_to_s(u : NATURAL; w : NATURAL) RETURN INTEGER; -- interpret w bit unsigned u as w bit signed, and remove any MSbits
+ FUNCTION s_to_u(s : INTEGER; w : NATURAL) RETURN NATURAL; -- interpret w bit signed s as w bit unsigned, and remove any MSbits
+
+ FUNCTION u_wrap(u : NATURAL; w : NATURAL) RETURN NATURAL; -- return u & 2**w-1 (bit wise and), so keep w LSbits of unsigned u, and remove MSbits
+ FUNCTION s_wrap(s : INTEGER; w : NATURAL) RETURN INTEGER; -- return s & 2**w-1 (bit wise and), so keep w LSbits of signed s, and remove MSbits
+
+ FUNCTION u_clip(u : NATURAL; max : NATURAL) RETURN NATURAL; -- if s < max return s, else return n
+ FUNCTION s_clip(s : INTEGER; max : NATURAL; min : INTEGER) RETURN INTEGER; -- if s <= min return min, else if s >= max return max, else return s
+ FUNCTION s_clip(s : INTEGER; max : NATURAL) RETURN INTEGER; -- if s <= -max return -max, else if s >= max return max, else return s
+
+ FUNCTION hton(a : STD_LOGIC_VECTOR; w, sz : NATURAL) RETURN STD_LOGIC_VECTOR; -- convert endianity from host to network, sz in symbols of width w
+ FUNCTION hton(a : STD_LOGIC_VECTOR; sz : NATURAL) RETURN STD_LOGIC_VECTOR; -- convert endianity from host to network, sz in bytes
+ FUNCTION hton(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- convert endianity from host to network, for all bytes in a
+ FUNCTION ntoh(a : STD_LOGIC_VECTOR; sz : NATURAL) RETURN STD_LOGIC_VECTOR; -- convert endianity from network to host, sz in bytes, ntoh() = hton()
+ FUNCTION ntoh(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- convert endianity from network to host, for all bytes in a, ntoh() = hton()
+
+ FUNCTION flip(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- bit flip a vector, map a[h:0] to [0:h]
+ FUNCTION flip(a, w : NATURAL) RETURN NATURAL; -- bit flip a vector, map a[h:0] to [0:h], h = w-1
+ FUNCTION flip(a : t_slv_32_arr) RETURN t_slv_32_arr;
+ FUNCTION flip(a : t_integer_arr) RETURN t_integer_arr;
+ FUNCTION flip(a : t_natural_arr) RETURN t_natural_arr;
+ FUNCTION flip(a : t_nat_natural_arr) RETURN t_nat_natural_arr;
+
+ FUNCTION transpose(a : STD_LOGIC_VECTOR; row, col : NATURAL) RETURN STD_LOGIC_VECTOR; -- transpose a vector, map a[i*row+j] to output index [j*col+i]
+ FUNCTION transpose(a, row, col : NATURAL) RETURN NATURAL; -- transpose index a = [i*row+j] to output index [j*col+i]
+
+ FUNCTION split_w(input_w : NATURAL; min_out_w : NATURAL; max_out_w : NATURAL) RETURN NATURAL;
+
+ FUNCTION pad(str : STRING; width : NATURAL; pad_char : CHARACTER) RETURN STRING;
+
+ FUNCTION slice_up(str : STRING; width : NATURAL; i : NATURAL) RETURN STRING;
+ FUNCTION slice_up(str : STRING; width : NATURAL; i : NATURAL; pad_char : CHARACTER) RETURN STRING;
+ FUNCTION slice_dn(str : STRING; width : NATURAL; i : NATURAL) RETURN STRING;
+
+ FUNCTION nat_arr_to_concat_slv(nat_arr : t_natural_arr; nof_elements : NATURAL) RETURN STD_LOGIC_VECTOR;
+
+ ------------------------------------------------------------------------------
+ -- Component specific functions
+ ------------------------------------------------------------------------------
+
+ -- common_fifo_*
+ PROCEDURE proc_common_fifo_asserts(CONSTANT c_fifo_name : IN STRING;
+ CONSTANT c_note_is_ful : IN BOOLEAN;
+ CONSTANT c_fail_rd_emp : IN BOOLEAN;
+ SIGNAL wr_rst : IN STD_LOGIC;
+ SIGNAL wr_clk : IN STD_LOGIC;
+ SIGNAL wr_full : IN STD_LOGIC;
+ SIGNAL wr_en : IN STD_LOGIC;
+ SIGNAL rd_clk : IN STD_LOGIC;
+ SIGNAL rd_empty : IN STD_LOGIC;
+ SIGNAL rd_en : IN STD_LOGIC);
+
+ -- common_fanout_tree
+ FUNCTION func_common_fanout_tree_pipelining(c_nof_stages, c_nof_output_per_cell, c_nof_output : NATURAL;
+ c_cell_pipeline_factor_arr, c_cell_pipeline_arr : t_natural_arr) RETURN t_natural_arr;
+
+ -- common_reorder_symbol
+ FUNCTION func_common_reorder2_is_there(I, J : NATURAL) RETURN BOOLEAN;
+ FUNCTION func_common_reorder2_is_active(I, J, N : NATURAL) RETURN BOOLEAN;
+ FUNCTION func_common_reorder2_get_select_index(I, J, N : NATURAL) RETURN INTEGER;
+ FUNCTION func_common_reorder2_get_select(I, J, N : NATURAL; select_arr : t_natural_arr) RETURN NATURAL;
+ FUNCTION func_common_reorder2_inverse_select(N : NATURAL; select_arr : t_natural_arr) RETURN t_natural_arr;
+
+ -- Generate faster sample SCLK from digital DCLK for sim only
+ PROCEDURE proc_common_dclk_generate_sclk(CONSTANT Pfactor : IN POSITIVE;
+ SIGNAL dclk : IN STD_LOGIC;
+ SIGNAL sclk : INOUT STD_LOGIC);
+ function stringround_to_enum_round(stringin : string) return t_rounding_mode;
+END common_pkg;
+
+PACKAGE BODY common_pkg IS
+
+ FUNCTION pow2(n : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN 2 ** n;
+ END;
+
+ FUNCTION ceil_pow2(n : INTEGER) RETURN NATURAL IS
+ -- Also allows negative exponents and rounds up before returning the value
+ BEGIN
+ RETURN natural(integer(ceil(2 ** real(n))));
+ END;
+
+ FUNCTION true_log2(n : NATURAL) RETURN NATURAL IS
+ -- Purpose: For calculating extra vector width of existing vector
+ -- Description: Return mathematical ceil(log2(n))
+ -- n log2()
+ -- 0 -> -oo --> FAILURE
+ -- 1 -> 0
+ -- 2 -> 1
+ -- 3 -> 2
+ -- 4 -> 2
+ -- 5 -> 3
+ -- 6 -> 3
+ -- 7 -> 3
+ -- 8 -> 3
+ -- 9 -> 4
+ -- etc, up to n = NATURAL'HIGH = 2**31-1
+ BEGIN
+ RETURN natural(integer(ceil(log2(real(n)))));
+ END;
+
+ FUNCTION ceil_log2(n : NATURAL) RETURN NATURAL IS
+ -- Purpose: For calculating vector width of new vector
+ -- Description:
+ -- Same as true_log2() except ceil_log2(1) = 1, which is needed to support
+ -- the vector width width for 1 address, to avoid NULL array for single
+ -- word register address.
+ -- If n = 0, return 0 so we get a NULL array when using
+ -- STD_LOGIC_VECTOR(ceil_log2(g_addr_w)-1 DOWNTO 0), instead of an error.
+ BEGIN
+ IF n = 0 THEN
+ RETURN 0; -- Get NULL array
+ ELSIF n = 1 THEN
+ RETURN 1; -- avoid NULL array
+ ELSE
+ RETURN true_log2(n);
+ END IF;
+ END;
+
+ FUNCTION next_pow2(n : NATURAL) return NATURAL is
+ variable pow : NATURAL := 1;
+ variable result : NATURAL;
+ begin
+ while pow < n loop
+ pow := pow * 2;
+ end loop;
+ result := ceil_log2(pow);
+ return result;
+ end FUNCTION;
+
+ FUNCTION floor_log10(n : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN natural(integer(floor(log10(real(n)))));
+ END;
+
+ FUNCTION is_pow2(n : NATURAL) RETURN BOOLEAN IS
+ BEGIN
+ RETURN n = 2 ** true_log2(n);
+ END;
+
+ FUNCTION true_log_pow2(n : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN 2 ** true_log2(n);
+ END;
+
+ FUNCTION ratio(n, d : NATURAL) RETURN NATURAL IS
+ BEGIN
+ IF n MOD d = 0 THEN
+ RETURN n / d;
+ ELSE
+ RETURN 0;
+ END IF;
+ END;
+
+ FUNCTION ratio2(n, m : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN largest(ratio(n, m), ratio(m, n));
+ END;
+
+ FUNCTION ceil_div(n, d : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN n / d + sel_a_b(n MOD d = 0, 0, 1);
+ END;
+
+ FUNCTION ceil_value(n, d : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN ceil_div(n, d) * d;
+ END;
+
+ FUNCTION floor_value(n, d : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN (n / d) * d;
+ END;
+
+ FUNCTION ceil_div(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED IS
+ BEGIN
+ RETURN n / d + sel_a_b(n MOD d = 0, 0, 1); -- "/" returns same width as n
+ END;
+
+ FUNCTION ceil_value(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED IS
+ CONSTANT w : NATURAL := n'LENGTH;
+ VARIABLE p : UNSIGNED(2 * w - 1 DOWNTO 0);
+ BEGIN
+ p := ceil_div(n, d) * d;
+ RETURN p(w - 1 DOWNTO 0); -- return same width as n
+ END;
+
+ FUNCTION floor_value(n : UNSIGNED; d : NATURAL) RETURN UNSIGNED IS
+ CONSTANT w : NATURAL := n'LENGTH;
+ VARIABLE p : UNSIGNED(2 * w - 1 DOWNTO 0);
+ BEGIN
+ p := (n / d) * d;
+ RETURN p(w - 1 DOWNTO 0); -- return same width as n
+ END;
+
+ FUNCTION slv(n : IN STD_LOGIC) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE r : STD_LOGIC_VECTOR(0 DOWNTO 0);
+ BEGIN
+ r(0) := n;
+ RETURN r;
+ END;
+
+ FUNCTION sl(n : IN STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
+ VARIABLE r : STD_LOGIC;
+ BEGIN
+ r := n(n'LOW);
+ RETURN r;
+ END;
+
+ FUNCTION to_natural_arr(n : t_integer_arr; to_zero : BOOLEAN) RETURN t_natural_arr IS
+ VARIABLE vN : t_integer_arr(n'LENGTH - 1 DOWNTO 0);
+ VARIABLE vR : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ vN := n;
+ FOR I IN vN'RANGE LOOP
+ IF to_zero = FALSE THEN
+ vR(I) := vN(I);
+ ELSE
+ vR(I) := 0;
+ IF vN(I) > 0 THEN
+ vR(I) := vN(I);
+ END IF;
+ END IF;
+ END LOOP;
+ RETURN vR;
+ END;
+
+ FUNCTION to_natural_arr(n : t_nat_natural_arr) RETURN t_natural_arr IS
+ VARIABLE vN : t_nat_natural_arr(n'LENGTH - 1 DOWNTO 0);
+ VARIABLE vR : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ vN := n;
+ FOR I IN vN'RANGE LOOP
+ vR(I) := vN(I);
+ END LOOP;
+ RETURN vR;
+ END;
+
+ FUNCTION to_integer_arr(n : t_natural_arr) RETURN t_integer_arr IS
+ VARIABLE vN : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
+ VARIABLE vR : t_integer_arr(n'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ vN := n;
+ FOR I IN vN'RANGE LOOP
+ vR(I) := vN(I);
+ END LOOP;
+ RETURN vR;
+ END;
+
+ FUNCTION to_integer_arr(n : t_nat_natural_arr) RETURN t_integer_arr IS
+ VARIABLE vN : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ vN := to_natural_arr(n);
+ RETURN to_integer_arr(vN);
+ END;
+
+ FUNCTION to_slv_32_arr(n : t_integer_arr) RETURN t_slv_32_arr IS
+ VARIABLE vN : t_integer_arr(n'LENGTH - 1 DOWNTO 0);
+ VARIABLE vR : t_slv_32_arr(n'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ vN := n;
+ FOR I IN vN'RANGE LOOP
+ vR(I) := TO_SVEC(vN(I), 32);
+ END LOOP;
+ RETURN vR;
+ END;
+
+ FUNCTION to_slv_32_arr(n : t_natural_arr) RETURN t_slv_32_arr IS
+ VARIABLE vN : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
+ VARIABLE vR : t_slv_32_arr(n'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ vN := n;
+ FOR I IN vN'RANGE LOOP
+ vR(I) := TO_UVEC(vN(I), 32);
+ END LOOP;
+ RETURN vR;
+ END;
+
+ FUNCTION vector_tree(slv : STD_LOGIC_VECTOR; operation : STRING) RETURN STD_LOGIC IS
+ -- Linear loop to determine result takes combinatorial delay that is proportional to slv'LENGTH:
+ -- FOR I IN slv'RANGE LOOP
+ -- v_result := v_result OPERATION slv(I);
+ -- END LOOP;
+ -- RETURN v_result;
+ -- Instead use binary tree to determine result with smallest combinatorial delay that depends on log2(slv'LENGTH)
+ CONSTANT c_slv_w : NATURAL := slv'LENGTH;
+ CONSTANT c_nof_stages : NATURAL := ceil_log2(c_slv_w);
+ CONSTANT c_w : NATURAL := 2 ** c_nof_stages; -- extend the input slv to a vector with length power of 2 to ease using binary tree
+ TYPE t_stage_arr IS ARRAY (-1 TO c_nof_stages - 1) OF STD_LOGIC_VECTOR(c_w - 1 DOWNTO 0);
+ VARIABLE v_stage_arr : t_stage_arr;
+ VARIABLE v_result : STD_LOGIC := '0';
+ BEGIN
+ -- default any unused, the stage results will be kept in the LSBits and the last result in bit 0
+ IF operation = "AND" THEN
+ v_stage_arr := (OTHERS => (OTHERS => '1'));
+ ELSIF operation = "OR" THEN
+ v_stage_arr := (OTHERS => (OTHERS => '0'));
+ ELSIF operation = "XOR" THEN
+ v_stage_arr := (OTHERS => (OTHERS => '0'));
+ ELSE
+ ASSERT TRUE REPORT "common_pkg: Unsupported vector_tree operation" SEVERITY FAILURE;
+ END IF;
+ v_stage_arr(-1)(c_slv_w - 1 DOWNTO 0) := slv; -- any unused input c_w : c_slv_w bits have void default value
+ FOR J IN 0 TO c_nof_stages - 1 LOOP
+ FOR I IN 0 TO c_w / (2 ** (J + 1)) - 1 LOOP
+ IF operation = "AND" THEN
+ v_stage_arr(J)(I) := v_stage_arr(J - 1)(2 * I) AND v_stage_arr(J - 1)(2 * I + 1);
+ ELSIF operation = "OR" THEN
+ v_stage_arr(J)(I) := v_stage_arr(J - 1)(2 * I) OR v_stage_arr(J - 1)(2 * I + 1);
+ ELSIF operation = "XOR" THEN
+ v_stage_arr(J)(I) := v_stage_arr(J - 1)(2 * I) XOR v_stage_arr(J - 1)(2 * I + 1);
+ END IF;
+ END LOOP;
+ END LOOP;
+ RETURN v_stage_arr(c_nof_stages - 1)(0);
+ END;
+
+ FUNCTION vector_and(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
+ BEGIN
+ RETURN vector_tree(slv, "AND");
+ END;
+
+ FUNCTION vector_or(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
+ BEGIN
+ RETURN vector_tree(slv, "OR");
+ END;
+
+ FUNCTION vector_xor(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
+ BEGIN
+ RETURN vector_tree(slv, "XOR");
+ END;
+
+ FUNCTION vector_one_hot(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_one_hot : BOOLEAN := FALSE;
+ VARIABLE v_zeros : STD_LOGIC_VECTOR(slv'RANGE) := (OTHERS => '0');
+ BEGIN
+ FOR i IN slv'RANGE LOOP
+ IF slv(i) = '1' THEN
+ IF NOT (v_one_hot) THEN
+ -- No hot bits found so far
+ v_one_hot := TRUE;
+ ELSE
+ -- This is the second hot bit found; return zeros.
+ RETURN v_zeros;
+ END IF;
+ END IF;
+ END LOOP;
+ -- No or a single hot bit found in slv; return slv.
+ RETURN slv;
+ END;
+
+ FUNCTION andv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
+ BEGIN
+ RETURN vector_tree(slv, "AND");
+ END;
+
+ FUNCTION orv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
+ BEGIN
+ RETURN vector_tree(slv, "OR");
+ END;
+
+ FUNCTION xorv(slv : STD_LOGIC_VECTOR) RETURN STD_LOGIC IS
+ BEGIN
+ RETURN vector_tree(slv, "XOR");
+ END;
+
+ FUNCTION matrix_and(mat : t_sl_matrix; wi, wj : NATURAL) RETURN STD_LOGIC IS
+ VARIABLE v_mat : t_sl_matrix(0 TO wi - 1, 0 TO wj - 1) := mat; -- map to fixed range
+ VARIABLE v_result : STD_LOGIC := '1';
+ BEGIN
+ FOR I IN 0 TO wi - 1 LOOP
+ FOR J IN 0 TO wj - 1 LOOP
+ v_result := v_result AND v_mat(I, J);
+ END LOOP;
+ END LOOP;
+ RETURN v_result;
+ END;
+
+ FUNCTION matrix_or(mat : t_sl_matrix; wi, wj : NATURAL) RETURN STD_LOGIC IS
+ VARIABLE v_mat : t_sl_matrix(0 TO wi - 1, 0 TO wj - 1) := mat; -- map to fixed range
+ VARIABLE v_result : STD_LOGIC := '0';
+ BEGIN
+ FOR I IN 0 TO wi - 1 LOOP
+ FOR J IN 0 TO wj - 1 LOOP
+ v_result := v_result OR v_mat(I, J);
+ END LOOP;
+ END LOOP;
+ RETURN v_result;
+ END;
+
+ FUNCTION smallest(n, m : INTEGER) RETURN INTEGER IS
+ BEGIN
+ IF n < m THEN
+ RETURN n;
+ ELSE
+ RETURN m;
+ END IF;
+ END;
+
+ FUNCTION smallest(n, m, l : INTEGER) RETURN INTEGER IS
+ VARIABLE v : NATURAL;
+ BEGIN
+ v := n;
+ IF v > m THEN
+ v := m;
+ END IF;
+ IF v > l THEN
+ v := l;
+ END IF;
+ RETURN v;
+ END;
+
+ FUNCTION smallest(n : t_natural_arr) RETURN NATURAL IS
+ VARIABLE m : NATURAL := 0;
+ BEGIN
+ FOR I IN n'RANGE LOOP
+ IF n(I) < m THEN
+ m := n(I);
+ END IF;
+ END LOOP;
+ RETURN m;
+ END;
+
+ FUNCTION largest(n, m : INTEGER) RETURN INTEGER IS
+ BEGIN
+ IF n > m THEN
+ RETURN n;
+ ELSE
+ RETURN m;
+ END IF;
+ END;
+
+ FUNCTION largest(n : t_natural_arr) RETURN NATURAL IS
+ VARIABLE m : NATURAL := 0;
+ BEGIN
+ FOR I IN n'RANGE LOOP
+ IF n(I) > m THEN
+ m := n(I);
+ END IF;
+ END LOOP;
+ RETURN m;
+ END;
+
+ FUNCTION func_sum(n : t_natural_arr) RETURN NATURAL IS
+ VARIABLE vS : NATURAL;
+ BEGIN
+ vS := 0;
+ FOR I IN n'RANGE LOOP
+ vS := vS + n(I);
+ END LOOP;
+ RETURN vS;
+ END;
+
+ FUNCTION func_sum(n : t_nat_natural_arr) RETURN NATURAL IS
+ VARIABLE vN : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ vN := to_natural_arr(n);
+ RETURN func_sum(vN);
+ END;
+
+ FUNCTION func_product(n : t_natural_arr) RETURN NATURAL IS
+ VARIABLE vP : NATURAL;
+ BEGIN
+ vP := 1;
+ FOR I IN n'RANGE LOOP
+ vP := vP * n(I);
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION func_product(n : t_nat_natural_arr) RETURN NATURAL IS
+ VARIABLE vN : t_natural_arr(n'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ vN := to_natural_arr(n);
+ RETURN func_product(vN);
+ END;
+
+ FUNCTION "+"(L, R : t_natural_arr) RETURN t_natural_arr IS
+ CONSTANT w : NATURAL := L'LENGTH;
+ VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
+ BEGIN
+ vL := L;
+ vR := R;
+ FOR I IN vL'RANGE LOOP
+ vP(I) := vL(I) + vR(I);
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION "+"(L : t_natural_arr; R : INTEGER) RETURN t_natural_arr IS
+ CONSTANT w : NATURAL := L'LENGTH;
+ VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
+ BEGIN
+ vL := L;
+ FOR I IN vL'RANGE LOOP
+ vP(I) := vL(I) + R;
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION "+"(L : INTEGER; R : t_natural_arr) RETURN t_natural_arr IS
+ BEGIN
+ RETURN R + L;
+ END;
+
+ FUNCTION "-"(L, R : t_natural_arr) RETURN t_natural_arr IS
+ CONSTANT w : NATURAL := L'LENGTH;
+ VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
+ BEGIN
+ vL := L;
+ vR := R;
+ FOR I IN vL'RANGE LOOP
+ vP(I) := vL(I) - vR(I);
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION "-"(L, R : t_natural_arr) RETURN t_integer_arr IS
+ CONSTANT w : NATURAL := L'LENGTH;
+ VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vP : t_integer_arr(w - 1 DOWNTO 0);
+ BEGIN
+ vL := L;
+ vR := R;
+ FOR I IN vL'RANGE LOOP
+ vP(I) := vL(I) - vR(I);
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION "-"(L : t_natural_arr; R : INTEGER) RETURN t_natural_arr IS
+ CONSTANT w : NATURAL := L'LENGTH;
+ VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
+ BEGIN
+ vL := L;
+ FOR I IN vL'RANGE LOOP
+ vP(I) := vL(I) - R;
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION "-"(L : INTEGER; R : t_natural_arr) RETURN t_natural_arr IS
+ CONSTANT w : NATURAL := R'LENGTH;
+ VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
+ BEGIN
+ vR := R;
+ FOR I IN vR'RANGE LOOP
+ vP(I) := L - vR(I);
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION "*"(L, R : t_natural_arr) RETURN t_natural_arr IS
+ CONSTANT w : NATURAL := L'LENGTH;
+ VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
+ BEGIN
+ vL := L;
+ vR := R;
+ FOR I IN vL'RANGE LOOP
+ vP(I) := vL(I) * vR(I);
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION "*"(L : t_natural_arr; R : NATURAL) RETURN t_natural_arr IS
+ CONSTANT w : NATURAL := L'LENGTH;
+ VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
+ BEGIN
+ vL := L;
+ FOR I IN vL'RANGE LOOP
+ vP(I) := vL(I) * R;
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION "*"(L : NATURAL; R : t_natural_arr) RETURN t_natural_arr IS
+ BEGIN
+ RETURN R * L;
+ END;
+
+ FUNCTION "/"(L, R : t_natural_arr) RETURN t_natural_arr IS
+ CONSTANT w : NATURAL := L'LENGTH;
+ VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
+ BEGIN
+ vL := L;
+ vR := R;
+ FOR I IN vL'RANGE LOOP
+ vP(I) := vL(I) / vR(I);
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION "/"(L : t_natural_arr; R : POSITIVE) RETURN t_natural_arr IS
+ CONSTANT w : NATURAL := L'LENGTH;
+ VARIABLE vL : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
+ BEGIN
+ vL := L;
+ FOR I IN vL'RANGE LOOP
+ vP(I) := vL(I) / R;
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION "/"(L : NATURAL; R : t_natural_arr) RETURN t_natural_arr IS
+ CONSTANT w : NATURAL := R'LENGTH;
+ VARIABLE vR : t_natural_arr(w - 1 DOWNTO 0);
+ VARIABLE vP : t_natural_arr(w - 1 DOWNTO 0);
+ BEGIN
+ vR := R;
+ FOR I IN vR'RANGE LOOP
+ vP(I) := L / vR(I);
+ END LOOP;
+ RETURN vP;
+ END;
+
+ FUNCTION is_true(a : STD_LOGIC) RETURN BOOLEAN IS
+ BEGIN
+ IF a = '1' THEN
+ RETURN TRUE;
+ ELSE
+ RETURN FALSE;
+ END IF;
+ END;
+ FUNCTION is_true(a : STD_LOGIC) RETURN NATURAL IS
+ BEGIN
+ IF a = '1' THEN
+ RETURN 1;
+ ELSE
+ RETURN 0;
+ END IF;
+ END;
+ FUNCTION is_true(a : BOOLEAN) RETURN STD_LOGIC IS
+ BEGIN
+ IF a = TRUE THEN
+ RETURN '1';
+ ELSE
+ RETURN '0';
+ END IF;
+ END;
+ FUNCTION is_true(a : BOOLEAN) RETURN NATURAL IS
+ BEGIN
+ IF a = TRUE THEN
+ RETURN 1;
+ ELSE
+ RETURN 0;
+ END IF;
+ END;
+ FUNCTION is_true(a : INTEGER) RETURN BOOLEAN IS
+ BEGIN
+ IF a /= 0 THEN
+ RETURN TRUE;
+ ELSE
+ RETURN FALSE;
+ END IF;
+ END;
+ FUNCTION is_true(a : INTEGER) RETURN STD_LOGIC IS
+ BEGIN
+ IF a /= 0 THEN
+ RETURN '1';
+ ELSE
+ RETURN '0';
+ END IF;
+ END;
+
+ FUNCTION is_all(vec : STD_LOGIC_VECTOR; val : STD_LOGIC) RETURN BOOLEAN IS
+ CONSTANT all_bits : STD_LOGIC_VECTOR(vec'RANGE) := (OTHERS => val);
+ BEGIN
+ RETURN vec = all_bits;
+ END FUNCTION;
+
+ FUNCTION sel_a_b(sel, a, b : INTEGER) RETURN INTEGER IS
+ BEGIN
+ IF sel /= 0 THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel, a, b : BOOLEAN) RETURN BOOLEAN IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : INTEGER) RETURN INTEGER IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : REAL) RETURN REAL IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : STD_LOGIC) RETURN STD_LOGIC IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : INTEGER; a, b : STD_LOGIC) RETURN STD_LOGIC IS
+ BEGIN
+ IF sel /= 0 THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : INTEGER; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ IF sel /= 0 THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : SIGNED) RETURN SIGNED IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : UNSIGNED) RETURN UNSIGNED IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_integer_arr) RETURN t_integer_arr IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_natural_arr) RETURN t_natural_arr IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_nat_integer_arr) RETURN t_nat_integer_arr IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : t_nat_natural_arr) RETURN t_nat_natural_arr IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : STRING) RETURN STRING IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : INTEGER; a, b : STRING) RETURN STRING IS
+ BEGIN
+ IF sel /= 0 THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : TIME) RETURN TIME IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ FUNCTION sel_a_b(sel : BOOLEAN; a, b : SEVERITY_LEVEL) RETURN SEVERITY_LEVEL IS
+ BEGIN
+ IF sel = TRUE THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+
+ -- sel_n : boolean
+ FUNCTION sel_n(sel : NATURAL; a, b, c : BOOLEAN) RETURN BOOLEAN IS
+ CONSTANT c_arr : t_nat_boolean_arr := (a, b, c);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d : BOOLEAN) RETURN BOOLEAN IS
+ CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : BOOLEAN) RETURN BOOLEAN IS
+ CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : BOOLEAN) RETURN BOOLEAN IS
+ CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e, f);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : BOOLEAN) RETURN BOOLEAN IS
+ CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e, f, g);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : BOOLEAN) RETURN BOOLEAN IS
+ CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e, f, g, h);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : BOOLEAN) RETURN BOOLEAN IS
+ CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e, f, g, h, i);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : BOOLEAN) RETURN BOOLEAN IS
+ CONSTANT c_arr : t_nat_boolean_arr := (a, b, c, d, e, f, g, h, i, j);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ -- sel_n : integer
+ FUNCTION sel_n(sel : NATURAL; a, b, c : INTEGER) RETURN INTEGER IS
+ CONSTANT c_arr : t_nat_integer_arr := (a, b, c);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d : INTEGER) RETURN INTEGER IS
+ CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : INTEGER) RETURN INTEGER IS
+ CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : INTEGER) RETURN INTEGER IS
+ CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e, f);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : INTEGER) RETURN INTEGER IS
+ CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e, f, g);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : INTEGER) RETURN INTEGER IS
+ CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e, f, g, h);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : INTEGER) RETURN INTEGER IS
+ CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e, f, g, h, i);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : INTEGER) RETURN INTEGER IS
+ CONSTANT c_arr : t_nat_integer_arr := (a, b, c, d, e, f, g, h, i, j);
+ BEGIN
+ RETURN c_arr(sel);
+ END;
+
+ -- sel_n : string
+ FUNCTION sel_n(sel : NATURAL; a, b : STRING) RETURN STRING IS
+ BEGIN
+ IF sel = 0 THEN
+ RETURN a;
+ ELSE
+ RETURN b;
+ END IF;
+ END;
+ FUNCTION sel_n(sel : NATURAL; a, b, c : STRING) RETURN STRING IS
+ BEGIN
+ IF sel < 2 THEN
+ RETURN sel_n(sel, a, b);
+ ELSE
+ RETURN c;
+ END IF;
+ END;
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d : STRING) RETURN STRING IS
+ BEGIN
+ IF sel < 3 THEN
+ RETURN sel_n(sel, a, b, c);
+ ELSE
+ RETURN d;
+ END IF;
+ END;
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e : STRING) RETURN STRING IS
+ BEGIN
+ IF sel < 4 THEN
+ RETURN sel_n(sel, a, b, c, d);
+ ELSE
+ RETURN e;
+ END IF;
+ END;
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f : STRING) RETURN STRING IS
+ BEGIN
+ IF sel < 5 THEN
+ RETURN sel_n(sel, a, b, c, d, e);
+ ELSE
+ RETURN f;
+ END IF;
+ END;
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g : STRING) RETURN STRING IS
+ BEGIN
+ IF sel < 6 THEN
+ RETURN sel_n(sel, a, b, c, d, e, f);
+ ELSE
+ RETURN g;
+ END IF;
+ END;
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h : STRING) RETURN STRING IS
+ BEGIN
+ IF sel < 7 THEN
+ RETURN sel_n(sel, a, b, c, d, e, f, g);
+ ELSE
+ RETURN h;
+ END IF;
+ END;
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i : STRING) RETURN STRING IS
+ BEGIN
+ IF sel < 8 THEN
+ RETURN sel_n(sel, a, b, c, d, e, f, g, h);
+ ELSE
+ RETURN i;
+ END IF;
+ END;
+ FUNCTION sel_n(sel : NATURAL; a, b, c, d, e, f, g, h, i, j : STRING) RETURN STRING IS
+ BEGIN
+ IF sel < 9 THEN
+ RETURN sel_n(sel, a, b, c, d, e, f, g, h, i);
+ ELSE
+ RETURN j;
+ END IF;
+ END;
+
+ FUNCTION array_init(init : STD_LOGIC; nof : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_arr : STD_LOGIC_VECTOR(0 TO nof - 1);
+ BEGIN
+ FOR I IN v_arr'RANGE LOOP
+ v_arr(I) := init;
+ END LOOP;
+ RETURN v_arr;
+ END;
+
+ FUNCTION array_init(init, nof : NATURAL) RETURN t_natural_arr IS
+ VARIABLE v_arr : t_natural_arr(0 TO nof - 1);
+ BEGIN
+ FOR I IN v_arr'RANGE LOOP
+ v_arr(I) := init;
+ END LOOP;
+ RETURN v_arr;
+ END;
+
+ FUNCTION array_init(init, nof : NATURAL) RETURN t_nat_natural_arr IS
+ VARIABLE v_arr : t_nat_natural_arr(0 TO nof - 1);
+ BEGIN
+ FOR I IN v_arr'RANGE LOOP
+ v_arr(I) := init;
+ END LOOP;
+ RETURN v_arr;
+ END;
+
+ FUNCTION array_init(init, nof, incr : NATURAL) RETURN t_natural_arr IS
+ VARIABLE v_arr : t_natural_arr(0 TO nof - 1);
+ VARIABLE v_i : NATURAL;
+ BEGIN
+ v_i := 0;
+ FOR I IN v_arr'RANGE LOOP
+ v_arr(I) := init + v_i * incr;
+ v_i := v_i + 1;
+ END LOOP;
+ RETURN v_arr;
+ END;
+
+ FUNCTION array_init(init, nof, incr : NATURAL) RETURN t_nat_natural_arr IS
+ VARIABLE v_arr : t_nat_natural_arr(0 TO nof - 1);
+ VARIABLE v_i : NATURAL;
+ BEGIN
+ v_i := 0;
+ FOR I IN v_arr'RANGE LOOP
+ v_arr(I) := init + v_i * incr;
+ v_i := v_i + 1;
+ END LOOP;
+ RETURN v_arr;
+ END;
+
+ FUNCTION array_init(init, nof, incr : INTEGER) RETURN t_slv_16_arr IS
+ VARIABLE v_arr : t_slv_16_arr(0 TO nof - 1);
+ VARIABLE v_i : NATURAL;
+ BEGIN
+ v_i := 0;
+ FOR I IN v_arr'RANGE LOOP
+ v_arr(I) := TO_SVEC(init + v_i * incr, 16);
+ v_i := v_i + 1;
+ END LOOP;
+ RETURN v_arr;
+ END;
+
+ FUNCTION array_init(init, nof, incr : INTEGER) RETURN t_slv_32_arr IS
+ VARIABLE v_arr : t_slv_32_arr(0 TO nof - 1);
+ VARIABLE v_i : NATURAL;
+ BEGIN
+ v_i := 0;
+ FOR I IN v_arr'RANGE LOOP
+ v_arr(I) := TO_SVEC(init + v_i * incr, 32);
+ v_i := v_i + 1;
+ END LOOP;
+ RETURN v_arr;
+ END;
+
+ FUNCTION array_init(init, nof, width : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_arr : STD_LOGIC_VECTOR(nof * width - 1 DOWNTO 0);
+ BEGIN
+ FOR I IN 0 TO nof - 1 LOOP
+ v_arr(width * (I + 1) - 1 DOWNTO width * I) := TO_UVEC(init, width);
+ END LOOP;
+ RETURN v_arr;
+ END;
+
+ FUNCTION array_init(init, nof, width, incr : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_arr : STD_LOGIC_VECTOR(nof * width - 1 DOWNTO 0);
+ VARIABLE v_i : NATURAL;
+ BEGIN
+ v_i := 0;
+ FOR I IN 0 TO nof - 1 LOOP
+ v_arr(width * (I + 1) - 1 DOWNTO width * I) := TO_UVEC(init + v_i * incr, width);
+ v_i := v_i + 1;
+ END LOOP;
+ RETURN v_arr;
+ END;
+
+ FUNCTION array_sinit(init : INTEGER; nof, width : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_arr : STD_LOGIC_VECTOR(nof * width - 1 DOWNTO 0);
+ BEGIN
+ FOR I IN 0 TO nof - 1 LOOP
+ v_arr(width * (I + 1) - 1 DOWNTO width * I) := TO_SVEC(init, width);
+ END LOOP;
+ RETURN v_arr;
+ END;
+
+ FUNCTION init_slv_64_matrix(nof_a, nof_b, k : INTEGER) RETURN t_slv_64_matrix IS
+ VARIABLE v_mat : t_slv_64_matrix(nof_a - 1 DOWNTO 0, nof_b - 1 DOWNTO 0);
+ BEGIN
+ FOR I IN 0 TO nof_a - 1 LOOP
+ FOR J IN 0 TO nof_b - 1 LOOP
+ v_mat(I, J) := TO_SVEC(k, 64);
+ END LOOP;
+ END LOOP;
+ RETURN v_mat;
+ END;
+
+ -- Support concatenation of up to 7 slv into 1 slv
+ FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ CONSTANT c_max_w : NATURAL := a'LENGTH + b'LENGTH + c'LENGTH + d'LENGTH + e'LENGTH + f'LENGTH + g'LENGTH;
+ VARIABLE v_res : STD_LOGIC_VECTOR(c_max_w - 1 DOWNTO 0) := (OTHERS => '0');
+ VARIABLE v_len : NATURAL := 0;
+ BEGIN
+ IF use_a = TRUE THEN
+ v_res(a'LENGTH - 1 + v_len DOWNTO v_len) := a;
+ v_len := v_len + a'LENGTH;
+ END IF;
+ IF use_b = TRUE THEN
+ v_res(b'LENGTH - 1 + v_len DOWNTO v_len) := b;
+ v_len := v_len + b'LENGTH;
+ END IF;
+ IF use_c = TRUE THEN
+ v_res(c'LENGTH - 1 + v_len DOWNTO v_len) := c;
+ v_len := v_len + c'LENGTH;
+ END IF;
+ IF use_d = TRUE THEN
+ v_res(d'LENGTH - 1 + v_len DOWNTO v_len) := d;
+ v_len := v_len + d'LENGTH;
+ END IF;
+ IF use_e = TRUE THEN
+ v_res(e'LENGTH - 1 + v_len DOWNTO v_len) := e;
+ v_len := v_len + e'LENGTH;
+ END IF;
+ IF use_f = TRUE THEN
+ v_res(f'LENGTH - 1 + v_len DOWNTO v_len) := f;
+ v_len := v_len + f'LENGTH;
+ END IF;
+ IF use_g = TRUE THEN
+ v_res(g'LENGTH - 1 + v_len DOWNTO v_len) := g;
+ v_len := v_len + g'LENGTH;
+ END IF;
+ RETURN v_res(v_len - 1 DOWNTO 0);
+ END func_slv_concat;
+
+ FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a, b, c, d, e, f : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, a, b, c, d, e, f, "0");
+ END func_slv_concat;
+
+ FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a, b, c, d, e : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN func_slv_concat(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, a, b, c, d, e, "0", "0");
+ END func_slv_concat;
+
+ FUNCTION func_slv_concat(use_a, use_b, use_c, use_d : BOOLEAN; a, b, c, d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN func_slv_concat(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, a, b, c, d, "0", "0", "0");
+ END func_slv_concat;
+
+ FUNCTION func_slv_concat(use_a, use_b, use_c : BOOLEAN; a, b, c : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN func_slv_concat(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, a, b, c, "0", "0", "0", "0");
+ END func_slv_concat;
+
+ FUNCTION func_slv_concat(use_a, use_b : BOOLEAN; a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN func_slv_concat(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, a, b, "0", "0", "0", "0", "0");
+ END func_slv_concat;
+
+ FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL) RETURN NATURAL IS
+ VARIABLE v_len : NATURAL := 0;
+ BEGIN
+ IF use_a = TRUE THEN
+ v_len := v_len + a_w;
+ END IF;
+ IF use_b = TRUE THEN
+ v_len := v_len + b_w;
+ END IF;
+ IF use_c = TRUE THEN
+ v_len := v_len + c_w;
+ END IF;
+ IF use_d = TRUE THEN
+ v_len := v_len + d_w;
+ END IF;
+ IF use_e = TRUE THEN
+ v_len := v_len + e_w;
+ END IF;
+ IF use_f = TRUE THEN
+ v_len := v_len + f_w;
+ END IF;
+ IF use_g = TRUE THEN
+ v_len := v_len + g_w;
+ END IF;
+ RETURN v_len;
+ END func_slv_concat_w;
+
+ FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, 0);
+ END func_slv_concat_w;
+
+ FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, a_w, b_w, c_w, d_w, e_w, 0, 0);
+ END func_slv_concat_w;
+
+ FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, a_w, b_w, c_w, d_w, 0, 0, 0);
+ END func_slv_concat_w;
+
+ FUNCTION func_slv_concat_w(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN func_slv_concat_w(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, a_w, b_w, c_w, 0, 0, 0, 0);
+ END func_slv_concat_w;
+
+ FUNCTION func_slv_concat_w(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN func_slv_concat_w(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, a_w, b_w, 0, 0, 0, 0, 0);
+ END func_slv_concat_w;
+
+ -- extract slv
+ FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_w : NATURAL := 0;
+ VARIABLE v_lo : NATURAL := 0;
+ BEGIN
+ -- if the selected slv is not used in vec, then return dummy, else return the selected slv from vec
+ CASE sel IS
+ WHEN 0 =>
+ IF use_a = TRUE THEN
+ v_w := a_w;
+ ELSE
+ RETURN c_slv0(a_w - 1 DOWNTO 0);
+ END IF;
+ WHEN 1 =>
+ IF use_b = TRUE THEN
+ v_w := b_w;
+ ELSE
+ RETURN c_slv0(b_w - 1 DOWNTO 0);
+ END IF;
+ IF use_a = TRUE THEN
+ v_lo := v_lo + a_w;
+ END IF;
+ WHEN 2 =>
+ IF use_c = TRUE THEN
+ v_w := c_w;
+ ELSE
+ RETURN c_slv0(c_w - 1 DOWNTO 0);
+ END IF;
+ IF use_a = TRUE THEN
+ v_lo := v_lo + a_w;
+ END IF;
+ IF use_b = TRUE THEN
+ v_lo := v_lo + b_w;
+ END IF;
+ WHEN 3 =>
+ IF use_d = TRUE THEN
+ v_w := d_w;
+ ELSE
+ RETURN c_slv0(d_w - 1 DOWNTO 0);
+ END IF;
+ IF use_a = TRUE THEN
+ v_lo := v_lo + a_w;
+ END IF;
+ IF use_b = TRUE THEN
+ v_lo := v_lo + b_w;
+ END IF;
+ IF use_c = TRUE THEN
+ v_lo := v_lo + c_w;
+ END IF;
+ WHEN 4 =>
+ IF use_e = TRUE THEN
+ v_w := e_w;
+ ELSE
+ RETURN c_slv0(e_w - 1 DOWNTO 0);
+ END IF;
+ IF use_a = TRUE THEN
+ v_lo := v_lo + a_w;
+ END IF;
+ IF use_b = TRUE THEN
+ v_lo := v_lo + b_w;
+ END IF;
+ IF use_c = TRUE THEN
+ v_lo := v_lo + c_w;
+ END IF;
+ IF use_d = TRUE THEN
+ v_lo := v_lo + d_w;
+ END IF;
+ WHEN 5 =>
+ IF use_f = TRUE THEN
+ v_w := f_w;
+ ELSE
+ RETURN c_slv0(f_w - 1 DOWNTO 0);
+ END IF;
+ IF use_a = TRUE THEN
+ v_lo := v_lo + a_w;
+ END IF;
+ IF use_b = TRUE THEN
+ v_lo := v_lo + b_w;
+ END IF;
+ IF use_c = TRUE THEN
+ v_lo := v_lo + c_w;
+ END IF;
+ IF use_d = TRUE THEN
+ v_lo := v_lo + d_w;
+ END IF;
+ IF use_e = TRUE THEN
+ v_lo := v_lo + e_w;
+ END IF;
+ WHEN 6 =>
+ IF use_g = TRUE THEN
+ v_w := g_w;
+ ELSE
+ RETURN c_slv0(g_w - 1 DOWNTO 0);
+ END IF;
+ IF use_a = TRUE THEN
+ v_lo := v_lo + a_w;
+ END IF;
+ IF use_b = TRUE THEN
+ v_lo := v_lo + b_w;
+ END IF;
+ IF use_c = TRUE THEN
+ v_lo := v_lo + c_w;
+ END IF;
+ IF use_d = TRUE THEN
+ v_lo := v_lo + d_w;
+ END IF;
+ IF use_e = TRUE THEN
+ v_lo := v_lo + e_w;
+ END IF;
+ IF use_f = TRUE THEN
+ v_lo := v_lo + f_w;
+ END IF;
+ WHEN OTHERS => REPORT "Unknown common_pkg func_slv_extract argument" SEVERITY FAILURE;
+ END CASE;
+ RETURN vec(v_w - 1 + v_lo DOWNTO v_lo); -- extracted slv
+ END func_slv_extract;
+
+ FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, 0, vec, sel);
+ END func_slv_extract;
+
+ FUNCTION func_slv_extract(use_a, use_b, use_c, use_d, use_e : BOOLEAN; a_w, b_w, c_w, d_w, e_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN func_slv_extract(use_a, use_b, use_c, use_d, use_e, FALSE, FALSE, a_w, b_w, c_w, d_w, e_w, 0, 0, vec, sel);
+ END func_slv_extract;
+
+ FUNCTION func_slv_extract(use_a, use_b, use_c, use_d : BOOLEAN; a_w, b_w, c_w, d_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN func_slv_extract(use_a, use_b, use_c, use_d, FALSE, FALSE, FALSE, a_w, b_w, c_w, d_w, 0, 0, 0, vec, sel);
+ END func_slv_extract;
+
+ FUNCTION func_slv_extract(use_a, use_b, use_c : BOOLEAN; a_w, b_w, c_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN func_slv_extract(use_a, use_b, use_c, FALSE, FALSE, FALSE, FALSE, a_w, b_w, c_w, 0, 0, 0, 0, vec, sel);
+ END func_slv_extract;
+
+ FUNCTION func_slv_extract(use_a, use_b : BOOLEAN; a_w, b_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN func_slv_extract(use_a, use_b, FALSE, FALSE, FALSE, FALSE, FALSE, a_w, b_w, 0, 0, 0, 0, 0, vec, sel);
+ END func_slv_extract;
+
+ FUNCTION func_slv_reverse(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE result : STD_LOGIC_VECTOR(a'RANGE);
+ ALIAS aa : STD_LOGIC_VECTOR(a'REVERSE_RANGE) is a;
+ BEGIN
+ FOR i in aa'RANGE LOOP
+ result(i) := aa(i);
+ END LOOP;
+ RETURN result;
+ END;
+
+ FUNCTION TO_UINT(vec : STD_LOGIC_VECTOR) RETURN NATURAL IS
+ BEGIN
+ RETURN TO_INTEGER(UNSIGNED(vec));
+ END;
+
+ FUNCTION TO_SINT(vec : STD_LOGIC_VECTOR) RETURN INTEGER IS
+ BEGIN
+ RETURN TO_INTEGER(SIGNED(vec));
+ END;
+
+ FUNCTION TO_UVEC(dec, w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN STD_LOGIC_VECTOR(TO_UNSIGNED(dec, w));
+ END;
+
+ FUNCTION TO_SVEC(dec, w : INTEGER) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN STD_LOGIC_VECTOR(TO_SIGNED(dec, w));
+ END;
+
+ FUNCTION TO_SVEC_32(dec : INTEGER) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN TO_SVEC(dec, 32);
+ END;
+
+ FUNCTION RESIZE_NUM(u : UNSIGNED; w : NATURAL) RETURN UNSIGNED IS
+ BEGIN
+ -- left extend with '0' or keep LS part (same as RESIZE for UNSIGNED)
+ RETURN RESIZE(u, w);
+ END;
+
+ FUNCTION RESIZE_NUM(s : SIGNED; w : NATURAL) RETURN SIGNED IS
+ BEGIN
+ -- left extend with sign bit or keep sign bit and LS part (same as RESIZE for SIGNED)
+ -- If w < s'LENGTH then assume caller ensures that the actual s values
+ -- will still fit in the w bits. Otherwise the result will wrap and
+ -- there is nothing more that this RESIZE_NUM() can improve compared
+ -- to RESIZE().
+ RETURN RESIZE(s, w);
+ END;
+
+ FUNCTION RESIZE_UVEC(sl : STD_LOGIC; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_slv0 : STD_LOGIC_VECTOR(w - 1 DOWNTO 1) := (OTHERS => '0');
+ BEGIN
+ RETURN v_slv0 & sl;
+ END;
+
+ FUNCTION RESIZE_UVEC(vec : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN STD_LOGIC_VECTOR(RESIZE_NUM(UNSIGNED(vec), w));
+ END;
+
+ FUNCTION RESIZE_SVEC(vec : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN STD_LOGIC_VECTOR(RESIZE_NUM(SIGNED(vec), w));
+ END;
+
+ FUNCTION RESIZE_UINT(u : INTEGER; w : NATURAL) RETURN INTEGER IS
+ VARIABLE v : STD_LOGIC_VECTOR(c_word_w - 1 DOWNTO 0);
+ BEGIN
+ v := TO_UVEC(u, c_word_w);
+ RETURN TO_UINT(v(w - 1 DOWNTO 0));
+ END;
+
+ FUNCTION RESIZE_SINT(s : INTEGER; w : NATURAL) RETURN INTEGER IS
+ VARIABLE v : STD_LOGIC_VECTOR(c_word_w - 1 DOWNTO 0);
+ BEGIN
+ v := TO_SVEC(s, c_word_w);
+ RETURN TO_SINT(v(w - 1 DOWNTO 0));
+ END;
+
+ FUNCTION RESIZE_UVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN RESIZE_UVEC(vec, 32);
+ END;
+
+ FUNCTION RESIZE_SVEC_32(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN RESIZE_SVEC(vec, 32);
+ END;
+
+ FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_dec : INTEGER;
+ BEGIN
+ IF dec < 0 THEN
+ v_dec := -dec;
+ RETURN STD_LOGIC_VECTOR(UNSIGNED(vec) - v_dec); -- uses function "-" (L : UNSIGNED, R : NATURAL), there is no function + with R : INTEGER argument
+ ELSE
+ v_dec := dec;
+ RETURN STD_LOGIC_VECTOR(UNSIGNED(vec) + v_dec); -- uses function "+" (L : UNSIGNED, R : NATURAL)
+ END IF;
+ END;
+
+ FUNCTION INCR_UVEC(vec : STD_LOGIC_VECTOR; dec : UNSIGNED) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN STD_LOGIC_VECTOR(UNSIGNED(vec) + dec);
+ END;
+
+ FUNCTION INCR_SVEC(vec : STD_LOGIC_VECTOR; dec : INTEGER) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_dec : INTEGER;
+ BEGIN
+ RETURN STD_LOGIC_VECTOR(SIGNED(vec) + v_dec); -- uses function "+" (L : SIGNED, R : INTEGER)
+ END;
+
+ FUNCTION INCR_SVEC(vec : STD_LOGIC_VECTOR; dec : SIGNED) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN STD_LOGIC_VECTOR(SIGNED(vec) + dec);
+ END;
+
+ FUNCTION ADD_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN STD_LOGIC_VECTOR(RESIZE_NUM(SIGNED(l_vec), res_w) + SIGNED(r_vec));
+ END;
+
+ FUNCTION SUB_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN STD_LOGIC_VECTOR(RESIZE_NUM(SIGNED(l_vec), res_w) - SIGNED(r_vec));
+ END;
+
+ FUNCTION ADD_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN STD_LOGIC_VECTOR(RESIZE_NUM(UNSIGNED(l_vec), res_w) + UNSIGNED(r_vec));
+ END;
+
+ FUNCTION SUB_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR; res_w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN STD_LOGIC_VECTOR(RESIZE_NUM(UNSIGNED(l_vec), res_w) - UNSIGNED(r_vec));
+ END;
+
+ FUNCTION ADD_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN ADD_SVEC(l_vec, r_vec, l_vec'LENGTH);
+ END;
+
+ FUNCTION SUB_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN SUB_SVEC(l_vec, r_vec, l_vec'LENGTH);
+ END;
+
+ FUNCTION ADD_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN ADD_UVEC(l_vec, r_vec, l_vec'LENGTH);
+ END;
+
+ FUNCTION SUB_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN SUB_UVEC(l_vec, r_vec, l_vec'LENGTH);
+ END;
+
+ FUNCTION COMPLEX_MULT_REAL(a_re, a_im, b_re, b_im : INTEGER) RETURN INTEGER IS
+ BEGIN
+ RETURN (a_re * b_re - a_im * b_im);
+ END;
+
+ FUNCTION COMPLEX_MULT_IMAG(a_re, a_im, b_re, b_im : INTEGER) RETURN INTEGER IS
+ BEGIN
+ RETURN (a_im * b_re + a_re * b_im);
+ END;
+
+ FUNCTION S_ADD_OVFLW_DET(a, b, sum_a_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC is
+ VARIABLE a_sign : SIGNED(a'RANGE) := SIGNED(a);
+ VARIABLE b_sign : SIGNED(a'RANGE) := SIGNED(b);
+ VARIABLE sum_a_b_sign : SIGNED(sum_a_b'RANGE) := SIGNED(sum_a_b);
+ BEGIN
+ IF (a_sign >= 0 xor b_sign >= 0) THEN
+ RETURN '0'; -- no overflow from addition can occur when signed values have different signs
+ ELSIF (sum_a_b_sign >= 0 xor a_sign >= 0) THEN -- signs are same so use either a_sign|b_sign
+ RETURN '1'; -- overflow has occured - note sum wrapped to a different sign than inputs
+ ELSE
+ RETURN '0';
+ END IF;
+ END;
+
+ FUNCTION S_SUB_OVFLW_DET(a, b, sub_a_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC is
+ VARIABLE a_sign : SIGNED(a'RANGE) := SIGNED(a);
+ VARIABLE b_sign : SIGNED(a'RANGE) := SIGNED(b);
+ VARIABLE sub_a_b_sign : SIGNED(sub_a_b'RANGE) := SIGNED(sub_a_b);
+ BEGIN
+ IF not (a_sign >= 0 xor b_sign >= 0) THEN
+ RETURN '0'; -- no overflow from subtraction can occur when signed values have same signs
+ ELSIF not (sub_a_b_sign >= 0 xor b_sign >= 0) THEN
+ RETURN '1'; -- overflow occurs if the result has the same sign as the subtrahend
+ ELSE
+ RETURN '0';
+ END IF;
+ END;
+
+ FUNCTION SHIFT_UVEC(vec : STD_LOGIC_VECTOR; shift : INTEGER) RETURN STD_LOGIC_VECTOR is
+ BEGIN
+ IF shift < 0 THEN
+ RETURN STD_LOGIC_VECTOR(SHIFT_LEFT(UNSIGNED(vec), -shift)); -- fill zeros from right
+ ELSE
+ RETURN STD_LOGIC_VECTOR(SHIFT_RIGHT(UNSIGNED(vec), shift)); -- fill zeros from left
+ END IF;
+ END;
+
+ FUNCTION SHIFT_SVEC(vec : STD_LOGIC_VECTOR; shift : INTEGER) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ IF shift < 0 THEN
+ RETURN STD_LOGIC_VECTOR(SHIFT_LEFT(SIGNED(vec), -shift)); -- same as SHIFT_LEFT for UNSIGNED
+ ELSE
+ RETURN STD_LOGIC_VECTOR(SHIFT_RIGHT(SIGNED(vec), shift)); -- extend sign
+ END IF;
+ END;
+
+ --
+ -- offset_binary() : maps offset binary to or from two-complement binary.
+ --
+ -- National ADC08DC1020 offset binary two-complement binary
+ -- + full scale = 127.5 : 11111111 = 255 127 = 01111111
+ -- ...
+ -- + = +0.5 : 10000000 = 128 0 = 00000000
+ -- 0
+ -- - = -0.5 : 01111111 = 127 -1 = 11111111
+ -- ...
+ -- - full scale = -127.5 : 00000000 = 0 -128 = 10000000
+ --
+ -- To map between the offset binary and two complement binary involves
+ -- adding 128 to the binary value or equivalently inverting the sign bit.
+ -- The offset_binary() mapping can be done and undone both ways.
+ -- The offset_binary() mapping to two-complement binary yields a DC offset
+ -- of -0.5 Lsb.
+ FUNCTION offset_binary(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_res : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0) := a;
+ BEGIN
+ v_res(v_res'HIGH) := NOT v_res(v_res'HIGH); -- invert MSbit to get to from offset binary to two's complement, or vice versa
+ RETURN v_res;
+ END;
+
+ FUNCTION truncate(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ CONSTANT c_vec_w : NATURAL := vec'LENGTH;
+ CONSTANT c_trunc_w : NATURAL := c_vec_w - n;
+ VARIABLE v_vec : STD_LOGIC_VECTOR(c_vec_w - 1 DOWNTO 0) := vec;
+ VARIABLE v_res : STD_LOGIC_VECTOR(c_trunc_w - 1 DOWNTO 0);
+ BEGIN
+ v_res := v_vec(c_vec_w - 1 DOWNTO n); -- keep MS part
+ RETURN v_res;
+ END;
+
+ FUNCTION truncate_and_resize_uvec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ CONSTANT c_vec_w : NATURAL := vec'LENGTH;
+ CONSTANT c_trunc_w : NATURAL := c_vec_w - n;
+ VARIABLE v_trunc : STD_LOGIC_VECTOR(c_trunc_w - 1 DOWNTO 0);
+ VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
+ BEGIN
+ v_trunc := truncate(vec, n); -- first keep MS part
+ v_res := RESIZE_UVEC(v_trunc, w); -- then keep LS part or left extend with '0'
+ RETURN v_res;
+ END;
+
+ FUNCTION truncate_and_resize_svec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ CONSTANT c_vec_w : NATURAL := vec'LENGTH;
+ CONSTANT c_trunc_w : NATURAL := c_vec_w - n;
+ VARIABLE v_trunc : STD_LOGIC_VECTOR(c_trunc_w - 1 DOWNTO 0);
+ VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
+ BEGIN
+ v_trunc := truncate(vec, n); -- first keep MS part
+ v_res := RESIZE_SVEC(v_trunc, w); -- then keep sign bit and LS part or left extend sign bit
+ RETURN v_res;
+ END;
+
+ FUNCTION scale(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ CONSTANT c_vec_w : NATURAL := vec'LENGTH;
+ CONSTANT c_scale_w : NATURAL := c_vec_w + n;
+ VARIABLE v_res : STD_LOGIC_VECTOR(c_scale_w - 1 DOWNTO 0) := (OTHERS => '0');
+ BEGIN
+ v_res(c_scale_w - 1 DOWNTO n) := vec; -- scale by adding n zero bits at the right
+ RETURN v_res;
+ END;
+
+ FUNCTION scale_and_resize_uvec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ CONSTANT c_vec_w : NATURAL := vec'LENGTH;
+ CONSTANT c_scale_w : NATURAL := c_vec_w + n;
+ VARIABLE v_scale : STD_LOGIC_VECTOR(c_scale_w - 1 DOWNTO 0) := (OTHERS => '0');
+ VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
+ BEGIN
+ v_scale(c_scale_w - 1 DOWNTO n) := vec; -- first scale by adding n zero bits at the right
+ v_res := RESIZE_UVEC(v_scale, w); -- then keep LS part or left extend with '0'
+ RETURN v_res;
+ END;
+
+ FUNCTION scale_and_resize_svec(vec : STD_LOGIC_VECTOR; n, w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ CONSTANT c_vec_w : NATURAL := vec'LENGTH;
+ CONSTANT c_scale_w : NATURAL := c_vec_w + n;
+ VARIABLE v_scale : STD_LOGIC_VECTOR(c_scale_w - 1 DOWNTO 0) := (OTHERS => '0');
+ VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
+ BEGIN
+ v_scale(c_scale_w - 1 DOWNTO n) := vec; -- first scale by adding n zero bits at the right
+ v_res := RESIZE_SVEC(v_scale, w); -- then keep LS part or left extend sign bit
+ RETURN v_res;
+ END;
+
+ FUNCTION truncate_or_resize_uvec(vec : STD_LOGIC_VECTOR; b : BOOLEAN; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ CONSTANT c_vec_w : NATURAL := vec'LENGTH;
+ VARIABLE c_n : INTEGER := c_vec_w - w;
+ VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
+ BEGIN
+ IF b = TRUE AND c_n > 0 THEN
+ v_res := truncate_and_resize_uvec(vec, c_n, w);
+ ELSE
+ v_res := RESIZE_UVEC(vec, w);
+ END IF;
+ RETURN v_res;
+ END;
+
+ FUNCTION truncate_or_resize_svec(vec : STD_LOGIC_VECTOR; b : BOOLEAN; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ CONSTANT c_vec_w : NATURAL := vec'LENGTH;
+ VARIABLE c_n : INTEGER := c_vec_w - w;
+ VARIABLE v_res : STD_LOGIC_VECTOR(w - 1 DOWNTO 0);
+ BEGIN
+ IF b = TRUE AND c_n > 0 THEN
+ v_res := truncate_and_resize_svec(vec, c_n, w);
+ ELSE
+ v_res := RESIZE_SVEC(vec, w);
+ END IF;
+ RETURN v_res;
+ END;
+
+ -- Functions s_round, s_round_up and u_round:
+ --
+ -- . The returned output width is input width - n.
+ -- . If n=0 then the return value is the same as the input value so only
+ -- wires (NOP, no operation).
+ -- . Both have the same implementation but different c_max and c_clip values.
+ -- . Round up for unsigned so +2.5 becomes 3
+
+ -- Round away from zero was previously implemented here, but for DSP applications
+ -- Round Away from zero can cause a noticable dc bias when using large FFTs and/or doing correlation.
+ -- A more appopriate rounding logic is to use round to nearest even for DSP
+ --
+ -- Generates rounding logic when there is bits to round off
+ -- Round nearest Even does the following assuming two fractional bits and two integer bits
+ -- with an output of no fractional and two integer bits.
+ -- # Binary Round out
+ -- -1.75 "10.01" -2 "10"
+ -- -1.5 "10.10" -2 "10"
+ -- -1.25 "10.11" -1 "11"
+ -- -1.00 "11.00" -1 "11"
+ -- -0.75 "11.01" -1 "11"
+ -- -0.5 "11.10" 0 "00"
+ -- -0.25 "11.11" 0 "00"
+ -- 0.00 "00.00" 0 "00"
+ -- 0.25 "00.01" 0 "00"
+ -- 0.50 "00.10" 0 "00"
+ -- 0.75 "00.11" 1 "01"
+ -- 1.00 "01.00" 1 "01"
+ -- 1.25 "01.01" 1 "01"
+ -- 1.5 "01.10" 2 "10"
+ -- 1.75 "01.11" 2 "10"
+
+ -- . Rounding can cause an increase to the integer part, use clip = TRUE to
+ -- clip the potential overflow due to adding 0.5 to +max.
+ -- . For negative values overflow due to rounding can not occur, because c_half-1 >= 0 for n>0
+ -- . If the input comes from a product and is rounded to the input width then
+ -- clip can safely be FALSE, because e.g. for unsigned 4b*4b=8b->4b the
+ -- maximum product is 15*15=225 <= 255-8, and for signed 4b*4b=8b->4b the
+ -- maximum product is -8*-8=+64 <= 127-8, so wrapping due to rounding
+ -- overflow will never occur.
+
+ FUNCTION s_round_inf(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR IS
+ -- Use SIGNED to avoid NATURAL (32 bit range) overflow error
+ CONSTANT c_in_w : NATURAL := vec'LENGTH;
+ CONSTANT c_out_w : NATURAL := vec'LENGTH - n;
+ CONSTANT c_one : SIGNED(c_in_w - 1 DOWNTO 0) := TO_SIGNED(1, c_in_w);
+ CONSTANT c_half : SIGNED(c_in_w - 1 DOWNTO 0) := SHIFT_LEFT(c_one, n - 1); -- = 2**(n-1)
+ CONSTANT c_max : SIGNED(c_in_w - 1 DOWNTO 0) := SIGNED('0' & c_slv1(c_in_w - 2 DOWNTO 0)) - c_half; -- = 2**(c_in_w-1)-1 - c_half
+ CONSTANT c_clip : SIGNED(c_out_w - 1 DOWNTO 0) := SIGNED('0' & c_slv1(c_out_w - 2 DOWNTO 0)); -- = 2**(c_out_w-1)-1
+ VARIABLE v_in : SIGNED(c_in_w - 1 DOWNTO 0);
+ VARIABLE v_out : SIGNED(c_out_w - 1 DOWNTO 0);
+ BEGIN
+ v_in := SIGNED(vec);
+ IF n > 0 THEN
+ IF clip AND v_in > c_max THEN
+ v_out := c_clip; -- Round clip to maximum positive to avoid wrap to negative
+ ELSE
+ IF vec(vec'HIGH) = '0' THEN
+ v_out := RESIZE_NUM(SHIFT_RIGHT(v_in + c_half + 0, n), c_out_w); -- Round up for positive
+ ELSE
+ v_out := RESIZE_NUM(SHIFT_RIGHT(v_in + c_half - 1, n), c_out_w); -- Round down for negative
+ END IF;
+ END IF;
+ ELSE
+ v_out := RESIZE_NUM(v_in, c_out_w); -- NOP
+ END IF;
+ RETURN STD_LOGIC_VECTOR(v_out);
+ END;
+
+ FUNCTION s_round(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN; round_style : t_rounding_mode) RETURN STD_LOGIC_VECTOR IS
+ -- Use SIGNED to avoid NATURAL (32 bit range) overflow error
+ CONSTANT c_out_w : NATURAL := vec'LENGTH - n;
+ variable input_data_fixed : sfixed(c_out_w - 1 downto (-n)); -- we will use Fixed Point Lib in VHDL 2008 to do the calcs
+ variable output_data_fixed : sfixed(c_out_w - 1 downto 0);
+ BEGIN
+ input_data_fixed := sfixed(signed(vec));
+ --even rounding specified
+ if round_style = ROUND then
+ if clip then
+ output_data_fixed := resize(arg => input_data_fixed, size_res => output_data_fixed, overflow_style => fixed_saturate, round_style => fixed_round);
+ else
+ output_data_fixed := resize(arg => input_data_fixed, size_res => output_data_fixed, overflow_style => fixed_wrap, round_style => fixed_round);
+ end if;
+ --infinite rounding specified
+ elsif round_style = ROUNDINF then
+ RETURN s_round_inf(vec => vec, n => n, clip => clip);
+ else
+ RETURN truncate(vec, n);
+ end if;
+ RETURN to_slv(output_data_fixed);
+ END;
+
+ FUNCTION s_round(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN s_round(vec, n, FALSE, ROUND); -- no even-round clip
+ END;
+
+ -- An alternative is to always round up, also for negative numbers (i.e. s_round_up = u_round).
+ FUNCTION s_round_up(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN u_round(vec, n, clip);
+ END;
+
+ FUNCTION s_round_up(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN u_round(vec, n, FALSE); -- no round clip
+ END;
+
+ -- Unsigned numbers are round up (almost same as s_round, but without the else on negative vec)
+ FUNCTION u_round(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR IS
+ -- Use UNSIGNED to avoid NATURAL (32 bit range) overflow error
+ CONSTANT c_in_w : NATURAL := vec'LENGTH;
+ CONSTANT c_out_w : NATURAL := vec'LENGTH - n;
+ CONSTANT c_one : UNSIGNED(c_in_w - 1 DOWNTO 0) := TO_UNSIGNED(1, c_in_w);
+ CONSTANT c_half : UNSIGNED(c_in_w - 1 DOWNTO 0) := SHIFT_LEFT(c_one, n - 1); -- = 2**(n-1)
+ CONSTANT c_max : UNSIGNED(c_in_w - 1 DOWNTO 0) := UNSIGNED(c_slv1(c_in_w - 1 DOWNTO 0)) - c_half; -- = 2**c_in_w-1 - c_half
+ CONSTANT c_clip : UNSIGNED(c_out_w - 1 DOWNTO 0) := UNSIGNED(c_slv1(c_out_w - 1 DOWNTO 0)); -- = 2**c_out_w-1
+ VARIABLE v_in : UNSIGNED(c_in_w - 1 DOWNTO 0);
+ VARIABLE v_out : UNSIGNED(c_out_w - 1 DOWNTO 0);
+ BEGIN
+ v_in := UNSIGNED(vec);
+ IF n > 0 THEN
+ IF clip AND v_in > c_max THEN
+ v_out := c_clip; -- Round clip to +max to avoid wrap to 0
+ ELSE
+ v_out := RESIZE_NUM(SHIFT_RIGHT(v_in + c_half, n), c_out_w); -- Round up
+ END IF;
+ ELSE
+ v_out := RESIZE_NUM(v_in, c_out_w); -- NOP
+ END IF;
+ RETURN STD_LOGIC_VECTOR(v_out);
+ END;
+
+ FUNCTION u_round(vec : STD_LOGIC_VECTOR; n : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN u_round(vec, n, FALSE); -- no round clip
+ END;
+
+ FUNCTION u_to_s(u : NATURAL; w : NATURAL) RETURN INTEGER IS
+ VARIABLE v_u : STD_LOGIC_VECTOR(31 DOWNTO 0) := TO_UVEC(u, 32); -- via 32 bit word to avoid NUMERIC_STD.TO_SIGNED: vector truncated warming
+ BEGIN
+ RETURN TO_SINT(v_u(w - 1 DOWNTO 0));
+ END;
+
+ FUNCTION s_to_u(s : INTEGER; w : NATURAL) RETURN NATURAL IS
+ VARIABLE v_s : STD_LOGIC_VECTOR(31 DOWNTO 0) := TO_SVEC(s, 32); -- via 32 bit word to avoid NUMERIC_STD.TO_SIGNED: vector truncated warming
+ BEGIN
+ RETURN TO_UINT(v_s(w - 1 DOWNTO 0));
+ END;
+
+ FUNCTION u_wrap(u : NATURAL; w : NATURAL) RETURN NATURAL IS
+ VARIABLE v_u : STD_LOGIC_VECTOR(31 DOWNTO 0) := TO_UVEC(u, 32); -- via 32 bit word to avoid NUMERIC_STD.TO_SIGNED: vector truncated warming
+ BEGIN
+ RETURN TO_UINT(v_u(w - 1 DOWNTO 0));
+ END;
+
+ FUNCTION s_wrap(s : INTEGER; w : NATURAL) RETURN INTEGER IS
+ VARIABLE v_s : STD_LOGIC_VECTOR(31 DOWNTO 0) := TO_SVEC(s, 32); -- via 32 bit word to avoid NUMERIC_STD.TO_SIGNED: vector truncated warming
+ BEGIN
+ RETURN TO_SINT(v_s(w - 1 DOWNTO 0));
+ END;
+
+ FUNCTION u_clip(u : NATURAL; max : NATURAL) RETURN NATURAL IS
+ BEGIN
+ IF u > max THEN
+ RETURN max;
+ ELSE
+ RETURN u;
+ END IF;
+ END;
+
+ FUNCTION s_clip(s : INTEGER; max : NATURAL; min : INTEGER) RETURN INTEGER IS
+ BEGIN
+ IF s < min THEN
+ RETURN min;
+ ELSE
+ IF s > max THEN
+ RETURN max;
+ ELSE
+ RETURN s;
+ END IF;
+ END IF;
+ END;
+
+ FUNCTION s_clip(s : INTEGER; max : NATURAL) RETURN INTEGER IS
+ BEGIN
+ RETURN s_clip(s, max, -max);
+ END;
+
+ FUNCTION hton(a : STD_LOGIC_VECTOR; w, sz : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_a : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0) := a; -- map a to range [h:0]
+ VARIABLE v_b : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0) := a; -- default b = a
+ VARIABLE vL : NATURAL;
+ VARIABLE vK : NATURAL;
+ BEGIN
+ -- Note:
+ -- . if sz = 1 then v_b = v_a
+ -- . if a'LENGTH > sz*w then v_b(a'LENGTH:sz*w) = v_a(a'LENGTH:sz*w)
+ FOR vL IN 0 TO sz - 1 LOOP
+ vK := sz - 1 - vL;
+ v_b((vL + 1) * w - 1 DOWNTO vL * w) := v_a((vK + 1) * w - 1 DOWNTO vK * w);
+ END LOOP;
+ RETURN v_b;
+ END FUNCTION;
+
+ FUNCTION hton(a : STD_LOGIC_VECTOR; sz : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN hton(a, c_byte_w, sz); -- symbol width w = c_byte_w = 8
+ END FUNCTION;
+
+ FUNCTION hton(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ CONSTANT c_sz : NATURAL := a'LENGTH / c_byte_w;
+ BEGIN
+ RETURN hton(a, c_byte_w, c_sz); -- symbol width w = c_byte_w = 8
+ END FUNCTION;
+
+ FUNCTION ntoh(a : STD_LOGIC_VECTOR; sz : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN hton(a, sz); -- i.e. ntoh() = hton()
+ END FUNCTION;
+
+ FUNCTION ntoh(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ BEGIN
+ RETURN hton(a); -- i.e. ntoh() = hton()
+ END FUNCTION;
+
+ FUNCTION flip(a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_a : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0) := a;
+ VARIABLE v_b : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ FOR I IN v_a'RANGE LOOP
+ v_b(a'LENGTH - 1 - I) := v_a(I);
+ END LOOP;
+ RETURN v_b;
+ END;
+
+ FUNCTION flip(a, w : NATURAL) RETURN NATURAL IS
+ BEGIN
+ RETURN TO_UINT(flip(TO_UVEC(a, w)));
+ END;
+
+ FUNCTION flip(a : t_slv_32_arr) RETURN t_slv_32_arr IS
+ VARIABLE v_a : t_slv_32_arr(a'LENGTH - 1 DOWNTO 0) := a;
+ VARIABLE v_b : t_slv_32_arr(a'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ FOR I IN v_a'RANGE LOOP
+ v_b(a'LENGTH - 1 - I) := v_a(I);
+ END LOOP;
+ RETURN v_b;
+ END;
+
+ FUNCTION flip(a : t_integer_arr) RETURN t_integer_arr IS
+ VARIABLE v_a : t_integer_arr(a'LENGTH - 1 DOWNTO 0) := a;
+ VARIABLE v_b : t_integer_arr(a'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ FOR I IN v_a'RANGE LOOP
+ v_b(a'LENGTH - 1 - I) := v_a(I);
+ END LOOP;
+ RETURN v_b;
+ END;
+
+ FUNCTION flip(a : t_natural_arr) RETURN t_natural_arr IS
+ VARIABLE v_a : t_natural_arr(a'LENGTH - 1 DOWNTO 0) := a;
+ VARIABLE v_b : t_natural_arr(a'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ FOR I IN v_a'RANGE LOOP
+ v_b(a'LENGTH - 1 - I) := v_a(I);
+ END LOOP;
+ RETURN v_b;
+ END;
+
+ FUNCTION flip(a : t_nat_natural_arr) RETURN t_nat_natural_arr IS
+ VARIABLE v_a : t_nat_natural_arr(a'LENGTH - 1 DOWNTO 0) := a;
+ VARIABLE v_b : t_nat_natural_arr(a'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ FOR I IN v_a'RANGE LOOP
+ v_b(a'LENGTH - 1 - I) := v_a(I);
+ END LOOP;
+ RETURN v_b;
+ END;
+
+ FUNCTION transpose(a : STD_LOGIC_VECTOR; row, col : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE vIn : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0);
+ VARIABLE vOut : STD_LOGIC_VECTOR(a'LENGTH - 1 DOWNTO 0);
+ BEGIN
+ vIn := a; -- map input vector to h:0 range
+ vOut := vIn; -- default leave any unused MSbits the same
+ FOR J IN 0 TO row - 1 LOOP
+ FOR I IN 0 TO col - 1 LOOP
+ vOut(J * col + I) := vIn(I * row + J); -- transpose vector, map input index [i*row+j] to output index [j*col+i]
+ END LOOP;
+ END LOOP;
+ RETURN vOut;
+ END FUNCTION;
+
+ FUNCTION transpose(a, row, col : NATURAL) RETURN NATURAL IS -- transpose index a = [i*row+j] to output index [j*col+i]
+ VARIABLE vI : NATURAL;
+ VARIABLE vJ : NATURAL;
+ BEGIN
+ vI := a / row;
+ vJ := a MOD row;
+ RETURN vJ * col + vI;
+ END;
+
+ FUNCTION split_w(input_w : NATURAL; min_out_w : NATURAL; max_out_w : NATURAL) RETURN NATURAL IS -- Calculate input_w in multiples as close as possible to max_out_w
+ -- Examples: split_w(256, 8, 32) = 32; split_w(16, 8, 32) = 16; split_w(72, 8, 32) = 18; -- Input_w must be multiple of 2.
+ VARIABLE r : NATURAL;
+ BEGIN
+ r := input_w;
+ FOR i IN 1 TO ceil_log2(input_w) LOOP -- Useless to divide the number beyond this
+ IF r <= max_out_w AND r >= min_out_w THEN
+ RETURN r;
+ ELSIF i = ceil_log2(input_w) THEN -- last iteration
+ RETURN 0; -- Indicates wrong values were used
+ END IF;
+ r := r / 2;
+ END LOOP;
+ END;
+
+ FUNCTION pad(str : STRING; width : NATURAL; pad_char : CHARACTER) RETURN STRING IS
+ VARIABLE v_str : STRING(1 TO width) := (OTHERS => pad_char);
+ BEGIN
+ v_str(width - str'LENGTH + 1 TO width) := str;
+ RETURN v_str;
+ END;
+
+ FUNCTION slice_up(str : STRING; width : NATURAL; i : NATURAL) RETURN STRING IS
+ BEGIN
+ RETURN str(i * width + 1 TO (i + 1) * width);
+ END;
+
+ -- If the input value is not a multiple of the desired width, the return value is padded with
+ -- the passed pad value. E.g. if input='10' and desired width is 4, return value is '0010'.
+ FUNCTION slice_up(str : STRING; width : NATURAL; i : NATURAL; pad_char : CHARACTER) RETURN STRING IS
+ VARIABLE padded_str : STRING(1 TO width) := (OTHERS => '0');
+ BEGIN
+ padded_str := pad(str(i * width + 1 TO (i + 1) * width), width, '0');
+ RETURN padded_str;
+ END;
+
+ FUNCTION slice_dn(str : STRING; width : NATURAL; i : NATURAL) RETURN STRING IS
+ BEGIN
+ RETURN str((i + 1) * width - 1 DOWNTO i * width);
+ END;
+
+ FUNCTION nat_arr_to_concat_slv(nat_arr : t_natural_arr; nof_elements : NATURAL) RETURN STD_LOGIC_VECTOR IS
+ VARIABLE v_concat_slv : STD_LOGIC_VECTOR(nof_elements * 32 - 1 DOWNTO 0) := (OTHERS => '0');
+ BEGIN
+ FOR i IN 0 TO nof_elements - 1 LOOP
+ v_concat_slv(i * 32 + 32 - 1 DOWNTO i * 32) := TO_UVEC(nat_arr(i), 32);
+ END LOOP;
+ RETURN v_concat_slv;
+ END;
+
+ ------------------------------------------------------------------------------
+ -- common_fifo_*
+ ------------------------------------------------------------------------------
+
+ PROCEDURE proc_common_fifo_asserts(CONSTANT c_fifo_name : IN STRING;
+ CONSTANT c_note_is_ful : IN BOOLEAN;
+ CONSTANT c_fail_rd_emp : IN BOOLEAN;
+ SIGNAL wr_rst : IN STD_LOGIC;
+ SIGNAL wr_clk : IN STD_LOGIC;
+ SIGNAL wr_full : IN STD_LOGIC;
+ SIGNAL wr_en : IN STD_LOGIC;
+ SIGNAL rd_clk : IN STD_LOGIC;
+ SIGNAL rd_empty : IN STD_LOGIC;
+ SIGNAL rd_en : IN STD_LOGIC) IS
+ BEGIN
+ -- c_fail_rd_emp : when TRUE report FAILURE when read from an empty FIFO, important when FIFO rd_val is not used
+ -- c_note_is_ful : when TRUE report NOTE when FIFO goes full, to note that operation is on the limit
+ -- FIFO overflow is always reported as FAILURE
+
+ -- The FIFO wr_full goes high at reset to indicate that it can not be written and it goes low a few cycles after reset.
+ -- Therefore only check on wr_full going high when wr_rst='0'.
+
+ --synthesis translate_off
+ ASSERT NOT (c_fail_rd_emp = TRUE AND rising_edge(rd_clk) AND rd_empty = '1' AND rd_en = '1') REPORT c_fifo_name & " : read from empty fifo occurred!" SEVERITY FAILURE;
+ ASSERT NOT (c_note_is_ful = TRUE AND rising_edge(wr_full) AND wr_rst = '0') REPORT c_fifo_name & " : fifo is full now" SEVERITY NOTE;
+ ASSERT NOT (rising_edge(wr_clk) AND wr_full = '1' AND wr_en = '1') REPORT c_fifo_name & " : fifo overflow occurred!" SEVERITY FAILURE;
+ --synthesis translate_on
+ END PROCEDURE proc_common_fifo_asserts;
+
+ ------------------------------------------------------------------------------
+ -- common_fanout_tree
+ ------------------------------------------------------------------------------
+
+ FUNCTION func_common_fanout_tree_pipelining(c_nof_stages, c_nof_output_per_cell, c_nof_output : NATURAL;
+ c_cell_pipeline_factor_arr, c_cell_pipeline_arr : t_natural_arr) RETURN t_natural_arr IS
+ CONSTANT k_cell_pipeline_factor_arr : t_natural_arr(c_nof_stages - 1 DOWNTO 0) := c_cell_pipeline_factor_arr;
+ CONSTANT k_cell_pipeline_arr : t_natural_arr(c_nof_output_per_cell - 1 DOWNTO 0) := c_cell_pipeline_arr;
+ VARIABLE v_stage_pipeline_arr : t_natural_arr(c_nof_output - 1 DOWNTO 0) := (OTHERS => 0);
+ VARIABLE v_prev_stage_pipeline_arr : t_natural_arr(c_nof_output - 1 DOWNTO 0) := (OTHERS => 0);
+ BEGIN
+ loop_stage : FOR j IN 0 TO c_nof_stages - 1 LOOP
+ v_prev_stage_pipeline_arr := v_stage_pipeline_arr;
+ loop_cell : FOR i IN 0 TO c_nof_output_per_cell ** j - 1 LOOP
+ v_stage_pipeline_arr((i + 1) * c_nof_output_per_cell - 1 DOWNTO i * c_nof_output_per_cell) := v_prev_stage_pipeline_arr(i) + (k_cell_pipeline_factor_arr(j) * k_cell_pipeline_arr);
+ END LOOP;
+ END LOOP;
+ RETURN v_stage_pipeline_arr;
+ END FUNCTION func_common_fanout_tree_pipelining;
+
+ ------------------------------------------------------------------------------
+ -- common_reorder_symbol
+ ------------------------------------------------------------------------------
+
+ -- Determine whether the stage I and row J index refer to any (active or redundant) 2-input reorder cell instantiation
+ FUNCTION func_common_reorder2_is_there(I, J : NATURAL) RETURN BOOLEAN IS
+ VARIABLE v_odd : BOOLEAN;
+ VARIABLE v_even : BOOLEAN;
+ BEGIN
+ v_odd := (I MOD 2 = 1) AND (J MOD 2 = 1); -- for odd stage at each odd row
+ v_even := (I MOD 2 = 0) AND (J MOD 2 = 0); -- for even stage at each even row
+ RETURN v_odd OR v_even;
+ END func_common_reorder2_is_there;
+
+ -- Determine whether the stage I and row J index refer to an active 2-input reorder cell instantiation in a reorder network with N stages
+ FUNCTION func_common_reorder2_is_active(I, J, N : NATURAL) RETURN BOOLEAN IS
+ VARIABLE v_inst : BOOLEAN;
+ VARIABLE v_act : BOOLEAN;
+ BEGIN
+ v_inst := func_common_reorder2_is_there(I, J);
+ v_act := (I > 0) AND (I <= N) AND (J > 0) AND (J < N);
+ RETURN v_inst AND v_act;
+ END func_common_reorder2_is_active;
+
+ -- Get the index K in the select setting array for the reorder2 cell on stage I and row J in a reorder network with N stages
+ FUNCTION func_common_reorder2_get_select_index(I, J, N : NATURAL) RETURN INTEGER IS
+ CONSTANT c_nof_reorder2_per_odd_stage : NATURAL := N / 2;
+ CONSTANT c_nof_reorder2_per_even_stage : NATURAL := (N - 1) / 2;
+ VARIABLE v_nof_odd_stages : NATURAL;
+ VARIABLE v_nof_even_stages : NATURAL;
+ VARIABLE v_offset : NATURAL;
+ VARIABLE v_K : INTEGER;
+ BEGIN
+ -- for I, J that do not refer to an reorder cell instance for -1 as dummy return value.
+ -- for the redundant two port reorder cells at the border rows for -1 to indicate that the cell should pass on the input.
+ v_K := -1;
+ IF func_common_reorder2_is_active(I, J, N) THEN
+ -- for the active two port reorder cells use the setting at index v_K from the select setting array
+ v_nof_odd_stages := I / 2;
+ v_nof_even_stages := (I - 1) / 2;
+ v_offset := (J - 1) / 2; -- suits both odd stage and even stage
+ v_K := v_nof_odd_stages * c_nof_reorder2_per_odd_stage + v_nof_even_stages * c_nof_reorder2_per_even_stage + v_offset;
+ END IF;
+ RETURN v_K;
+ END func_common_reorder2_get_select_index;
+
+ -- Get the select setting for the reorder2 cell on stage I and row J in a reorder network with N stages
+ FUNCTION func_common_reorder2_get_select(I, J, N : NATURAL; select_arr : t_natural_arr) RETURN NATURAL IS
+ CONSTANT c_nof_select : NATURAL := select_arr'LENGTH;
+ CONSTANT c_select_arr : t_natural_arr(c_nof_select - 1 DOWNTO 0) := select_arr; -- force range downto 0
+ VARIABLE v_sel : NATURAL;
+ VARIABLE v_K : INTEGER;
+ BEGIN
+ v_sel := 0;
+ v_K := func_common_reorder2_get_select_index(I, J, N);
+ IF v_K >= 0 THEN
+ v_sel := c_select_arr(v_K);
+ END IF;
+ RETURN v_sel;
+ END func_common_reorder2_get_select;
+
+ -- Determine the inverse of a reorder network by using two reorder networks in series
+ FUNCTION func_common_reorder2_inverse_select(N : NATURAL; select_arr : t_natural_arr) RETURN t_natural_arr IS
+ CONSTANT c_nof_select : NATURAL := select_arr'LENGTH;
+ CONSTANT c_select_arr : t_natural_arr(c_nof_select - 1 DOWNTO 0) := select_arr; -- force range downto 0
+ VARIABLE v_sel : NATURAL;
+ VARIABLE v_Ki : INTEGER;
+ VARIABLE v_Ii : NATURAL;
+ VARIABLE v_inverse_arr : t_natural_arr(2 * c_nof_select - 1 DOWNTO 0) := (OTHERS => 0); -- default set identity for the reorder2 cells in both reorder instances
+ BEGIN
+ -- the inverse select consists of inverse_in reorder and inverse_out reorder in series
+ IF N MOD 2 = 1 THEN
+ -- N is odd so only need to fill in the inverse_in reorder, the inverse_out reorder remains at default pass on
+ FOR I IN 1 TO N LOOP
+ FOR J IN 0 TO N - 1 LOOP
+ -- get the DUT setting
+ v_sel := func_common_reorder2_get_select(I, J, N, c_select_arr);
+ -- map DUT I to inverse v_Ii stage index and determine the index for the inverse setting
+ v_Ii := 1 + N - I;
+ v_Ki := func_common_reorder2_get_select_index(v_Ii, J, N);
+ IF v_Ki >= 0 THEN
+ v_inverse_arr(v_Ki) := v_sel;
+ END IF;
+ END LOOP;
+ END LOOP;
+ ELSE
+ -- N is even so only use stage 1 of the inverse_out reorder, the other stages remain at default pass on
+ FOR K IN 0 TO N / 2 - 1 LOOP
+ v_Ki := c_nof_select + K; -- stage 1 of the inverse_out reorder
+ v_inverse_arr(v_Ki) := c_select_arr(K);
+ END LOOP;
+ -- N is even so leave stage 1 of the inverse_in reorder at default pass on, and do inverse the other stages
+ FOR I IN 2 TO N LOOP
+ FOR J IN 0 TO N - 1 LOOP
+ -- get the DUT setting
+ v_sel := func_common_reorder2_get_select(I, J, N, c_select_arr);
+ -- map DUT I to inverse v_Ii stage index and determine the index for the inverse setting
+ v_Ii := 2 + N - I;
+ v_Ki := func_common_reorder2_get_select_index(v_Ii, J, N);
+ IF v_Ki >= 0 THEN
+ v_inverse_arr(v_Ki) := v_sel;
+ END IF;
+ END LOOP;
+ END LOOP;
+ END IF;
+ RETURN v_inverse_arr;
+ END func_common_reorder2_inverse_select;
+
+ ------------------------------------------------------------------------------
+ -- PROCEDURE: Generate faster sample SCLK from digital DCLK for sim only
+ -- Description:
+ -- The SCLK kan be used to serialize Pfactor >= 1 symbols per word and then
+ -- view them in a scope component that is use internally in the design.
+ -- The scope component is only instantiated for simulation, to view the
+ -- serialized symbols, typically with decimal radix and analogue format.
+ -- The scope component will not be synthesized, because the SCLK can not
+ -- be synthesized.
+ --
+ -- Pfactor = 4
+ -- _______ _______ _______ _______
+ -- DCLK ___| |_______| |_______| |_______| |_______
+ -- ___________________ _ _ _ _ _ _ _ _ _ _ _ _
+ -- SCLK |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_|
+ --
+ -- The rising edges of SCLK occur after the rising edge of DCLK, to ensure
+ -- that they all apply to the same wide data word that was clocked by the
+ -- rising edge of the DCLK.
+ ------------------------------------------------------------------------------
+ PROCEDURE proc_common_dclk_generate_sclk(CONSTANT Pfactor : IN POSITIVE;
+ SIGNAL dclk : IN STD_LOGIC;
+ SIGNAL sclk : INOUT STD_LOGIC) IS
+ VARIABLE v_dperiod : TIME;
+ VARIABLE v_speriod : TIME;
+ BEGIN
+ SCLK <= '1';
+ -- Measure DCLK period
+ WAIT UNTIL rising_edge(DCLK);
+ v_dperiod := NOW;
+ WAIT UNTIL rising_edge(DCLK);
+ v_dperiod := NOW - v_dperiod;
+ v_speriod := v_dperiod / Pfactor;
+ -- Generate Pfactor SCLK periods per DCLK period
+ WHILE TRUE LOOP
+ -- Realign at every DCLK
+ WAIT UNTIL rising_edge(DCLK);
+ -- Create Pfactor SCLK periods within this DCLK period
+ SCLK <= '0';
+ IF Pfactor > 1 THEN
+ FOR I IN 0 TO 2 * Pfactor - 1 - 2 LOOP
+ WAIT FOR v_speriod / 2;
+ SCLK <= NOT SCLK;
+ END LOOP;
+ END IF;
+ WAIT FOR v_speriod / 2;
+ SCLK <= '1';
+ -- Wait for next DCLK
+ END LOOP;
+ WAIT;
+ END proc_common_dclk_generate_sclk;
+
+ function stringround_to_enum_round(stringin : string) return t_rounding_mode is
+ begin
+ -- use an ugly if because CASE expects string to always be the same length
+ if stringin = "ROUND" then
+ return ROUND;
+ elsif stringin = "ROUNDINF" then
+ return ROUNDINF;
+ else
+ return TRUNCATE;
+ end if;
+ end function stringround_to_enum_round;
+END common_pkg;
diff --git a/common_pkg/fixed_float_types_c.vhd b/common_pkg/fixed_float_types_c.vhd
new file mode 100644
index 00000000..0e13a196
--- /dev/null
+++ b/common_pkg/fixed_float_types_c.vhd
@@ -0,0 +1,35 @@
+-- --------------------------------------------------------------------
+-- "fixed_float_types" package contains types used in the fixed and floating
+-- point packages..
+-- Please see the documentation for the floating point package.
+-- This package should be compiled into "ieee_proposed" and used as follows:
+--
+-- This verison is designed to work with the VHDL-93 compilers. Please
+-- note the "%%%" comments. These are where we diverge from the
+-- VHDL-200X LRM.
+--
+-- --------------------------------------------------------------------
+-- Version : $Revision: 1.2 $
+-- Date : $Date: 2011/03/24 07:44:24 $
+-- --------------------------------------------------------------------
+
+package common_fixed_float_types is
+
+ -- Types used for generics of fixed_generic_pkg
+
+ type com_fixed_round_style_type is (fixed_round, fixed_truncate);
+
+ type com_fixed_overflow_style_type is (fixed_saturate, fixed_wrap);
+
+ -- Type used for generics of float_generic_pkg
+
+ -- These are the same as the C FE_TONEAREST, FE_UPWARD, FE_DOWNWARD,
+ -- and FE_TOWARDZERO floating point rounding macros.
+
+ type com_round_type is (round_nearest, -- Default, nearest LSB '0'
+ round_inf, -- Round toward positive infinity
+ round_neginf, -- Round toward negative infinity
+ round_zero); -- Round toward zero (truncate)
+
+end package common_fixed_float_types;
+
diff --git a/common_pkg/fixed_generic_pkg_2008redirect.vhdl b/common_pkg/fixed_generic_pkg_2008redirect.vhdl
new file mode 100755
index 00000000..bd3a6b8b
--- /dev/null
+++ b/common_pkg/fixed_generic_pkg_2008redirect.vhdl
@@ -0,0 +1,7758 @@
+-- -----------------------------------------------------------------
+--
+-- Copyright 2019 IEEE P1076 WG Authors
+--
+-- See the LICENSE file distributed with this work for copyright and
+-- licensing information and the AUTHORS file.
+--
+-- This file to you under the Apache License, Version 2.0 (the "License").
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+-- implied. See the License for the specific language governing
+-- permissions and limitations under the License.
+--
+-- Title : Fixed-point package (Generic package declaration)
+-- :
+-- Library : This package shall be compiled into a library
+-- : symbolically named IEEE.
+-- :
+-- Developers: Accellera VHDL-TC and IEEE P1076 Working Group
+-- :
+-- Purpose : This packages defines basic binary fixed point
+-- : arithmetic functions
+-- :
+-- 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) $
+-- --------------------------------------------------------------------
+
+use STD.TEXTIO.all;
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.NUMERIC_STD.all;
+library common_pkg_lib;
+use common_pkg_lib.common_fixed_float_types.all;
+use ieee.math_real.all;
+
+package fixed_generic_pkg is
+ generic (
+ -- Rounding routine to use in fixed point, fixed_round or fixed_truncate
+ fixed_round_style : com_fixed_round_style_type := fixed_round;
+ -- Overflow routine to use in fixed point, fixed_saturate or fixed_wrap
+ fixed_overflow_style : com_fixed_overflow_style_type := fixed_saturate;
+ -- Extra bits used in divide routines
+ fixed_guard_bits : NATURAL := 3;
+ -- If TRUE, then turn off warnings on "X" propagation
+ no_warning : BOOLEAN := false
+ );
+
+ -- Author David Bishop (dbishop@vhdl.org)
+ constant CopyRightNotice : STRING :=
+ "Copyright IEEE P1076 WG. Licensed Apache 2.0";
+
+ -- 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;
+
+ alias U_ufixed is UNRESOLVED_ufixed;
+ alias U_sfixed is UNRESOLVED_sfixed;
+
+ subtype ufixed is (resolved) UNRESOLVED_ufixed;
+ subtype sfixed is (resolved) 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 : com_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 : com_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 : com_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 : com_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 : com_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 : com_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 : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : UNRESOLVED_SIGNED) return UNRESOLVED_ufixed;
+ function scalb (y : UNRESOLVED_sfixed; N : INTEGER) return UNRESOLVED_sfixed;
+ function scalb (y : UNRESOLVED_sfixed; N : UNRESOLVED_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" (l : UNRESOLVED_ufixed) return STD_ULOGIC;
+ function "nand" (l : UNRESOLVED_ufixed) return STD_ULOGIC;
+ function "or" (l : UNRESOLVED_ufixed) return STD_ULOGIC;
+ function "nor" (l : UNRESOLVED_ufixed) return STD_ULOGIC;
+ function "xor" (l : UNRESOLVED_ufixed) return STD_ULOGIC;
+ function "xnor" (l : UNRESOLVED_ufixed) return STD_ULOGIC;
+ function "and" (l : UNRESOLVED_sfixed) return STD_ULOGIC;
+ function "nand" (l : UNRESOLVED_sfixed) return STD_ULOGIC;
+ function "or" (l : UNRESOLVED_sfixed) return STD_ULOGIC;
+ function "nor" (l : UNRESOLVED_sfixed) return STD_ULOGIC;
+ function "xor" (l : UNRESOLVED_sfixed) return STD_ULOGIC;
+ function "xnor" (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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : UNRESOLVED_UNSIGNED; -- unsigned
+ constant left_index : INTEGER; -- left index (high index)
+ constant right_index : INTEGER := 0; -- right index
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_ufixed;
+
+ function to_ufixed (
+ arg : UNRESOLVED_UNSIGNED; -- unsigned
+ size_res : UNRESOLVED_ufixed; -- for size only
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_ufixed;
+
+ -- Performs a conversion. ufixed (arg'range) is returned
+ function to_ufixed (
+ arg : UNRESOLVED_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_UNSIGNED;
+
+ -- unsigned fixed point to unsigned
+ function to_unsigned (
+ arg : UNRESOLVED_ufixed; -- fixed point input
+ size_res : UNRESOLVED_UNSIGNED; -- used for length of output
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style;
+ constant guard_bits : NATURAL := fixed_guard_bits)
+ return UNRESOLVED_sfixed;
+
+ -- signed to sfixed
+ function to_sfixed (
+ arg : UNRESOLVED_SIGNED; -- signed
+ constant left_index : INTEGER; -- left index (high index)
+ constant right_index : INTEGER := 0; -- right index
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_sfixed;
+
+ function to_sfixed (
+ arg : UNRESOLVED_SIGNED; -- signed
+ size_res : UNRESOLVED_sfixed; -- for size only
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : UNRESOLVED_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_SIGNED;
+
+ -- signed fixed point to signed
+ function to_signed (
+ arg : UNRESOLVED_sfixed; -- fixed point input
+ size_res : UNRESOLVED_SIGNED; -- used for length of output
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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;
+
+ --===========================================================================
+ -- 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];
+
+end package fixed_generic_pkg;
+
+package body fixed_generic_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;
+
+ -- 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_generic_pkg'instance_name
+ & " 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
+ begin -- function cleanvec
+ assert not (arg'ascending and (arg'low /= INTEGER'low))
+ report fixed_generic_pkg'instance_name
+ & " 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
+ begin -- function cleanvec
+ assert not (arg'ascending and (arg'low /= INTEGER'low))
+ report fixed_generic_pkg'instance_name
+ & " 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 : UNRESOLVED_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 : UNRESOLVED_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 UNRESOLVED_UNSIGNED
+ is
+ subtype t is UNRESOLVED_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 UNRESOLVED_SIGNED
+ is
+ subtype t is UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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 (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 : com_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 (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 : com_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 (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 intermediate_result : UNRESOLVED_ufixed(arg'length-1 downto 0);
+ begin
+ if arg'length < 1 then
+ return NSLV;
+ end if;
+ intermediate_result := arg;
+ return STD_ULOGIC_VECTOR (intermediate_result);
+ end function to_sulv;
+
+ function to_sulv (
+ arg : UNRESOLVED_sfixed) -- fixed point vector
+ return STD_ULOGIC_VECTOR
+ is
+ variable intermediate_result : UNRESOLVED_sfixed(arg'length-1 downto 0);
+ begin
+ if arg'length < 1 then
+ return NSLV;
+ end if;
+ intermediate_result := arg;
+ return STD_ULOGIC_VECTOR (intermediate_result);
+ end function to_sulv;
+
+ function to_slv (
+ arg : UNRESOLVED_ufixed) -- fixed point vector
+ return STD_LOGIC_VECTOR is
+ begin
+ return to_sulv(arg);
+ end function to_slv;
+
+ function to_slv (
+ arg : UNRESOLVED_sfixed) -- fixed point vector
+ return STD_LOGIC_VECTOR is
+ begin
+ return 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_generic_pkg'instance_name & "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 => UNRESOLVED_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_generic_pkg'instance_name & "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 => UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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 -- ufixed(max(a,c)+1 downto min(b,d))
+ is
+ 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 : UNRESOLVED_UNSIGNED (left_index-right_index
+ downto 0);
+ variable result_slv : UNRESOLVED_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 -- sfixed(max(a,c)+1 downto min(b,d))
+ is
+ 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 : UNRESOLVED_SIGNED (left_index-right_index downto 0);
+ variable result_slv : UNRESOLVED_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 -- ufixed(max(a,c)+1 downto min(b,d))
+ is
+ 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 : UNRESOLVED_UNSIGNED (left_index-right_index
+ downto 0);
+ variable result_slv : UNRESOLVED_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 -- sfixed(max(a,c)+1 downto min(b,d))
+ is
+ 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 : UNRESOLVED_SIGNED (left_index-right_index downto 0);
+ variable result_slv : UNRESOLVED_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 -- ufixed(a+c+1 downto b+d)
+ is
+ variable lslv : UNRESOLVED_UNSIGNED (l'length-1 downto 0);
+ variable rslv : UNRESOLVED_UNSIGNED (r'length-1 downto 0);
+ variable result_slv : UNRESOLVED_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 -- sfixed(a+c+1 downto b+d)
+ is
+ variable lslv : UNRESOLVED_SIGNED (l'length-1 downto 0);
+ variable rslv : UNRESOLVED_SIGNED (r'length-1 downto 0);
+ variable result_slv : UNRESOLVED_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 : com_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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ variable rslv : UNRESOLVED_UNSIGNED (r'length-1 downto 0);
+ variable result_slv : UNRESOLVED_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_generic_pkg'instance_name
+ & "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 : com_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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ variable rslv : UNRESOLVED_SIGNED (r'length-1 downto 0);
+ variable result_slv : UNRESOLVED_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_generic_pkg'instance_name
+ & "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 : com_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 : com_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 : com_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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ variable rslv : UNRESOLVED_UNSIGNED (rresize'length-1 downto 0);
+ variable result_slv : UNRESOLVED_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_generic_pkg'instance_name
+ & "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 : com_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 : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : UNRESOLVED_UNSIGNED (left_index-right_index
+ downto 0);
+ variable result_slv : UNRESOLVED_UNSIGNED (left_index-right_index
+ downto 0);
+ variable cx : UNRESOLVED_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-right_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 : UNRESOLVED_SIGNED (left_index-right_index
+ downto 0);
+ variable result_slv : UNRESOLVED_SIGNED (left_index-right_index
+ downto 0);
+ variable cx : UNRESOLVED_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-right_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 : UNRESOLVED_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 : UNRESOLVED_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 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 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 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 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 : UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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 : UNRESOLVED_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_generic_pkg'instance_name
+ & """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_generic_pkg'instance_name
+ & """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_generic_pkg'instance_name
+ & """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_generic_pkg'instance_name
+ & """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_generic_pkg'instance_name
+ & """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_generic_pkg'instance_name
+ & """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_generic_pkg'instance_name
+ & """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_generic_pkg'instance_name
+ & """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_generic_pkg'instance_name
+ & """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_generic_pkg'instance_name
+ & """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_generic_pkg'instance_name
+ & """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_generic_pkg'instance_name
+ & """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 operators
+ function "and" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
+ begin
+ return and to_sulv(l);
+ end function "and";
+
+ function "nand" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
+ begin
+ return nand to_sulv(l);
+ end function "nand";
+
+ function "or" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
+ begin
+ return or to_sulv(l);
+ end function "or";
+
+ function "nor" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
+ begin
+ return nor to_sulv(l);
+ end function "nor";
+
+ function "xor" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
+ begin
+ return xor to_sulv(l);
+ end function "xor";
+
+ function "xnor" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
+ begin
+ return xnor to_sulv(l);
+ end function "xnor";
+
+ function "and" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
+ begin
+ return and to_sulv(l);
+ end function "and";
+
+ function "nand" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
+ begin
+ return nand to_sulv(l);
+ end function "nand";
+
+ function "or" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
+ begin
+ return or to_sulv(l);
+ end function "or";
+
+ function "nor" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
+ begin
+ return nor to_sulv(l);
+ end function "nor";
+
+ function "xor" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
+ begin
+ return xor to_sulv(l);
+ end function "xor";
+
+ function "xnor" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
+ begin
+ return xnor to_sulv(l);
+ end function "xnor";
+ -- End reduction operators
+
+ 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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin -- ?=
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?="": 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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin -- ?/=
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?/="": 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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin -- ?>
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?>"": 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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin -- ?>=
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?>="": 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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin -- ?<
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?<"": 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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin -- ?<=
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?<="": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin -- ?=
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?="": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin -- ?/=
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?/="": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin -- ?>
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?>"": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin -- ?>=
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?>="": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin -- ?<
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?<"": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin -- ?<=
+ if ((L'length < 1) or (R'length < 1)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """?<="": 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_generic_pkg'instance_name
+ & "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_generic_pkg'instance_name
+ & "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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """="": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """="": 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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """/="": null argument detected, returning TRUE"
+ severity warning;
+ return true;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """/="": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """/="": null argument detected, returning TRUE"
+ severity warning;
+ return true;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """/="": 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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """>"": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """>"": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """>"": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """>"": 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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """<"": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """<"": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """<"": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """<"": 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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """>="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """>="": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """>="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """>="": 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 : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """<="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """<="": 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 : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
+ begin
+ if (l'length < 1 or r'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """<="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & """<="": 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);
+ return to_fixed(maximum(to_uns(lresize), to_uns(rresize)),
+ left_index, right_index);
+ 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);
+ return to_fixed(maximum(to_s(lresize), to_s(rresize)),
+ left_index, right_index);
+ 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);
+ return to_fixed(minimum(to_uns(lresize), to_uns(rresize)),
+ left_index, right_index);
+ 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);
+ return to_fixed(minimum(to_s(lresize), to_s(rresize)),
+ left_index, right_index);
+ 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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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_generic_pkg'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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_generic_pkg'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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;
+ begin
+ -- If negative or null range, return.
+ if (left_index < fw) then
+ return NAUF;
+ end if;
+ if (arg < 0.0) then
+ report fixed_generic_pkg'instance_name
+ & "TO_UFIXED: Negative argument passed "
+ & REAL'image(arg) severity error;
+ return result;
+ end if;
+ presult := arg;
+ if presult >= (2.0**(left_index+1)) then
+ assert no_warning report fixed_generic_pkg'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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_generic_pkg'instance_name
+ & "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 : UNRESOLVED_UNSIGNED; -- unsigned
+ constant left_index : INTEGER; -- left index (high index)
+ constant right_index : INTEGER := 0; -- right index
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_ufixed
+ is
+ constant ARG_LEFT : INTEGER := arg'length-1;
+ alias XARG : UNRESOLVED_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 : UNRESOLVED_UNSIGNED) -- unsigned
+ return UNRESOLVED_ufixed
+ is
+ constant ARG_LEFT : INTEGER := arg'length-1;
+ alias XARG : UNRESOLVED_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 : UNRESOLVED_SIGNED; -- signed
+ constant left_index : INTEGER; -- left index (high index)
+ constant right_index : INTEGER := 0; -- right index
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_sfixed
+ is
+ constant ARG_LEFT : INTEGER := arg'length-1;
+ alias XARG : UNRESOLVED_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 : UNRESOLVED_SIGNED) -- signed
+ return UNRESOLVED_sfixed
+ is
+ constant ARG_LEFT : INTEGER := arg'length-1;
+ alias XARG : UNRESOLVED_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_generic_pkg'instance_name
+ & "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_generic_pkg'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_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 : UNRESOLVED_UNSIGNED; -- length of output
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_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 : UNRESOLVED_SIGNED; -- used for length of output
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return UNRESOLVED_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_generic_pkg'instance_name
+ & "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_generic_pkg'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return NATURAL
+ is
+ constant left_index : INTEGER := arg'high;
+ variable arg_uns : UNRESOLVED_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_generic_pkg'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_fixed_round_style_type := fixed_round_style)
+ return INTEGER
+ is
+ constant left_index : INTEGER := arg'high;
+ variable arg_s : UNRESOLVED_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_generic_pkg'instance_name
+ & "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
+ begin
+ if (s'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & "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
+ begin
+ if (s'length < 1) then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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(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 (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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 (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 (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 (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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : UNRESOLVED_UNSIGNED; -- unsigned
+ size_res : UNRESOLVED_ufixed; -- for size only
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : UNRESOLVED_SIGNED; -- signed
+ size_res : UNRESOLVED_sfixed; -- for size only
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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;
+
+ -- copied from std_logic_textio
+ type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', error);
+ type char_indexed_by_MVL9 is array (STD_ULOGIC) of CHARACTER;
+ type MVL9_indexed_by_char is array (CHARACTER) of STD_ULOGIC;
+ type MVL9plus_indexed_by_char is array (CHARACTER) of MVL9plus;
+
+ constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-";
+ constant char_to_MVL9 : MVL9_indexed_by_char :=
+ ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
+ 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U');
+ constant char_to_MVL9plus : MVL9plus_indexed_by_char :=
+ ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
+ 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => error);
+ constant NBSP : CHARACTER := CHARACTER'val(160); -- space character
+ constant NUS : STRING(2 to 1) := (others => ' ');
+
+ -- purpose: Skips white space
+ procedure skip_whitespace (
+ L : inout LINE) is
+ variable c : CHARACTER;
+ variable left : positive;
+ begin
+ while L /= null and L.all'length /= 0 loop
+ left := L.all'left;
+ c := L.all(left);
+ if (c = ' ' or c = NBSP or c = HT) then
+ read (L, c);
+ else
+ exit;
+ end if;
+ end loop;
+ end procedure skip_whitespace;
+
+ -- 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_generic_pkg'instance_name & "READ(ufixed) "
+ & "End of string encountered"
+ severity error;
+ return;
+ elsif c = '_' then
+ if i = VALUE'high then
+ report fixed_generic_pkg'instance_name & "READ(ufixed) "
+ & "String begins with an ""_""" severity error;
+ return;
+ elsif lastu then
+ report fixed_generic_pkg'instance_name & "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_generic_pkg'instance_name & "READ(ufixed) "
+ & "Two binary points found in input string" severity error;
+ return;
+ elsif i /= -1 then -- Seperator in the wrong spot
+ report fixed_generic_pkg'instance_name & "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_generic_pkg'instance_name & "READ(ufixed) "
+ & "Short read, Space encounted in input string"
+ severity error;
+ return;
+ elsif char_to_MVL9plus(c) = error then
+ report fixed_generic_pkg'instance_name & "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_generic_pkg'instance_name & "READ(sfixed) "
+ & "End of string encountered"
+ severity error;
+ return;
+ elsif c = '_' then
+ if i = VALUE'high then
+ report fixed_generic_pkg'instance_name & "READ(sfixed) "
+ & "String begins with an ""_""" severity error;
+ return;
+ elsif lastu then
+ report fixed_generic_pkg'instance_name & "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_generic_pkg'instance_name & "READ(sfixed) "
+ & "Two binary points found in input string" severity error;
+ return;
+ elsif i /= -1 then -- Seperator in the wrong spot
+ report fixed_generic_pkg'instance_name & "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_generic_pkg'instance_name & "READ(sfixed) "
+ & "Short read, Space encounted in input string"
+ severity error;
+ return;
+ elsif char_to_MVL9plus(c) = error then
+ report fixed_generic_pkg'instance_name & "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;
+
+ -- 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 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_generic_pkg'instance_name
+ & "OREAD Error: Read a '" & C &
+ "', expected an Octal character (0-7)."
+ severity error;
+ RESULT := "UUU";
+ GOOD := false;
+ end case;
+ end procedure Char2TriBits;
+
+ -- 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_generic_pkg'instance_name
+ & "OREAD(sfixed) "
+ & mess
+ severity error;
+ else
+ report fixed_generic_pkg'instance_name
+ & "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 (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then
+ report fixed_generic_pkg'instance_name
+ & "OREAD(ufixed): Vector truncated."
+ severity error;
+ else
+ if (or (slv(VALUE'low-lbv-1 downto 0)) = '1') then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & "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 (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 (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or
+ (slv(VALUE'high-lbv) = '1' and
+ and (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then
+ report fixed_generic_pkg'instance_name
+ & "OREAD(sfixed): Vector truncated."
+ severity error;
+ else
+ if (or (slv(VALUE'low-lbv-1 downto 0)) = '1') then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & "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 (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or
+ (slv(VALUE'high-lbv) = '1' and
+ and (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;
+
+ -- 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_generic_pkg'instance_name
+ & "HREAD Error: Read a '" & C &
+ "', expected a Hex character (0-F)."
+ severity error;
+ RESULT := "UUUU";
+ GOOD := false;
+ end case;
+ end procedure Char2QuadBits;
+
+ -- purpose: Routines common to the HREAD 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_generic_pkg'instance_name
+ & "HREAD(sfixed) "
+ & mess
+ severity error;
+ else
+ report fixed_generic_pkg'instance_name
+ & "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 => true,
+ smath => false);
+ if igood then
+ if not ((i = -1) and -- We read everything, and high bits 0
+ (or (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then
+ report fixed_generic_pkg'instance_name
+ & "HREAD(ufixed): Vector truncated."
+ severity error;
+ else
+ if (or (slv(VALUE'low-lbv-1 downto 0)) = '1') then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & "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 (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 (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or
+ (slv(VALUE'high-lbv) = '1' and
+ and (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then
+ report fixed_generic_pkg'instance_name
+ & "HREAD(sfixed): Vector truncated."
+ severity error;
+ else
+ if (or (slv(VALUE'low-lbv-1 downto 0)) = '1') then
+ assert no_warning
+ report fixed_generic_pkg'instance_name
+ & "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 (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or
+ (slv(VALUE'high-lbv) = '1' and
+ and (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;
+
+ -- TO_STRING functions. Useful in "report" statements.
+ -- Example: report "result was " & TO_STRING(result);
+ 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_generic_pkg'instance_name
+ & "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_generic_pkg'instance_name
+ & "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_generic_pkg'instance_name
+ & "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_generic_pkg'instance_name
+ & "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_generic_pkg'instance_name
+ & "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_generic_pkg'instance_name
+ & "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;
+
+ -- 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.
+ -- 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_generic_pkg'instance_name
+ & "Found a space in the input STRING " & xarg
+ severity error;
+ elsif xarg(i) = '.' then
+ if founddot then
+ report fixed_generic_pkg'instance_name
+ & "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;
+
+end package body fixed_generic_pkg;
+
diff --git a/common_pkg/fixed_pkg_c.vhd b/common_pkg/fixed_pkg_c.vhd
new file mode 100644
index 00000000..95f20e41
--- /dev/null
+++ b/common_pkg/fixed_pkg_c.vhd
@@ -0,0 +1,8256 @@
+-- --------------------------------------------------------------------
+-- "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.3 $
+-- Date : $Date: 2011/03/24 07:44:24 $
+-- --------------------------------------------------------------------
+
+use STD.TEXTIO.all;
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.NUMERIC_STD.all;
+library common_pkg_lib;
+use common_pkg_lib.common_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 : com_fixed_round_style_type := fixed_round;
+ -- Overflow routine to use in fixed point, fixed_saturate or fixed_wrap
+ constant fixed_overflow_style : com_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 : com_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 : com_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 : com_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 : com_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 : com_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 : com_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 : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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
+
+
+
+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.3 $
+-- Date : $Date: 2011/03/24 07:44:24 $
+--
+-- 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') -- | - |
+ );
+
+ -------------------------------------------------------------------
+ -- ?= functions, Similar to "std_match", but returns "std_ulogic".
+ -------------------------------------------------------------------
+ function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is
+ begin
+ return match_logic_table (l, r);
+ end function \?=\;
+ function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is
+ begin
+ return not match_logic_table (l, r);
+ end function \?/=\;
+ -- "?=" operator is similar to "std_match", but returns a std_ulogic..
+ -- Id: M.2B
+ function \?=\ (L, R: UNSIGNED) return STD_ULOGIC is
+ constant L_LEFT : INTEGER := L'LENGTH-1;
+ constant R_LEFT : INTEGER := R'LENGTH-1;
+ alias XL : UNSIGNED(L_LEFT downto 0) is L;
+ alias XR : UNSIGNED(R_LEFT downto 0) is R;
+ constant SIZE : NATURAL := 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
+ result := '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'instance_name
+ & " 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'instance_name
+ & " 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'instance_name
+ & " 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 : com_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 : com_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 to_stdlogicvector(to_sulv(arg));
+ end function to_slv;
+
+ function to_slv (
+ arg : UNRESOLVED_sfixed) -- fixed point vector
+ return STD_LOGIC_VECTOR is
+ begin
+ return to_stdlogicvector(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'instance_name & "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'instance_name & "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 : com_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'instance_name
+ & "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 : com_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'instance_name
+ & "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 : com_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 : com_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 : com_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'instance_name
+ & "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 : com_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 : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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'instance_name
+ & """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'instance_name
+ & """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'instance_name
+ & """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'instance_name
+ & """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'instance_name
+ & """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'instance_name
+ & """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'instance_name
+ & """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'instance_name
+ & """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'instance_name
+ & """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'instance_name
+ & """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'instance_name
+ & """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'instance_name
+ & """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'instance_name
+ & """?="": 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'instance_name
+ & """?/="": 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'instance_name
+ & """?>"": 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'instance_name
+ & """?>="": 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'instance_name
+ & """?<"": 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'instance_name
+ & """?<="": 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'instance_name
+ & """?="": 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'instance_name
+ & """?/="": 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'instance_name
+ & """?>"": 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'instance_name
+ & """?>="": 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'instance_name
+ & """?<"": 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'instance_name
+ & """?<="": 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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & """="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """="": 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'instance_name
+ & """="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """="": 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'instance_name
+ & """/="": null argument detected, returning TRUE"
+ severity warning;
+ return true;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """/="": 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'instance_name
+ & """/="": null argument detected, returning TRUE"
+ severity warning;
+ return true;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """/="": 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'instance_name
+ & """>"": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """>"": 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'instance_name
+ & """>"": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """>"": 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'instance_name
+ & """<"": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """<"": 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'instance_name
+ & """<"": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """<"": 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'instance_name
+ & """>="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """>="": 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'instance_name
+ & """>="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """>="": 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'instance_name
+ & """<="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """<="": 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'instance_name
+ & """<="": null argument detected, returning FALSE"
+ severity warning;
+ return false;
+ elsif (Is_X(l) or Is_X(r)) then
+ assert NO_WARNING
+ report fixed_pkg'instance_name
+ & """<="": 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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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'instance_name
+ & "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'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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'instance_name
+ & "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'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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'instance_name
+ & "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'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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 : com_fixed_overflow_style_type := fixed_overflow_style;
+ constant round_style : com_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'instance_name
+ & "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'instance_name
+ & "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'instance_name & "READ(ufixed) "
+ & "End of string encountered"
+ severity error;
+ return;
+ elsif c = '_' then
+ if i = value'high then
+ report fixed_pkg'instance_name & "READ(ufixed) "
+ & "String begins with an ""_""" severity error;
+ return;
+ elsif lastu then
+ report fixed_pkg'instance_name & "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'instance_name & "READ(ufixed) "
+ & "Two binary points found in input string" severity error;
+ return;
+ elsif i /= -1 then -- Seperator in the wrong spot
+ report fixed_pkg'instance_name & "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'instance_name & "READ(ufixed) "
+ & "Short read, Space encounted in input string"
+ severity error;
+ return;
+ elsif char_to_MVL9plus(c) = error then
+ report fixed_pkg'instance_name & "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'instance_name & "READ(sfixed) "
+ & "End of string encountered"
+ severity error;
+ return;
+ elsif c = '_' then
+ if i = value'high then
+ report fixed_pkg'instance_name & "READ(sfixed) "
+ & "String begins with an ""_""" severity error;
+ return;
+ elsif lastu then
+ report fixed_pkg'instance_name & "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'instance_name & "READ(sfixed) "
+ & "Two binary points found in input string" severity error;
+ return;
+ elsif i /= -1 then -- Seperator in the wrong spot
+ report fixed_pkg'instance_name & "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'instance_name & "READ(sfixed) "
+ & "Short read, Space encounted in input string"
+ severity error;
+ return;
+ elsif char_to_MVL9plus(c) = error then
+ report fixed_pkg'instance_name & "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'instance_name
+ & "OREAD(sfixed) "
+ & mess
+ severity error;
+ else
+ report fixed_pkg'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "HREAD(sfixed) "
+ & mess
+ severity error;
+ else
+ report fixed_pkg'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "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'instance_name
+ & "Found a space in the input STRING " & xarg
+ severity error;
+ elsif xarg(i) = '.' then
+ if founddot then
+ report fixed_pkg'instance_name
+ & "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
+
+end package body fixed_pkg;
diff --git a/common_pkg/fixed_pkg_c_2008redirect.vhdl b/common_pkg/fixed_pkg_c_2008redirect.vhdl
new file mode 100755
index 00000000..922e71f4
--- /dev/null
+++ b/common_pkg/fixed_pkg_c_2008redirect.vhdl
@@ -0,0 +1,55 @@
+-- -----------------------------------------------------------------
+--
+-- Copyright 2019 IEEE P1076 WG Authors
+--
+-- See the LICENSE file distributed with this work for copyright and
+-- licensing information and the AUTHORS file.
+--
+-- This file to you under the Apache License, Version 2.0 (the "License").
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+-- implied. See the License for the specific language governing
+-- permissions and limitations under the License.
+--
+--
+-- Title : Fixed-point package (Instantiated package declaration)
+-- :
+-- Library : This package shall be compiled into a library
+-- : symbolically named IEEE.
+-- :
+-- Developers: Accellera VHDL-TC and IEEE P1076 Working Group
+-- :
+-- Purpose : This packages defines basic binary fixed point
+-- : arithmetic functions
+-- :
+-- 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) $
+-- --------------------------------------------------------------------
+
+library common_pkg_lib;
+library IEEE;
+use common_pkg_lib.common_fixed_float_types.all;
+--use common_pkg_lib.fixed_generic_pkg.all;
+
+package fixed_pkg is new common_pkg_lib.fixed_generic_pkg
+ generic map (
+ fixed_round_style => common_pkg_lib.common_fixed_float_types.fixed_round,
+ fixed_overflow_style => common_pkg_lib.common_fixed_float_types.fixed_saturate,
+ fixed_guard_bits => 3,
+ no_warning => false
+ );
diff --git a/common_pkg/float_generic_pkg_2008redirect.vhdl b/common_pkg/float_generic_pkg_2008redirect.vhdl
new file mode 100755
index 00000000..aad38b4e
--- /dev/null
+++ b/common_pkg/float_generic_pkg_2008redirect.vhdl
@@ -0,0 +1,6713 @@
+-- -----------------------------------------------------------------
+--
+-- Copyright 2019 IEEE P1076 WG Authors
+--
+-- See the LICENSE file distributed with this work for copyright and
+-- licensing information and the AUTHORS file.
+--
+-- This file to you under the Apache License, Version 2.0 (the "License").
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+-- implied. See the License for the specific language governing
+-- permissions and limitations under the License.
+--
+-- Title : Floating-point package (Generic package declaration)
+-- :
+-- Library : This package shall be compiled into a library
+-- : symbolically named IEEE.
+-- :
+-- Developers: Accellera VHDL-TC and IEEE P1076 Working Group
+-- :
+-- Purpose : This packages defines basic binary floating point
+-- : arithmetic functions
+-- :
+-- 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) $
+-- --------------------------------------------------------------------
+
+use STD.TEXTIO.all;
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.NUMERIC_STD.all;
+library common_pkg_lib;
+use common_pkg_lib.common_fixed_float_types.all;
+
+package float_generic_pkg is
+ generic (
+ -- Defaults for sizing routines, when you do a "to_float" this will be
+ -- the default size. Example float32 would be 8 and 23 (8 downto -23)
+ float_exponent_width : NATURAL := 8;
+ float_fraction_width : NATURAL := 23;
+ -- Rounding algorithm, "round_nearest" is default, other valid values
+ -- are "round_zero" (truncation), "round_inf" (round up), and
+ -- "round_neginf" (round down)
+ float_round_style : com_round_type := round_nearest;
+ -- Denormal numbers (very small numbers near zero) true or false
+ float_denormalize : BOOLEAN := true;
+ -- Turns on NAN processing (invalid numbers and overflow) true of false
+ float_check_error : BOOLEAN := true;
+ -- Guard bits are added to the bottom of every operation for rounding.
+ -- any natural number (including 0) are valid.
+ float_guard_bits : NATURAL := 3;
+ -- If TRUE, then turn off warnings on "X" propagation
+ no_warning : BOOLEAN := false;
+ package fixed_pkg is new common_pkg_lib.fixed_generic_pkg
+ generic map (<>) );
+
+ -- Author David Bishop (dbishop@vhdl.org)
+ constant CopyRightNotice : STRING :=
+ "Copyright IEEE P1076 WG. Licensed Apache 2.0";
+
+ use fixed_pkg.all;
+
+ -- Note that this is "INTEGER range <>", thus if you use a literal, then the
+ -- default range will be (INTEGER'low to INTEGER'low + X)
+ type UNRESOLVED_float is array (INTEGER range <>) of STD_ULOGIC; -- main type
+ alias U_float is UNRESOLVED_float;
+
+ subtype float is (resolved) UNRESOLVED_float;
+ -----------------------------------------------------------------------------
+ -- Use the float type to define your own floating point numbers.
+ -- There must be a negative index or the packages will error out.
+ -- Minimum supported is "subtype float7 is float (3 downto -3);"
+ -- "subtype float16 is float (6 downto -9);" is probably the smallest
+ -- practical one to use.
+ -----------------------------------------------------------------------------
+
+ -- IEEE 754 single precision
+ subtype UNRESOLVED_float32 is UNRESOLVED_float (8 downto -23);
+ alias U_float32 is UNRESOLVED_float32;
+ subtype float32 is float (8 downto -23);
+ -----------------------------------------------------------------------------
+ -- IEEE-754 single precision floating point. This is a "float"
+ -- in C, and a FLOAT in Fortran. The exponent is 8 bits wide, and
+ -- the fraction is 23 bits wide. This format can hold roughly 7 decimal
+ -- digits. Infinity is 2**127 = 1.7E38 in this number system.
+ -- The bit representation is as follows:
+ -- 1 09876543 21098765432109876543210
+ -- 8 76543210 12345678901234567890123
+ -- 0 00000000 00000000000000000000000
+ -- 8 7 0 -1 -23
+ -- +/- exp. fraction
+ -----------------------------------------------------------------------------
+
+ -- IEEE 754 double precision
+ subtype UNRESOLVED_float64 is UNRESOLVED_float (11 downto -52);
+ alias U_float64 is UNRESOLVED_float64;
+ subtype float64 is float (11 downto -52);
+ -----------------------------------------------------------------------------
+ -- IEEE-754 double precision floating point. This is a "double float"
+ -- in C, and a FLOAT*8 in Fortran. The exponent is 11 bits wide, and
+ -- the fraction is 52 bits wide. This format can hold roughly 15 decimal
+ -- digits. Infinity is 2**2047 in this number system.
+ -- The bit representation is as follows:
+ -- 3 21098765432 1098765432109876543210987654321098765432109876543210
+ -- 1 09876543210 1234567890123456789012345678901234567890123456789012
+ -- S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ -- 11 10 0 -1 -52
+ -- +/- exponent fraction
+ -----------------------------------------------------------------------------
+
+ -- IEEE 854 & C extended precision
+ subtype UNRESOLVED_float128 is UNRESOLVED_float (15 downto -112);
+ alias U_float128 is UNRESOLVED_float128;
+ subtype float128 is float (15 downto -112);
+ -----------------------------------------------------------------------------
+ -- The 128 bit floating point number is "long double" in C (on
+ -- some systems this is a 70 bit floating point number) and FLOAT*32
+ -- in Fortran. The exponent is 15 bits wide and the fraction is 112
+ -- bits wide. This number can handle approximately 33 decimal digits.
+ -- Infinity is 2**32,767 in this number system.
+ -----------------------------------------------------------------------------
+
+ -- purpose: Checks for a valid floating point number
+ type valid_fpstate is (nan, -- Signaling NaN (C FP_NAN)
+ quiet_nan, -- Quiet NaN (C FP_NAN)
+ neg_inf, -- Negative infinity (C FP_INFINITE)
+ neg_normal, -- negative normalized nonzero
+ neg_denormal, -- negative denormalized (FP_SUBNORMAL)
+ neg_zero, -- -0 (C FP_ZERO)
+ pos_zero, -- +0 (C FP_ZERO)
+ pos_denormal, -- Positive denormalized (FP_SUBNORMAL)
+ pos_normal, -- positive normalized nonzero
+ pos_inf, -- positive infinity
+ isx); -- at least one input is unknown
+
+ -- This deferred constant will tell you if the package body is synthesizable
+ -- or implemented as real numbers.
+ constant fphdlsynth_or_real : BOOLEAN; -- deferred constant
+
+ -- Returns the class which X falls into
+ function Classfp (
+ x : UNRESOLVED_float; -- floating point input
+ check_error : BOOLEAN := float_check_error) -- check for errors
+ return valid_fpstate;
+
+ -- Arithmetic functions, these operators do not require parameters.
+ function "abs" (arg : UNRESOLVED_float) return UNRESOLVED_float;
+ function "-" (arg : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- These allows the base math functions to use the default values
+ -- of their parameters. Thus they do full IEEE floating point.
+
+ function "+" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "-" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "*" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "/" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "rem" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "mod" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- Basic parameter list
+ -- round_style - Selects the rounding algorithm to use
+ -- guard - extra bits added to the end if the operation to add precision
+ -- check_error - When "false" turns off NAN and overflow checks
+ -- denormalize - When "false" turns off denormal number processing
+
+ function add (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function subtract (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function multiply (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function divide (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function remainder (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function modulo (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- reciprocal
+ function reciprocal (
+ arg : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function dividebyp2 (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- Multiply accumulate result = l*r + c
+ function mac (
+ l, r, c : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- Square root (all 754 based implementations need this)
+ function sqrt (
+ arg : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style;
+ constant guard : NATURAL := float_guard_bits;
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_float;
+
+ function Is_Negative (arg : UNRESOLVED_float) return BOOLEAN;
+
+ -----------------------------------------------------------------------------
+ -- compare functions
+ -- =, /=, >=, <=, <, >, maximum, minimum
+
+ function eq ( -- equal =
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ function ne ( -- not equal /=
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ function lt ( -- less than <
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ function gt ( -- greater than >
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ function le ( -- less than or equal to <=
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ function ge ( -- greater than or equal to >=
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ -- Need to overload the default versions of these
+ function "=" (l, r : UNRESOLVED_float) return BOOLEAN;
+ function "/=" (l, r : UNRESOLVED_float) return BOOLEAN;
+ function ">=" (l, r : UNRESOLVED_float) return BOOLEAN;
+ function "<=" (l, r : UNRESOLVED_float) return BOOLEAN;
+ function ">" (l, r : UNRESOLVED_float) return BOOLEAN;
+ function "<" (l, r : UNRESOLVED_float) return BOOLEAN;
+
+ function "?=" (l, r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?/=" (l, r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?>" (l, r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?>=" (l, r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?<" (l, r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?<=" (l, r : UNRESOLVED_float) return STD_ULOGIC;
+
+ function std_match (l, r : UNRESOLVED_float) return BOOLEAN;
+ function find_rightmost (arg : UNRESOLVED_float; y : STD_ULOGIC)
+ return INTEGER;
+ function find_leftmost (arg : UNRESOLVED_float; y : STD_ULOGIC)
+ return INTEGER;
+ function maximum (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function minimum (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- conversion functions
+ -- Converts one floating point number into another.
+
+ function resize (
+ arg : UNRESOLVED_float; -- Floating point input
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function resize (
+ arg : UNRESOLVED_float; -- Floating point input
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function to_float32 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float32;
+
+ function to_float64 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float64;
+
+ function to_float128 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float128;
+
+ -- Converts an fp into an SLV (needed for synthesis)
+ function to_slv (arg : UNRESOLVED_float) return STD_LOGIC_VECTOR;
+ alias to_StdLogicVector is to_slv [UNRESOLVED_float return STD_LOGIC_VECTOR];
+ alias to_Std_Logic_Vector is to_slv [UNRESOLVED_float return STD_LOGIC_VECTOR];
+
+ -- Converts an fp into an std_ulogic_vector (sulv)
+ function to_sulv (arg : UNRESOLVED_float) return STD_ULOGIC_VECTOR;
+ alias to_StdULogicVector is to_sulv [UNRESOLVED_float return STD_ULOGIC_VECTOR];
+ alias to_Std_ULogic_Vector is to_sulv [UNRESOLVED_float return STD_ULOGIC_VECTOR];
+
+ -- std_ulogic_vector to float
+ function to_float (
+ arg : STD_ULOGIC_VECTOR;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction
+ return UNRESOLVED_float;
+
+ -- Integer to float
+ function to_float (
+ arg : INTEGER;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- real to float
+ function to_float (
+ arg : REAL;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- unsigned to float
+ function to_float (
+ arg : UNRESOLVED_UNSIGNED;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- signed to float
+ function to_float (
+ arg : UNRESOLVED_SIGNED;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- unsigned fixed point to float
+ function to_float (
+ arg : UNRESOLVED_ufixed; -- unsigned fixed point input
+ constant exponent_width : NATURAL := float_exponent_width; -- width of exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- width of fraction
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions
+ return UNRESOLVED_float;
+
+ -- signed fixed point to float
+ function to_float (
+ arg : UNRESOLVED_sfixed;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- rounding option
+ return UNRESOLVED_float;
+
+ -- size_res functions
+ -- Integer to float
+ function to_float (
+ arg : INTEGER;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- real to float
+ function to_float (
+ arg : REAL;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- unsigned to float
+ function to_float (
+ arg : UNRESOLVED_UNSIGNED;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- signed to float
+ function to_float (
+ arg : UNRESOLVED_SIGNED;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- sulv to float
+ function to_float (
+ arg : STD_ULOGIC_VECTOR;
+ size_res : UNRESOLVED_float)
+ return UNRESOLVED_float;
+
+ -- unsigned fixed point to float
+ function to_float (
+ arg : UNRESOLVED_ufixed; -- unsigned fixed point input
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions
+ return UNRESOLVED_float;
+
+ -- signed fixed point to float
+ function to_float (
+ arg : UNRESOLVED_sfixed;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- rounding option
+ return UNRESOLVED_float;
+
+ -- float to unsigned
+ function to_unsigned (
+ arg : UNRESOLVED_float; -- floating point input
+ constant size : NATURAL; -- length of output
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNRESOLVED_UNSIGNED;
+
+ -- float to signed
+ function to_signed (
+ arg : UNRESOLVED_float; -- floating point input
+ constant size : NATURAL; -- length of output
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNRESOLVED_SIGNED;
+
+ -- purpose: Converts a float to unsigned fixed point
+ function to_ufixed (
+ arg : UNRESOLVED_float; -- fp input
+ constant left_index : INTEGER; -- integer part
+ constant right_index : INTEGER; -- fraction part
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_ufixed;
+
+ -- float to signed fixed point
+ function to_sfixed (
+ arg : UNRESOLVED_float; -- fp input
+ constant left_index : INTEGER; -- integer part
+ constant right_index : INTEGER; -- fraction part
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_sfixed;
+
+ -- size_res versions
+ -- float to unsigned
+ function to_unsigned (
+ arg : UNRESOLVED_float; -- floating point input
+ size_res : UNRESOLVED_UNSIGNED;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNRESOLVED_UNSIGNED;
+
+ -- float to signed
+ function to_signed (
+ arg : UNRESOLVED_float; -- floating point input
+ size_res : UNRESOLVED_SIGNED;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNRESOLVED_SIGNED;
+
+ -- purpose: Converts a float to unsigned fixed point
+ function to_ufixed (
+ arg : UNRESOLVED_float; -- fp input
+ size_res : UNRESOLVED_ufixed;
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_ufixed;
+
+ -- float to signed fixed point
+ function to_sfixed (
+ arg : UNRESOLVED_float; -- fp input
+ size_res : UNRESOLVED_sfixed;
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_sfixed;
+
+ -- float to real
+ function to_real (
+ arg : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return REAL;
+
+ -- float to integer
+ function to_integer (
+ arg : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return INTEGER;
+
+ -- For Verilog compatability
+ function realtobits (arg : REAL) return STD_ULOGIC_VECTOR;
+ function bitstoreal (arg : STD_ULOGIC_VECTOR) return REAL;
+
+ -- Maps metalogical values
+ function to_01 (
+ arg : UNRESOLVED_float; -- floating point input
+ XMAP : STD_LOGIC := '0')
+ return UNRESOLVED_float;
+
+ function Is_X (arg : UNRESOLVED_float) return BOOLEAN;
+ function to_X01 (arg : UNRESOLVED_float) return UNRESOLVED_float;
+ function to_X01Z (arg : UNRESOLVED_float) return UNRESOLVED_float;
+ function to_UX01 (arg : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- These two procedures were copied out of the body because they proved
+ -- very useful for vendor specific algorithm development
+ -- Break_number converts a floating point number into it's parts
+ -- Exponent is biased by -1
+
+ procedure break_number (
+ arg : in UNRESOLVED_float;
+ denormalize : in BOOLEAN := float_denormalize;
+ check_error : in BOOLEAN := float_check_error;
+ fract : out UNRESOLVED_UNSIGNED;
+ expon : out UNRESOLVED_SIGNED; -- NOTE: Add 1 to get the real exponent!
+ sign : out STD_ULOGIC);
+
+ procedure break_number (
+ arg : in UNRESOLVED_float;
+ denormalize : in BOOLEAN := float_denormalize;
+ check_error : in BOOLEAN := float_check_error;
+ fract : out UNRESOLVED_ufixed; -- a number between 1.0 and 2.0
+ expon : out UNRESOLVED_SIGNED; -- NOTE: Add 1 to get the real exponent!
+ sign : out STD_ULOGIC);
+
+ -- Normalize takes a fraction and and exponent and converts them into
+ -- a floating point number. Does the shifting and the rounding.
+ -- Exponent is assumed to be biased by -1
+
+ function normalize (
+ fract : UNRESOLVED_UNSIGNED; -- fraction, unnormalized
+ expon : UNRESOLVED_SIGNED; -- exponent - 1, normalized
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float;
+
+ -- Exponent is assumed to be biased by -1
+ function normalize (
+ fract : UNRESOLVED_ufixed; -- unsigned fixed point
+ expon : UNRESOLVED_SIGNED; -- exponent - 1, normalized
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float;
+
+ function normalize (
+ fract : UNRESOLVED_UNSIGNED; -- unsigned
+ expon : UNRESOLVED_SIGNED; -- exponent - 1, normalized
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ size_res : UNRESOLVED_float; -- used for sizing only
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float;
+
+ -- Exponent is assumed to be biased by -1
+ function normalize (
+ fract : UNRESOLVED_ufixed; -- unsigned fixed point
+ expon : UNRESOLVED_SIGNED; -- exponent - 1, normalized
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ size_res : UNRESOLVED_float; -- used for sizing only
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float;
+
+ -- overloaded versions
+ function "+" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "+" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "+" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "+" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "-" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "-" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "-" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "-" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "*" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "*" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "*" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "*" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "/" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "/" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "/" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "/" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "rem" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "rem" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "rem" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "rem" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "mod" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "mod" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "mod" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "mod" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- overloaded compare functions
+ function "=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function "/=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function ">=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function "<=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function ">" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function "<" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function "=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function "/=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function ">=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function "<=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function ">" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function "<" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function "=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function "/=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function ">=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function "<=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function ">" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function "<" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function "=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function "/=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function ">=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function "<=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function ">" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function "<" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function "?=" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function "?/=" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function "?>" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function "?>=" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function "?<" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function "?<=" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function "?=" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?/=" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?>" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?>=" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?<" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?<=" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?=" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function "?/=" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function "?>" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function "?>=" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function "?<" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function "?<=" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function "?=" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?/=" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?>" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?>=" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?<" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ function "?<=" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ -- minimum and maximum overloads
+ function maximum (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function minimum (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function maximum (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function minimum (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function maximum (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function minimum (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function maximum (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function minimum (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+----------------------------------------------------------------------------
+ -- logical functions
+ ----------------------------------------------------------------------------
+
+ function "not" (l : UNRESOLVED_float) return UNRESOLVED_float;
+ function "and" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "or" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "nand" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "nor" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "xor" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "xnor" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ -- Vector and std_ulogic functions, same as functions in numeric_std
+ function "and" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "and" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ function "or" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "or" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ function "nand" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "nand" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ function "nor" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "nor" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ function "xor" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "xor" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ function "xnor" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "xnor" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ -- Reduction operators, same as numeric_std functions
+ function "and" (l : UNRESOLVED_float) return STD_ULOGIC;
+ function "nand" (l : UNRESOLVED_float) return STD_ULOGIC;
+ function "or" (l : UNRESOLVED_float) return STD_ULOGIC;
+ function "nor" (l : UNRESOLVED_float) return STD_ULOGIC;
+ function "xor" (l : UNRESOLVED_float) return STD_ULOGIC;
+ function "xnor" (l : UNRESOLVED_float) return STD_ULOGIC;
+
+ -- Note: "sla", "sra", "sll", "slr", "rol" and "ror" not implemented.
+
+ -----------------------------------------------------------------------------
+ -- Recommended Functions from the IEEE 754 Appendix
+ -----------------------------------------------------------------------------
+
+ -- returns x with the sign of y.
+ function Copysign (x, y : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- Returns y * 2**n for integral values of N without computing 2**n
+ function Scalb (
+ y : UNRESOLVED_float; -- floating point input
+ N : INTEGER; -- exponent to add
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- Returns y * 2**n for integral values of N without computing 2**n
+ function Scalb (
+ y : UNRESOLVED_float; -- floating point input
+ N : UNRESOLVED_SIGNED; -- exponent to add
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- returns the unbiased exponent of x
+ function Logb (x : UNRESOLVED_float) return INTEGER;
+ function Logb (x : UNRESOLVED_float) return UNRESOLVED_SIGNED;
+
+ -- returns the next representable neighbor of x in the direction toward y
+ function Nextafter (
+ x, y : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_float;
+
+ -- Returns TRUE if X is unordered with Y.
+ function Unordered (x, y : UNRESOLVED_float) return BOOLEAN;
+ function Finite (x : UNRESOLVED_float) return BOOLEAN;
+ function Isnan (x : UNRESOLVED_float) return BOOLEAN;
+
+ -- Function to return constants.
+ function zerofp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ function nanfp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ function qnanfp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ function pos_inffp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ function neg_inffp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ function neg_zerofp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ -- size_res versions
+ function zerofp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+ function nanfp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+ function qnanfp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+ function pos_inffp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+ function neg_inffp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+ function neg_zerofp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+
+ --===========================================================================
+ -- string and textio Functions
+ --===========================================================================
+
+ -- writes S:EEEE:FFFFFFFF
+ procedure WRITE (
+ L : inout LINE; -- access type (pointer)
+ VALUE : in UNRESOLVED_float; -- value to write
+ JUSTIFIED : in SIDE := right; -- which side to justify text
+ FIELD : in WIDTH := 0); -- width of field
+
+ -- Reads SEEEEFFFFFFFF, "." and ":" are ignored
+ procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float);
+ procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float;
+ GOOD : out BOOLEAN);
+
+ alias BREAD is READ [LINE, UNRESOLVED_float, BOOLEAN];
+ alias BREAD is READ [LINE, UNRESOLVED_float];
+ alias BWRITE is WRITE [LINE, UNRESOLVED_float, SIDE, WIDTH];
+ alias BINARY_READ is READ [LINE, UNRESOLVED_float, BOOLEAN];
+ alias BINARY_READ is READ [LINE, UNRESOLVED_float];
+ alias BINARY_WRITE is WRITE [LINE, UNRESOLVED_float, SIDE, WIDTH];
+
+ procedure OWRITE (
+ L : inout LINE; -- access type (pointer)
+ VALUE : in UNRESOLVED_float; -- value to write
+ JUSTIFIED : in SIDE := right; -- which side to justify text
+ FIELD : in WIDTH := 0); -- width of field
+
+ -- Octal read with padding, no separators used
+ procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float);
+ procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float;
+ GOOD : out BOOLEAN);
+ alias OCTAL_READ is OREAD [LINE, UNRESOLVED_float, BOOLEAN];
+ alias OCTAL_READ is OREAD [LINE, UNRESOLVED_float];
+ alias OCTAL_WRITE is OWRITE [LINE, UNRESOLVED_float, SIDE, WIDTH];
+
+ -- Hex write with padding, no separators
+ procedure HWRITE (
+ L : inout LINE; -- access type (pointer)
+ VALUE : in UNRESOLVED_float; -- value to write
+ JUSTIFIED : in SIDE := right; -- which side to justify text
+ FIELD : in WIDTH := 0); -- width of field
+
+ -- Hex read with padding, no separators used
+ procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float);
+ procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float;
+ GOOD : out BOOLEAN);
+ alias HEX_READ is HREAD [LINE, UNRESOLVED_float, BOOLEAN];
+ alias HEX_READ is HREAD [LINE, UNRESOLVED_float];
+ alias HEX_WRITE is HWRITE [LINE, UNRESOLVED_float, SIDE, WIDTH];
+
+ -- returns "S:EEEE:FFFFFFFF"
+ function to_string (value : UNRESOLVED_float) return STRING;
+ alias TO_BSTRING is TO_STRING [UNRESOLVED_float return STRING];
+ alias TO_BINARY_STRING is TO_STRING [UNRESOLVED_float return STRING];
+
+ -- Returns a HEX string, with padding
+ function to_hstring (value : UNRESOLVED_float) return STRING;
+ alias TO_HEX_STRING is to_hstring [UNRESOLVED_float return STRING];
+
+ -- Returns and octal string, with padding
+ function to_ostring (value : UNRESOLVED_float) return STRING;
+ alias TO_OCTAL_STRING is to_ostring [UNRESOLVED_float return STRING];
+
+ function from_string (
+ bstring : STRING; -- binary string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float;
+ alias from_bstring is from_string [STRING, NATURAL, NATURAL
+ return UNRESOLVED_float];
+ alias from_binary_string is from_string [STRING, NATURAL, NATURAL
+ return UNRESOLVED_float];
+ function from_ostring (
+ ostring : STRING; -- Octal string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float;
+ alias from_octal_string is from_ostring [STRING, NATURAL, NATURAL
+ return UNRESOLVED_float];
+
+ function from_hstring (
+ hstring : STRING; -- hex string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float;
+ alias from_hex_string is from_hstring [STRING, NATURAL, NATURAL
+ return UNRESOLVED_float];
+
+ function from_string (
+ bstring : STRING; -- binary string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float;
+ alias from_bstring is from_string [STRING, UNRESOLVED_float
+ return UNRESOLVED_float];
+ alias from_binary_string is from_string [STRING, UNRESOLVED_float
+ return UNRESOLVED_float];
+
+ function from_ostring (
+ ostring : STRING; -- Octal string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float;
+ alias from_octal_string is from_ostring [STRING, UNRESOLVED_float
+ return UNRESOLVED_float];
+
+ function from_hstring (
+ hstring : STRING; -- hex string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float;
+ alias from_hex_string is from_hstring [STRING, UNRESOLVED_float
+ return UNRESOLVED_float];
+
+end package float_generic_pkg;
+-- -----------------------------------------------------------------
+--
+-- Copyright 2019 IEEE P1076 WG Authors
+--
+-- See the LICENSE file distributed with this work for copyright and
+-- licensing information and the AUTHORS file.
+--
+-- This file to you under the Apache License, Version 2.0 (the "License").
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+-- implied. See the License for the specific language governing
+-- permissions and limitations under the License.
+--
+-- Title : Floating-point package (Generic package body)
+-- :
+-- Library : This package shall be compiled into a library
+-- : symbolically named IEEE.
+-- :
+-- Developers: Accellera VHDL-TC and IEEE P1076 Working Group
+-- :
+-- Purpose : This packages defines basic binary floating point
+-- : arithmetic functions
+-- :
+-- 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 body float_generic_pkg is
+
+ -- Author David Bishop (dbishop@vhdl.org)
+ -----------------------------------------------------------------------------
+ -- type declarations
+ -----------------------------------------------------------------------------
+
+ -- This deferred constant will tell you if the package body is synthesizable
+ -- or implemented as real numbers, set to "true" if synthesizable.
+ constant fphdlsynth_or_real : BOOLEAN := true; -- deferred constant
+
+ -- types of boundary conditions
+ type boundary_type is (normal, infinity, zero, denormal);
+
+ -- null range array constant
+ constant NAFP : UNRESOLVED_float (0 downto 1) := (others => '0');
+ constant NSLV : STD_ULOGIC_VECTOR (0 downto 1) := (others => '0');
+
+ -- Special version of "minimum" to do some boundary checking
+ function mine (L, R : INTEGER)
+ return INTEGER is
+ begin -- function minimum
+ if (L = INTEGER'low or R = INTEGER'low) then
+ report float_generic_pkg'instance_name
+ & " Unbounded number passed, was a literal used?"
+ severity error;
+ return 0;
+ end if;
+ return minimum (L, R);
+ end function mine;
+
+ -- Generates the base number for the exponent normalization offset.
+ function gen_expon_base (
+ constant exponent_width : NATURAL)
+ return SIGNED
+ is
+ variable result : SIGNED (exponent_width-1 downto 0);
+ begin
+ result := (others => '1');
+ result (exponent_width-1) := '0';
+ return result;
+ end function gen_expon_base;
+
+ -- Integer version of the "log2" command (contributed by Peter Ashenden)
+ function log2 (A : NATURAL) return NATURAL is
+ variable quotient : NATURAL;
+ variable result : NATURAL := 0;
+ begin
+ quotient := A / 2;
+ while quotient > 0 loop
+ quotient := quotient / 2;
+ result := result + 1;
+ end loop;
+ return result;
+ end function log2;
+
+ -- Function similar to the ILOGB function in MATH_REAL
+ function log2 (A : REAL) return INTEGER is
+ variable Y : REAL;
+ variable N : INTEGER := 0;
+ begin
+ if (A = 1.0 or A = 0.0) then
+ return 0;
+ end if;
+ Y := A;
+ if(A > 1.0) then
+ while Y >= 2.0 loop
+ Y := Y / 2.0;
+ N := N + 1;
+ end loop;
+ return N;
+ end if;
+ -- O < Y < 1
+ while Y < 1.0 loop
+ Y := Y * 2.0;
+ N := N - 1;
+ end loop;
+ return N;
+ end function log2;
+
+ -- purpose: Test the boundary conditions of a Real number
+ procedure test_boundary (
+ arg : in REAL; -- Input, converted to real
+ constant fraction_width : in NATURAL; -- length of FP output fraction
+ constant exponent_width : in NATURAL; -- length of FP exponent
+ constant denormalize : in BOOLEAN := true; -- Use IEEE extended FP
+ variable btype : out boundary_type;
+ variable log2i : out INTEGER
+ ) is
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ constant exp_min : SIGNED (12 downto 0) :=
+ -(resize(expon_base, 13)) + 1; -- Minimum normal exponent
+ constant exp_ext_min : SIGNED (12 downto 0) :=
+ exp_min - fraction_width; -- Minimum for denormal exponent
+ variable log2arg : INTEGER; -- log2 of argument
+ begin -- function test_boundary
+ -- Check to see if the exponent is big enough
+ -- Note that the argument is always an absolute value at this point.
+ log2arg := log2(arg);
+ if arg = 0.0 then
+ btype := zero;
+ elsif exponent_width > 11 then -- Exponent for Real is 11 (64 bit)
+ btype := normal;
+ else
+ if log2arg < to_integer(exp_min) then
+ if denormalize then
+ if log2arg < to_integer(exp_ext_min) then
+ btype := zero;
+ else
+ btype := denormal;
+ end if;
+ else
+ if log2arg < to_integer(exp_min)-1 then
+ btype := zero;
+ else
+ btype := normal; -- Can still represent this number
+ end if;
+ end if;
+ elsif exponent_width < 11 then
+ if log2arg > to_integer(expon_base)+1 then
+ btype := infinity;
+ else
+ btype := normal;
+ end if;
+ else
+ btype := normal;
+ end if;
+ end if;
+ log2i := log2arg;
+ end procedure test_boundary;
+
+ -- purpose: Rounds depending on the state of the "round_style"
+ -- Logic taken from
+ -- "What Every Computer Scientist Should Know About Floating Point Arithmetic"
+ -- by David Goldberg (1991)
+ function check_round (
+ fract_in : STD_ULOGIC; -- input fraction
+ sign : STD_ULOGIC; -- sign bit
+ remainder : UNSIGNED; -- remainder to round from
+ sticky : STD_ULOGIC := '0'; -- Sticky bit
+ constant round_style : com_round_type) -- rounding type
+ return BOOLEAN
+ is
+ variable result : BOOLEAN;
+ variable or_reduced : STD_ULOGIC;
+ begin -- function check_round
+ result := false;
+ if (remainder'length > 0) then -- if remainder in a null array
+ or_reduced := or (remainder & sticky);
+ rounding_case : case round_style is
+ when round_nearest => -- Round Nearest, default mode
+ if remainder(remainder'high) = '1' then -- round
+ if (remainder'length > 1) then
+ if ((or (remainder(remainder'high-1
+ downto remainder'low)) = '1'
+ or sticky = '1')
+ or fract_in = '1') then
+ -- Make the bottom bit zero if possible if we are at 1/2
+ result := true;
+ end if;
+ else
+ result := (fract_in = '1' or sticky = '1');
+ end if;
+ end if;
+ when round_inf => -- round up if positive, else truncate.
+ if or_reduced = '1' and sign = '0' then
+ result := true;
+ end if;
+ when round_neginf => -- round down if negative, else truncate.
+ if or_reduced = '1' and sign = '1' then
+ result := true;
+ end if;
+ when round_zero => -- round toward 0 Truncate
+ null;
+ end case rounding_case;
+ end if;
+ return result;
+ end function check_round;
+
+ -- purpose: Rounds depending on the state of the "round_style"
+ -- unsigned version
+ procedure fp_round (
+ fract_in : in UNSIGNED; -- input fraction
+ expon_in : in SIGNED; -- input exponent
+ fract_out : out UNSIGNED; -- output fraction
+ expon_out : out SIGNED) is -- output exponent
+ begin -- procedure fp_round
+ if and (fract_in) = '1' then -- Fraction is all "1"
+ expon_out := expon_in + 1;
+ fract_out := to_unsigned(0, fract_out'high+1);
+ else
+ expon_out := expon_in;
+ fract_out := fract_in + 1;
+ end if;
+ end procedure fp_round;
+
+ -- This version of break_number doesn't call "classfp"
+ procedure break_number ( -- internal version
+ arg : in UNRESOLVED_float;
+ fptyp : in valid_fpstate;
+ denormalize : in BOOLEAN := true;
+ fract : out UNSIGNED;
+ expon : out SIGNED) is
+ constant fraction_width : NATURAL := -arg'low; -- length of FP output fraction
+ constant exponent_width : NATURAL := arg'high; -- length of FP output exponent
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable exp : SIGNED (expon'range);
+ begin
+ fract (fraction_width-1 downto 0) :=
+ UNSIGNED (to_slv(arg(-1 downto -fraction_width)));
+ breakcase : case fptyp is
+ when pos_zero | neg_zero =>
+ fract (fraction_width) := '0';
+ exp := -expon_base;
+ when pos_denormal | neg_denormal =>
+ if denormalize then
+ exp := -expon_base;
+ fract (fraction_width) := '0';
+ else
+ exp := -expon_base - 1;
+ fract (fraction_width) := '1';
+ end if;
+ when pos_normal | neg_normal | pos_inf | neg_inf =>
+ fract (fraction_width) := '1';
+ exp := SIGNED(arg(exponent_width-1 downto 0));
+ exp (exponent_width-1) := not exp(exponent_width-1);
+ when others =>
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & "BREAK_NUMBER: " &
+ "Meta state detected in fp_break_number process"
+ severity warning;
+ -- complete the case, if a NAN goes in, a NAN comes out.
+ exp := (others => '1');
+ fract (fraction_width) := '1';
+ end case breakcase;
+ expon := exp;
+ end procedure break_number;
+
+ -- purpose: floating point to UNSIGNED
+ -- Used by to_integer, to_unsigned, and to_signed functions
+ procedure float_to_unsigned (
+ arg : in UNRESOLVED_float; -- floating point input
+ variable sign : out STD_ULOGIC; -- sign of output
+ variable frac : out UNSIGNED; -- unsigned biased output
+ constant denormalize : in BOOLEAN; -- turn on denormalization
+ constant bias : in NATURAL; -- bias for fixed point
+ constant round_style : in com_round_type) is -- rounding method
+ constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction
+ constant exponent_width : INTEGER := arg'high; -- length of FP output exponent
+ variable fract : UNSIGNED (frac'range); -- internal version of frac
+ variable isign : STD_ULOGIC; -- internal version of sign
+ variable exp : INTEGER; -- Exponent
+ variable expon : SIGNED (exponent_width-1 downto 0); -- Vectorized exp
+ -- Base to divide fraction by
+ variable frac_shift : UNSIGNED (frac'high+3 downto 0); -- Fraction shifted
+ variable shift : INTEGER;
+ variable remainder : UNSIGNED (2 downto 0);
+ variable round : STD_ULOGIC; -- round BIT
+ begin
+ isign := to_x01(arg(arg'high));
+ -- exponent /= '0', normal floating point
+ expon := to_01(SIGNED(arg (exponent_width-1 downto 0)), 'X');
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ exp := to_integer (expon);
+ -- Figure out the fraction
+ fract := (others => '0'); -- fill with zero
+ fract (fract'high) := '1'; -- Add the "1.0".
+ shift := (fract'high-1) - exp;
+ if fraction_width > fract'high then -- Can only use size-2 bits
+ fract (fract'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto
+ -fract'high)));
+ else -- can use all bits
+ fract (fract'high-1 downto fract'high-fraction_width) :=
+ UNSIGNED (to_slv (arg(-1 downto -fraction_width)));
+ end if;
+ frac_shift := fract & "000";
+ if shift < 0 then -- Overflow
+ fract := (others => '1');
+ else
+ frac_shift := shift_right (frac_shift, shift);
+ fract := frac_shift (frac_shift'high downto 3);
+ remainder := frac_shift (2 downto 0);
+ -- round (round_zero will bypass this and truncate)
+ case round_style is
+ when round_nearest =>
+ round := remainder(2) and
+ (fract (0) or (or (remainder (1 downto 0))));
+ when round_inf =>
+ round := remainder(2) and not isign;
+ when round_neginf =>
+ round := remainder(2) and isign;
+ when others =>
+ round := '0';
+ end case;
+ if round = '1' then
+ fract := fract + 1;
+ end if;
+ end if;
+ frac := fract;
+ sign := isign;
+ end procedure float_to_unsigned;
+
+ -- purpose: returns a part of a vector, this function is here because
+ -- or (fractr (to_integer(shiftx) downto 0));
+ -- can't be synthesized in some synthesis tools.
+ function smallfract (
+ arg : UNSIGNED;
+ shift : NATURAL)
+ return STD_ULOGIC
+ is
+ variable orx : STD_ULOGIC;
+ begin
+ orx := arg(shift);
+ for i in arg'range loop
+ if i < shift then
+ orx := arg(i) or orx;
+ end if;
+ end loop;
+ return orx;
+ end function smallfract;
+ ---------------------------------------------------------------------------
+ -- Visible functions
+ ---------------------------------------------------------------------------
+
+ -- purpose: converts the negative index to a positive one
+ -- negative indices are illegal in 1164 and 1076.3
+ function to_sulv (
+ arg : UNRESOLVED_float) -- fp vector
+ return STD_ULOGIC_VECTOR
+ is
+ variable intermediate_result : UNRESOLVED_float(arg'length-1 downto 0);
+ begin -- function to_std_ulogic_vector
+ if arg'length < 1 then
+ return NSLV;
+ end if;
+ intermediate_result := arg;
+ return STD_ULOGIC_VECTOR (intermediate_result);
+ end function to_sulv;
+
+ -- Converts an fp into an SULV
+ function to_slv (arg : UNRESOLVED_float) return STD_LOGIC_VECTOR is
+ begin
+ return to_sulv (arg);
+ end function to_slv;
+
+ -- purpose: normalizes a floating point number
+ -- This version assumes an "unsigned" input with
+ function normalize (
+ fract : UNRESOLVED_UNSIGNED; -- fraction, unnormalized
+ expon : UNRESOLVED_SIGNED; -- exponent, normalized by -1
+ sign : STD_ULOGIC; -- sign BIT
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float
+ is
+ variable sfract : UNSIGNED (fract'high downto 0); -- shifted fraction
+ variable rfract : UNSIGNED (fraction_width-1 downto 0); -- fraction
+ variable exp : SIGNED (exponent_width+1 downto 0); -- exponent
+ variable rexp : SIGNED (exponent_width+1 downto 0); -- result exponent
+ variable rexpon : UNSIGNED (exponent_width-1 downto 0); -- exponent
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width); -- result
+ variable shiftr : INTEGER; -- shift amount
+ variable stickyx : STD_ULOGIC; -- version of sticky
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable round, zerores, infres : BOOLEAN;
+ begin -- function normalize
+ zerores := false;
+ infres := false;
+ round := false;
+ shiftr := find_leftmost (to_01(fract), '1') -- Find the first "1"
+ - fraction_width - nguard; -- subtract the length we want
+ exp := resize (expon, exp'length) + shiftr;
+ if (or (fract) = '0') then -- Zero
+ zerores := true;
+ elsif ((exp <= -resize(expon_base, exp'length)-1) and denormalize)
+ or ((exp < -resize(expon_base, exp'length)-1) and not denormalize) then
+ if (exp >= -resize(expon_base, exp'length)-fraction_width-1)
+ and denormalize then
+ exp := -resize(expon_base, exp'length)-1;
+ shiftr := -to_integer (expon + expon_base); -- new shift
+ else -- return zero
+ zerores := true;
+ end if;
+ elsif (exp > expon_base-1) then -- infinity
+ infres := true;
+ end if;
+ if zerores then
+ result := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif infres then
+ result := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ sfract := fract srl shiftr; -- shift
+ if shiftr > 0 then
+-- stickyx := sticky or (or (fract (shiftr-1 downto 0)));
+ stickyx := sticky or smallfract (fract, shiftr-1);
+ else
+ stickyx := sticky;
+ end if;
+ if nguard > 0 then
+ round := check_round (
+ fract_in => sfract (nguard),
+ sign => sign,
+ remainder => sfract(nguard-1 downto 0),
+ sticky => stickyx,
+ round_style => round_style);
+ end if;
+ if round then
+ fp_round(fract_in => sfract (fraction_width-1+nguard downto nguard),
+ expon_in => exp(rexp'range),
+ fract_out => rfract,
+ expon_out => rexp);
+ else
+ rfract := sfract (fraction_width-1+nguard downto nguard);
+ rexp := exp(rexp'range);
+ end if;
+ -- result
+ rexpon := UNSIGNED (rexp(exponent_width-1 downto 0));
+ rexpon (exponent_width-1) := not rexpon(exponent_width-1);
+ result (rexpon'range) := UNRESOLVED_float(rexpon);
+ result (-1 downto -fraction_width) := UNRESOLVED_float(rfract);
+ end if;
+ result (exponent_width) := sign; -- sign BIT
+ return result;
+ end function normalize;
+
+ -- purpose: normalizes a floating point number
+ -- This version assumes a "ufixed" input
+ function normalize (
+ fract : UNRESOLVED_ufixed; -- unsigned fixed point
+ expon : UNRESOLVED_SIGNED; -- exponent, normalized by -1
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable arguns : UNSIGNED (fract'high + fraction_width + nguard
+ downto 0) := (others => '0');
+ begin -- function normalize
+ arguns (arguns'high downto maximum (arguns'high-fract'length+1, 0)) :=
+ UNSIGNED (to_slv (fract));
+ result := normalize (fract => arguns,
+ expon => expon,
+ sign => sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => nguard);
+ return result;
+ end function normalize;
+
+ -- purpose: normalizes a floating point number
+ -- This version assumes a "ufixed" input with a "size_res" input
+ function normalize (
+ fract : UNRESOLVED_ufixed; -- unsigned fixed point
+ expon : UNRESOLVED_SIGNED; -- exponent, normalized by -1
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ size_res : UNRESOLVED_float; -- used for sizing only
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := -size_res'low;
+ constant exponent_width : NATURAL := size_res'high;
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable arguns : UNSIGNED (fract'high + fraction_width + nguard
+ downto 0) := (others => '0');
+ begin -- function normalize
+ arguns (arguns'high downto maximum (arguns'high-fract'length+1, 0)) :=
+ UNSIGNED (to_slv (fract));
+ result := normalize (fract => arguns,
+ expon => expon,
+ sign => sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => nguard);
+ return result;
+ end function normalize;
+
+ -- Regular "normalize" function with a "size_res" input.
+ function normalize (
+ fract : UNRESOLVED_UNSIGNED; -- unsigned
+ expon : UNRESOLVED_SIGNED; -- exponent - 1, normalized
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ size_res : UNRESOLVED_float; -- used for sizing only
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float is
+ begin
+ return normalize (fract => fract,
+ expon => expon,
+ sign => sign,
+ sticky => sticky,
+ fraction_width => -size_res'low,
+ exponent_width => size_res'high,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => nguard);
+ end function normalize;
+
+ -- Returns the class which X falls into
+ function Classfp (
+ x : UNRESOLVED_float; -- floating point input
+ check_error : BOOLEAN := float_check_error) -- check for errors
+ return valid_fpstate
+ is
+ constant fraction_width : INTEGER := -mine(x'low, x'low); -- length of FP output fraction
+ constant exponent_width : INTEGER := x'high; -- length of FP output exponent
+ variable arg : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- classfp
+ if (arg'length < 1 or fraction_width < 3 or exponent_width < 3
+ or x'left < x'right) then
+ report float_generic_pkg'instance_name
+ & "CLASSFP: " &
+ "Floating point number detected with a bad range"
+ severity error;
+ return isx;
+ end if;
+ -- Check for "X".
+ arg := to_01 (x, 'X');
+ if (arg(0) = 'X') then
+ return isx; -- If there is an X in the number
+ -- Special cases, check for illegal number
+ elsif check_error and
+ (and (STD_ULOGIC_VECTOR (arg (exponent_width-1 downto 0)))
+ = '1') then -- Exponent is all "1".
+ if or (to_slv (arg (-1 downto -fraction_width)))
+ /= '0' then -- Fraction must be all "0" or this is not a number.
+ if (arg(-1) = '1') then -- From "W. Khan - IEEE standard
+ return nan; -- 754 binary FP Signaling nan (Not a number)
+ else
+ return quiet_nan;
+ end if;
+ -- Check for infinity
+ elsif arg(exponent_width) = '0' then
+ return pos_inf; -- Positive infinity
+ else
+ return neg_inf; -- Negative infinity
+ end if;
+ -- check for "0"
+ elsif or (STD_LOGIC_VECTOR (arg (exponent_width-1 downto 0)))
+ = '0' then -- Exponent is all "0"
+ if or (to_slv (arg (-1 downto -fraction_width)))
+ = '0' then -- Fraction is all "0"
+ if arg(exponent_width) = '0' then
+ return pos_zero; -- Zero
+ else
+ return neg_zero;
+ end if;
+ else
+ if arg(exponent_width) = '0' then
+ return pos_denormal; -- Denormal number (ieee extended fp)
+ else
+ return neg_denormal;
+ end if;
+ end if;
+ else
+ if arg(exponent_width) = '0' then
+ return pos_normal; -- Normal FP number
+ else
+ return neg_normal;
+ end if;
+ end if;
+ end function Classfp;
+
+ procedure break_number (
+ arg : in UNRESOLVED_float;
+ denormalize : in BOOLEAN := float_denormalize;
+ check_error : in BOOLEAN := float_check_error;
+ fract : out UNRESOLVED_UNSIGNED;
+ expon : out UNRESOLVED_SIGNED;
+ sign : out STD_ULOGIC) is
+ variable fptyp : valid_fpstate;
+ begin
+ fptyp := Classfp (arg, check_error);
+ sign := to_x01(arg(arg'high));
+ break_number (
+ arg => arg,
+ fptyp => fptyp,
+ denormalize => denormalize,
+ fract => fract,
+ expon => expon);
+ end procedure break_number;
+
+ procedure break_number (
+ arg : in UNRESOLVED_float;
+ denormalize : in BOOLEAN := float_denormalize;
+ check_error : in BOOLEAN := float_check_error;
+ fract : out UNRESOLVED_ufixed; -- 1 downto -fraction_width
+ expon : out UNRESOLVED_SIGNED; -- exponent_width-1 downto 0
+ sign : out STD_ULOGIC) is
+ constant fraction_width : NATURAL := -mine(arg'low, arg'low); -- length of FP output fraction
+ variable fptyp : valid_fpstate;
+ variable ufract : UNSIGNED (fraction_width downto 0); -- unsigned fraction
+ begin
+ fptyp := Classfp (arg, check_error);
+ sign := to_x01(arg(arg'high));
+ break_number (
+ arg => arg,
+ fptyp => fptyp,
+ denormalize => denormalize,
+ fract => ufract,
+ expon => expon);
+ fract (0 downto -fraction_width) := ufixed (ufract);
+ end procedure break_number;
+
+ -- Arithmetic functions
+ function "abs" (
+ arg : UNRESOLVED_float) -- floating point input
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (arg'range); -- result
+ begin
+ if (arg'length > 0) then
+ result := to_01 (arg, 'X');
+ result (arg'high) := '0'; -- set the sign bit to positive
+ return result;
+ else
+ return NAFP;
+ end if;
+ end function "abs";
+
+ -- IEEE 754 "negative" function
+ function "-" (
+ arg : UNRESOLVED_float) -- floating point input
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (arg'range); -- result
+ begin
+ if (arg'length > 0) then
+ result := to_01 (arg, 'X');
+ result (arg'high) := not result (arg'high); -- invert sign bit
+ return result;
+ else
+ return NAFP;
+ end if;
+ end function "-";
+
+ -- Addition, adds two floating point numbers
+ function add (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ constant addguard : NATURAL := guard; -- add one guard bit
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable fractl, fractr : UNSIGNED (fraction_width+1+addguard downto 0); -- fractions
+ variable fractc, fracts : UNSIGNED (fractl'range); -- constant and shifted variables
+ variable urfract, ulfract : UNSIGNED (fraction_width downto 0);
+ variable ufract : UNSIGNED (fraction_width+1+addguard downto 0);
+ variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable rexpon : SIGNED (exponent_width downto 0); -- result exponent
+ variable shiftx : SIGNED (exponent_width downto 0); -- shift fractions
+ variable sign : STD_ULOGIC; -- sign of the output
+ variable leftright : BOOLEAN; -- left or right used
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable sticky : STD_ULOGIC; -- Holds precision for rounding
+ begin -- addition
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := Classfp (l, check_error);
+ rfptype := Classfp (r, check_error);
+ end if;
+ if (lfptype = isx or rfptype = isx) then
+ fpresult := (others => 'X');
+ elsif (lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan)
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ or (lfptype = pos_inf and rfptype = neg_inf)
+ or (lfptype = neg_inf and rfptype = pos_inf) then
+ -- Return quiet NAN, IEEE754-1985-7.1,2
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (lfptype = pos_inf or rfptype = pos_inf) then -- x + inf = inf
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (lfptype = neg_inf or rfptype = neg_inf) then -- x - inf = -inf
+ fpresult := neg_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (lfptype = neg_zero and rfptype = neg_zero) then -- -0 + -0 = -0
+ fpresult := neg_zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ lresize := resize (arg => to_X01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := Classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_X01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := Classfp (rresize, false); -- errors already checked
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => ulfract,
+ expon => exponl);
+ fractl := (others => '0');
+ fractl (fraction_width+addguard downto addguard) := ulfract;
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => urfract,
+ expon => exponr);
+ fractr := (others => '0');
+ fractr (fraction_width+addguard downto addguard) := urfract;
+ shiftx := (exponl(exponent_width-1) & exponl) - exponr;
+ if shiftx < -fractl'high then
+ rexpon := exponr(exponent_width-1) & exponr;
+ fractc := fractr;
+ fracts := (others => '0'); -- add zero
+ leftright := false;
+ sticky := or (fractl);
+ elsif shiftx < 0 then
+ shiftx := - shiftx;
+ fracts := shift_right (fractl, to_integer(shiftx));
+ fractc := fractr;
+ rexpon := exponr(exponent_width-1) & exponr;
+ leftright := false;
+-- sticky := or (fractl (to_integer(shiftx) downto 0));
+ sticky := smallfract (fractl, to_integer(shiftx));
+ elsif shiftx = 0 then
+ rexpon := exponl(exponent_width-1) & exponl;
+ sticky := '0';
+ if fractr > fractl then
+ fractc := fractr;
+ fracts := fractl;
+ leftright := false;
+ else
+ fractc := fractl;
+ fracts := fractr;
+ leftright := true;
+ end if;
+ elsif shiftx > fractr'high then
+ rexpon := exponl(exponent_width-1) & exponl;
+ fracts := (others => '0'); -- add zero
+ fractc := fractl;
+ leftright := true;
+ sticky := or (fractr);
+ elsif shiftx > 0 then
+ fracts := shift_right (fractr, to_integer(shiftx));
+ fractc := fractl;
+ rexpon := exponl(exponent_width-1) & exponl;
+ leftright := true;
+-- sticky := or (fractr (to_integer(shiftx) downto 0));
+ sticky := smallfract (fractr, to_integer(shiftx));
+ end if;
+ -- add
+ fracts (0) := fracts (0) or sticky; -- Or the sticky bit into the LSB
+ if l(l'high) = r(r'high) then
+ ufract := fractc + fracts;
+ sign := l(l'high);
+ else -- signs are different
+ ufract := fractc - fracts; -- always positive result
+ if leftright then -- Figure out which sign to use
+ sign := l(l'high);
+ else
+ sign := r(r'high);
+ end if;
+ end if;
+ if or (ufract) = '0' then
+ sign := '0'; -- IEEE 854, 6.3, paragraph 2.
+ end if;
+ -- normalize
+ fpresult := normalize (fract => ufract,
+ expon => rexpon,
+ sign => sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => addguard);
+ end if;
+ return fpresult;
+ end function add;
+
+ -- Subtraction, Calls "add".
+ function subtract (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ variable negr : UNRESOLVED_float (r'range); -- negative version of r
+ begin
+ negr := -r; -- r := -r
+ return add (l => l,
+ r => negr,
+ round_style => round_style,
+ guard => guard,
+ check_error => check_error,
+ denormalize => denormalize);
+ end function subtract;
+
+ -- Floating point multiply
+ function multiply (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ constant multguard : NATURAL := guard; -- guard bits
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable fractl, fractr : UNSIGNED (fraction_width downto 0); -- fractions
+ variable rfract : UNSIGNED ((2*(fraction_width))+1 downto 0); -- result fraction
+ variable sfract : UNSIGNED (fraction_width+1+multguard downto 0); -- result fraction
+ variable shifty : INTEGER; -- denormal shift
+ variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable rexpon : SIGNED (exponent_width+1 downto 0); -- result exponent
+ variable fp_sign : STD_ULOGIC; -- sign of result
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable sticky : STD_ULOGIC; -- Holds precision for rounding
+ begin -- multiply
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := Classfp (l, check_error);
+ rfptype := Classfp (r, check_error);
+ end if;
+ if (lfptype = isx or rfptype = isx) then
+ fpresult := (others => 'X');
+ elsif ((lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan)) then
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (((lfptype = pos_inf or lfptype = neg_inf) and
+ (rfptype = pos_zero or rfptype = neg_zero)) or
+ ((rfptype = pos_inf or rfptype = neg_inf) and
+ (lfptype = pos_zero or lfptype = neg_zero))) then -- 0 * inf
+ -- Return quiet NAN, IEEE754-1985-7.1,3
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (lfptype = pos_inf or rfptype = pos_inf
+ or lfptype = neg_inf or rfptype = neg_inf) then -- x * inf = inf
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ -- figure out the sign
+ fp_sign := l(l'high) xor r(r'high); -- figure out the sign
+ fpresult (exponent_width) := fp_sign;
+ else
+ fp_sign := l(l'high) xor r(r'high); -- figure out the sign
+ lresize := resize (arg => to_X01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := Classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_X01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := Classfp (rresize, false); -- errors already checked
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => fractl,
+ expon => exponl);
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => fractr,
+ expon => exponr);
+ if (rfptype = pos_denormal or rfptype = neg_denormal) then
+ shifty := fraction_width - find_leftmost(fractr, '1');
+ fractr := shift_left (fractr, shifty);
+ elsif (lfptype = pos_denormal or lfptype = neg_denormal) then
+ shifty := fraction_width - find_leftmost(fractl, '1');
+ fractl := shift_left (fractl, shifty);
+ else
+ shifty := 0;
+ -- Note that a denormal number * a denormal number is always zero.
+ end if;
+ -- multiply
+ -- add the exponents
+ rexpon := resize (exponl, rexpon'length) + exponr - shifty + 1;
+ rfract := fractl * fractr; -- Multiply the fraction
+ sfract := rfract (rfract'high downto
+ rfract'high - (fraction_width+1+multguard));
+ sticky := or (rfract (rfract'high-(fraction_width+1+multguard)
+ downto 0));
+ -- normalize
+ fpresult := normalize (fract => sfract,
+ expon => rexpon,
+ sign => fp_sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => multguard);
+ end if;
+ return fpresult;
+ end function multiply;
+
+ function short_divide (
+ lx, rx : UNSIGNED)
+ return UNSIGNED
+ is
+ -- This is a special divider for the floating point routines.
+ -- For a true unsigned divider, "stages" needs to = lx'high
+ constant stages : INTEGER := lx'high - rx'high; -- number of stages
+ variable partial : UNSIGNED (lx'range);
+ variable q : UNSIGNED (stages downto 0);
+ variable partial_argl : SIGNED (rx'high + 2 downto 0);
+ variable partial_arg : SIGNED (rx'high + 2 downto 0);
+ begin
+ partial := lx;
+ for i in stages downto 0 loop
+ partial_argl := resize ("0" & SIGNED (partial(lx'high downto i)),
+ partial_argl'length);
+ partial_arg := partial_argl - SIGNED ("0" & rx);
+ if (partial_arg (partial_arg'high) = '1') then -- negative
+ q(i) := '0';
+ else
+ q(i) := '1';
+ partial (lx'high+i-stages downto lx'high+i-stages-rx'high) :=
+ UNSIGNED (partial_arg(rx'range));
+ end if;
+ end loop;
+ -- to make the output look like that of the unsigned IEEE divide.
+ return resize (q, lx'length);
+ end function short_divide;
+
+ -- 1/X function. Needed for algorithm development.
+ function reciprocal (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := -mine(arg'low, arg'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := arg'high; -- length of FP output exponent
+ constant divguard : NATURAL := guard; -- guard bits
+ function onedivy (
+ arg : UNSIGNED)
+ return UNSIGNED
+ is
+ variable q : UNSIGNED((2*arg'high)+1 downto 0);
+ variable one : UNSIGNED (q'range);
+ begin
+ one := (others => '0');
+ one(one'high) := '1';
+ q := short_divide (one, arg); -- Unsigned divide
+ return resize (q, arg'length+1);
+ end function onedivy;
+ variable fptype : valid_fpstate;
+ variable expon : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable denorm_offset : NATURAL range 0 to 2;
+ variable fract : UNSIGNED (fraction_width downto 0);
+ variable fractg : UNSIGNED (fraction_width+divguard downto 0);
+ variable sfract : UNSIGNED (fraction_width+1+divguard downto 0); -- result fraction
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- reciprocal
+ fptype := Classfp(arg, check_error);
+ classcase : case fptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf | neg_inf => -- 1/inf, return 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when neg_zero | pos_zero => -- 1/0
+ report float_generic_pkg'instance_name
+ & "RECIPROCAL: Floating Point divide by zero"
+ severity error;
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when others =>
+ if (fptype = pos_denormal or fptype = neg_denormal)
+ and ((arg (-1) or arg(-2)) /= '1') then
+ -- 1/denormal = infinity, with the exception of 2**-expon_base
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fpresult (exponent_width) := to_x01 (arg (exponent_width));
+ else
+ break_number (
+ arg => arg,
+ fptyp => fptype,
+ denormalize => denormalize,
+ fract => fract,
+ expon => expon);
+ fractg := (others => '0');
+ if (fptype = pos_denormal or fptype = neg_denormal) then
+ -- The reciprocal of a denormal number is typically zero,
+ -- except for two special cases which are trapped here.
+ if (to_x01(arg (-1)) = '1') then
+ fractg (fractg'high downto divguard+1) :=
+ fract (fract'high-1 downto 0); -- Shift to not denormal
+ denorm_offset := 1; -- add 1 to exponent compensate
+ else -- arg(-2) = '1'
+ fractg (fractg'high downto divguard+2) :=
+ fract (fract'high-2 downto 0); -- Shift to not denormal
+ denorm_offset := 2; -- add 2 to exponent compensate
+ end if;
+ else
+ fractg (fractg'high downto divguard) := fract;
+ denorm_offset := 0;
+ end if;
+ expon := - expon - 3 + denorm_offset;
+ sfract := onedivy (fractg);
+ -- normalize
+ fpresult := normalize (fract => sfract,
+ expon => expon,
+ sign => arg(exponent_width),
+ sticky => '1',
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => divguard);
+ end if;
+ end case classcase;
+ return fpresult;
+ end function reciprocal;
+
+ -- floating point division
+ function divide (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ constant divguard : NATURAL := guard; -- division guard bits
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable ulfract, urfract : UNSIGNED (fraction_width downto 0);
+ variable fractl : UNSIGNED ((2*(fraction_width+divguard)+1) downto 0); -- left
+ variable fractr : UNSIGNED (fraction_width+divguard downto 0); -- right
+ variable rfract : UNSIGNED (fractl'range); -- result fraction
+ variable sfract : UNSIGNED (fraction_width+1+divguard downto 0); -- result fraction
+ variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable rexpon : SIGNED (exponent_width+1 downto 0); -- result exponent
+ variable fp_sign, sticky : STD_ULOGIC; -- sign of result
+ variable shifty, shiftx : INTEGER; -- denormal number shift
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- divide
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := Classfp (l, check_error);
+ rfptype := Classfp (r, check_error);
+ end if;
+ classcase : case rfptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf | neg_inf =>
+ if lfptype = pos_inf or lfptype = neg_inf -- inf / inf
+ or lfptype = quiet_nan or lfptype = nan then
+ -- Return quiet NAN, IEEE754-1985-7.1,4
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else -- x / inf = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (fpresult'high) := fp_sign; -- sign
+ end if;
+ when pos_zero | neg_zero =>
+ if lfptype = pos_zero or lfptype = neg_zero -- 0 / 0
+ or lfptype = quiet_nan or lfptype = nan then
+ -- Return quiet NAN, IEEE754-1985-7.1,4
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ report float_generic_pkg'instance_name
+ & "DIVIDE: Floating Point divide by zero"
+ severity error;
+ -- Infinity, define in 754-1985-7.2
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (fpresult'high) := fp_sign; -- sign
+ end if;
+ when others =>
+ classcase2 : case lfptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf | neg_inf => -- inf / x = inf
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult(exponent_width) := fp_sign;
+ when pos_zero | neg_zero => -- 0 / X = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult(exponent_width) := fp_sign;
+ when others =>
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ lresize := resize (arg => to_X01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := Classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_X01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := Classfp (rresize, false); -- errors already checked
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => ulfract,
+ expon => exponl);
+ -- right side
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => urfract,
+ expon => exponr);
+ -- Compute the exponent
+ rexpon := resize (exponl, rexpon'length) - exponr - 2;
+ if (rfptype = pos_denormal or rfptype = neg_denormal) then
+ -- Do the shifting here not after. That way we have a smaller
+ -- shifter, and need a smaller divider, because the top
+ -- bit in the divisor will always be a "1".
+ shifty := fraction_width - find_leftmost(urfract, '1');
+ urfract := shift_left (urfract, shifty);
+ rexpon := rexpon + shifty;
+ end if;
+ fractr := (others => '0');
+ fractr (fraction_width+divguard downto divguard) := urfract;
+ if (lfptype = pos_denormal or lfptype = neg_denormal) then
+ shiftx := fraction_width - find_leftmost(ulfract, '1');
+ ulfract := shift_left (ulfract, shiftx);
+ rexpon := rexpon - shiftx;
+ end if;
+ fractl := (others => '0');
+ fractl (fractl'high downto fractl'high-fraction_width) := ulfract;
+ -- divide
+ rfract := short_divide (fractl, fractr); -- unsigned divide
+ sfract := rfract (sfract'range); -- lower bits
+ sticky := '1';
+ -- normalize
+ fpresult := normalize (fract => sfract,
+ expon => rexpon,
+ sign => fp_sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => divguard);
+ end case classcase2;
+ end case classcase;
+ return fpresult;
+ end function divide;
+
+ -- division by a power of 2
+ function dividebyp2 (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable ulfract, urfract : UNSIGNED (fraction_width downto 0);
+ variable exponl, exponr : SIGNED(exponent_width-1 downto 0); -- exponents
+ variable rexpon : SIGNED(exponent_width downto 0); -- result exponent
+ variable fp_sign : STD_ULOGIC; -- sign of result
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- divisionbyp2
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := Classfp (l, check_error);
+ rfptype := Classfp (r, check_error);
+ end if;
+ classcase : case rfptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf | neg_inf =>
+ if lfptype = pos_inf or lfptype = neg_inf then -- inf / inf
+ -- Return quiet NAN, IEEE754-1985-7.1,4
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else -- x / inf = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (fpresult'high) := fp_sign; -- sign
+ end if;
+ when pos_zero | neg_zero =>
+ if lfptype = pos_zero or lfptype = neg_zero then -- 0 / 0
+ -- Return quiet NAN, IEEE754-1985-7.1,4
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ report float_generic_pkg'instance_name
+ & "DIVIDEBYP2: Floating Point divide by zero"
+ severity error;
+ -- Infinity, define in 754-1985-7.2
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (fpresult'high) := fp_sign; -- sign
+ end if;
+ when others =>
+ classcase2 : case lfptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf | neg_inf => -- inf / x = inf
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (exponent_width) := fp_sign; -- sign
+ when pos_zero | neg_zero => -- 0 / X = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (exponent_width) := fp_sign; -- sign
+ when others =>
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ lresize := resize (arg => to_X01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := Classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_X01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := Classfp (rresize, false); -- errors already checked
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => ulfract,
+ expon => exponl);
+ -- right side
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => urfract,
+ expon => exponr);
+ assert (or (urfract (fraction_width-1 downto 0)) = '0')
+ report float_generic_pkg'instance_name
+ & "DIVIDEBYP2: "
+ & "Dividebyp2 called with a non power of two divisor"
+ severity error;
+ rexpon := (exponl(exponl'high)&exponl)
+ - (exponr(exponr'high)&exponr) - 1;
+ -- normalize
+ fpresult := normalize (fract => ulfract,
+ expon => rexpon,
+ sign => fp_sign,
+ sticky => '1',
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => 0);
+ end case classcase2;
+ end case classcase;
+ return fpresult;
+ end function dividebyp2;
+
+ -- Multiply accumulate result = l*r + c
+ function mac (
+ l, r, c : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL :=
+ -mine (mine(l'low, r'low), c'low); -- length of FP output fraction
+ constant exponent_width : NATURAL :=
+ maximum (maximum(l'high, r'high), c'high); -- length of FP output exponent
+ variable lfptype, rfptype, cfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable fractl, fractr : UNSIGNED (fraction_width downto 0); -- fractions
+ variable fractx : UNSIGNED (fraction_width+guard downto 0);
+ variable fractc, fracts : UNSIGNED (fraction_width+1+guard downto 0);
+ variable rfract : UNSIGNED ((2*(fraction_width))+1 downto 0); -- result fraction
+ variable ufract : UNSIGNED (fraction_width+1+guard downto 0); -- result fraction
+ variable exponl, exponr, exponc : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable rexpon, rexpon2 : SIGNED (exponent_width+1 downto 0); -- result exponent
+ variable shifty : INTEGER; -- denormal shift
+ variable shiftx : SIGNED (rexpon'range); -- shift fractions
+ variable fp_sign : STD_ULOGIC; -- sign of result
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable cresize : UNRESOLVED_float (exponent_width downto -fraction_width - guard);
+ variable leftright : BOOLEAN; -- left or right used
+ variable sticky : STD_ULOGIC; -- Holds precision for rounding
+ begin -- multiply
+ if (fraction_width = 0 or l'length < 7 or r'length < 7 or c'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := Classfp (l, check_error);
+ rfptype := Classfp (r, check_error);
+ cfptype := Classfp (c, check_error);
+ end if;
+ if (lfptype = isx or rfptype = isx or cfptype = isx) then
+ fpresult := (others => 'X');
+ elsif (lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan or
+ cfptype = nan or cfptype = quiet_nan) then
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (((lfptype = pos_inf or lfptype = neg_inf) and
+ (rfptype = pos_zero or rfptype = neg_zero)) or
+ ((rfptype = pos_inf or rfptype = neg_inf) and
+ (lfptype = pos_zero or lfptype = neg_zero))) then -- 0 * inf
+ -- Return quiet NAN, IEEE754-1985-7.1,3
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (lfptype = pos_inf or rfptype = pos_inf
+ or lfptype = neg_inf or rfptype = neg_inf -- x * inf = inf
+ or cfptype = neg_inf or cfptype = pos_inf) then -- x + inf = inf
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ -- figure out the sign
+ fpresult (exponent_width) := l(l'high) xor r(r'high);
+ else
+ fp_sign := l(l'high) xor r(r'high); -- figure out the sign
+ lresize := resize (arg => to_X01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := Classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_X01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := Classfp (rresize, false); -- errors already checked
+ cresize := resize (arg => to_X01(c),
+ exponent_width => exponent_width,
+ fraction_width => -cresize'low,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ cfptype := Classfp (cresize, false); -- errors already checked
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => fractl,
+ expon => exponl);
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => fractr,
+ expon => exponr);
+ break_number (
+ arg => cresize,
+ fptyp => cfptype,
+ denormalize => denormalize,
+ fract => fractx,
+ expon => exponc);
+ if (rfptype = pos_denormal or rfptype = neg_denormal) then
+ shifty := fraction_width - find_leftmost(fractr, '1');
+ fractr := shift_left (fractr, shifty);
+ elsif (lfptype = pos_denormal or lfptype = neg_denormal) then
+ shifty := fraction_width - find_leftmost(fractl, '1');
+ fractl := shift_left (fractl, shifty);
+ else
+ shifty := 0;
+ -- Note that a denormal number * a denormal number is always zero.
+ end if;
+ -- multiply
+ rfract := fractl * fractr; -- Multiply the fraction
+ -- add the exponents
+ rexpon := resize (exponl, rexpon'length) + exponr - shifty + 1;
+ shiftx := rexpon - exponc;
+ if shiftx < -fractl'high then
+ rexpon2 := resize (exponc, rexpon2'length);
+ fractc := "0" & fractx;
+ fracts := (others => '0');
+ sticky := or (rfract);
+ elsif shiftx < 0 then
+ shiftx := - shiftx;
+ fracts := shift_right (rfract (rfract'high downto rfract'high
+ - fracts'length+1),
+ to_integer(shiftx));
+ fractc := "0" & fractx;
+ rexpon2 := resize (exponc, rexpon2'length);
+ leftright := false;
+ sticky := or (rfract (to_integer(shiftx)+rfract'high
+ - fracts'length downto 0));
+ elsif shiftx = 0 then
+ rexpon2 := resize (exponc, rexpon2'length);
+ sticky := or (rfract (rfract'high - fractc'length downto 0));
+ if rfract (rfract'high downto rfract'high - fractc'length+1) > fractx
+ then
+ fractc := "0" & fractx;
+ fracts := rfract (rfract'high downto rfract'high
+ - fracts'length+1);
+ leftright := false;
+ else
+ fractc := rfract (rfract'high downto rfract'high
+ - fractc'length+1);
+ fracts := "0" & fractx;
+ leftright := true;
+ end if;
+ elsif shiftx > fractx'high then
+ rexpon2 := rexpon;
+ fracts := (others => '0');
+ fractc := rfract (rfract'high downto rfract'high - fractc'length+1);
+ leftright := true;
+ sticky := or (fractx & rfract (rfract'high - fractc'length
+ downto 0));
+ else -- fractx'high > shiftx > 0
+ rexpon2 := rexpon;
+ fracts := "0" & shift_right (fractx, to_integer (shiftx));
+ fractc := rfract (rfract'high downto rfract'high - fractc'length+1);
+ leftright := true;
+ sticky := or (fractx (to_integer (shiftx) downto 0)
+ & rfract (rfract'high - fractc'length downto 0));
+ end if;
+ fracts (0) := fracts (0) or sticky; -- Or the sticky bit into the LSB
+ if fp_sign = to_X01(c(c'high)) then
+ ufract := fractc + fracts;
+ fp_sign := fp_sign;
+ else -- signs are different
+ ufract := fractc - fracts; -- always positive result
+ if leftright then -- Figure out which sign to use
+ fp_sign := fp_sign;
+ else
+ fp_sign := c(c'high);
+ end if;
+ end if;
+ -- normalize
+ fpresult := normalize (fract => ufract,
+ expon => rexpon2,
+ sign => fp_sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => guard);
+ end if;
+ return fpresult;
+ end function mac;
+
+ -- "rem" function
+ function remainder (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ constant divguard : NATURAL := guard; -- division guard bits
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable ulfract, urfract : UNSIGNED (fraction_width downto 0);
+ variable fractr, fractl : UNSIGNED (fraction_width+divguard downto 0); -- right
+ variable rfract : UNSIGNED (fractr'range); -- result fraction
+ variable sfract : UNSIGNED (fraction_width+divguard downto 0); -- result fraction
+ variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable rexpon : SIGNED (exponent_width downto 0); -- result exponent
+ variable fp_sign : STD_ULOGIC; -- sign of result
+ variable shifty : INTEGER; -- denormal number shift
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- remainder
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := Classfp (l, check_error);
+ rfptype := Classfp (r, check_error);
+ end if;
+ if (lfptype = isx or rfptype = isx) then
+ fpresult := (others => 'X');
+ elsif (lfptype = nan or lfptype = quiet_nan)
+ or (rfptype = nan or rfptype = quiet_nan)
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ or (lfptype = pos_inf or lfptype = neg_inf) -- inf rem x
+ -- Return quiet NAN, IEEE754-1985-7.1,5
+ or (rfptype = pos_zero or rfptype = neg_zero) then -- x rem 0
+ -- Return quiet NAN, IEEE754-1985-7.1,5
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (rfptype = pos_inf or rfptype = neg_inf) then -- x rem inf = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (abs(l) < abs(r)) then
+ fpresult := l;
+ else
+ fp_sign := to_X01(l(l'high)); -- sign
+ lresize := resize (arg => to_X01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := Classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_X01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := Classfp (rresize, false); -- errors already checked
+ fractl := (others => '0');
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => ulfract,
+ expon => exponl);
+ fractl (fraction_width+divguard downto divguard) := ulfract;
+ -- right side
+ fractr := (others => '0');
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => urfract,
+ expon => exponr);
+ fractr (fraction_width+divguard downto divguard) := urfract;
+ rexpon := (exponr(exponr'high)&exponr);
+ shifty := to_integer(exponl - rexpon);
+ if (shifty > 0) then
+ fractr := shift_right (fractr, shifty);
+ rexpon := rexpon + shifty;
+ end if;
+ if (fractr /= 0) then
+ -- rem
+ rfract := fractl rem fractr; -- unsigned rem
+ sfract := rfract (sfract'range); -- lower bits
+ -- normalize
+ fpresult := normalize (fract => sfract,
+ expon => rexpon,
+ sign => fp_sign,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => divguard);
+ else
+ -- If we shift "fractr" so far that it becomes zero, return zero.
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ end if;
+ end if;
+ return fpresult;
+ end function remainder;
+
+ -- "mod" function
+ function modulo (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := - mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable remres : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- remainder
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := Classfp (l, check_error);
+ rfptype := Classfp (r, check_error);
+ end if;
+ if (lfptype = isx or rfptype = isx) then
+ fpresult := (others => 'X');
+ elsif (lfptype = nan or lfptype = quiet_nan)
+ or (rfptype = nan or rfptype = quiet_nan)
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ or (lfptype = pos_inf or lfptype = neg_inf) -- inf rem x
+ -- Return quiet NAN, IEEE754-1985-7.1,5
+ or (rfptype = pos_zero or rfptype = neg_zero) then -- x rem 0
+ -- Return quiet NAN, IEEE754-1985-7.1,5
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (rfptype = pos_inf or rfptype = neg_inf) then -- x rem inf = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ remres := remainder (l => abs(l),
+ r => abs(r),
+ round_style => round_style,
+ guard => guard,
+ check_error => false,
+ denormalize => denormalize);
+ -- MOD is the same as REM, but you do something different with
+ -- negative values
+ if (Is_Negative (l)) then
+ remres := - remres;
+ end if;
+ if (Is_Negative (l) = Is_Negative (r) or remres = 0) then
+ fpresult := remres;
+ else
+ fpresult := add (l => remres,
+ r => r,
+ round_style => round_style,
+ guard => guard,
+ check_error => false,
+ denormalize => denormalize);
+ end if;
+ end if;
+ return fpresult;
+ end function modulo;
+
+ -- Square root of a floating point number. Done using Newton's Iteration.
+ function sqrt (
+ arg : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style;
+ constant guard : NATURAL := float_guard_bits;
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := guard-arg'low; -- length of FP output fraction
+ constant exponent_width : NATURAL := arg'high; -- length of FP output exponent
+ variable sign : STD_ULOGIC;
+ variable fpresult : float (arg'range);
+ variable fptype : valid_fpstate;
+ variable iexpon : SIGNED(exponent_width-1 downto 0); -- exponents
+ variable expon : SIGNED(exponent_width downto 0); -- exponents
+ variable ufact : ufixed (0 downto arg'low);
+ variable fact : ufixed (2 downto -fraction_width); -- fraction
+ variable resb : ufixed (fact'high+1 downto fact'low);
+ begin -- square root
+ fptype := Classfp (arg, check_error);
+ classcase : case fptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan |
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ neg_normal | neg_denormal | neg_inf => -- sqrt (neg)
+ -- Return quiet NAN, IEEE754-1985-7.1.6
+ fpresult := qnanfp (fraction_width => fraction_width-guard,
+ exponent_width => exponent_width);
+ when pos_inf => -- Sqrt (inf), return infinity
+ fpresult := pos_inffp (fraction_width => fraction_width-guard,
+ exponent_width => exponent_width);
+ when pos_zero => -- return 0
+ fpresult := zerofp (fraction_width => fraction_width-guard,
+ exponent_width => exponent_width);
+ when neg_zero => -- IEEE754-1985-6.3 return -0
+ fpresult := neg_zerofp (fraction_width => fraction_width-guard,
+ exponent_width => exponent_width);
+ when others =>
+ break_number (arg => arg,
+ denormalize => denormalize,
+ check_error => false,
+ fract => ufact,
+ expon => iexpon,
+ sign => sign);
+ expon := resize (iexpon+1, expon'length); -- get exponent
+ fact := resize (ufact, fact'high, fact'low);
+ if (expon(0) = '1') then
+ fact := fact sla 1; -- * 2.0
+ end if;
+ expon := shift_right (expon, 1); -- exponent/2
+ -- Newton's iteration - root := (1 + arg) / 2
+ resb := (fact + 1) sra 1;
+ for j in 0 to fraction_width/4 loop
+ -- root := (root + (arg/root))/2
+ resb := resize (arg => (resb + (fact/resb)) sra 1,
+ left_index => resb'high,
+ right_index => resb'low,
+ round_style => fixed_truncate,
+ overflow_style => fixed_wrap);
+ end loop;
+ fpresult := normalize (fract => resb,
+ expon => expon-1,
+ sign => '0',
+ exponent_width => arg'high,
+ fraction_width => -arg'low,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => guard);
+ end case classcase;
+ return fpresult;
+ end function sqrt;
+
+ function Is_Negative (arg : UNRESOLVED_float) return BOOLEAN is
+ -- Technically -0 should return "false", but I'm leaving that case out.
+ begin
+ return (to_x01(arg(arg'high)) = '1');
+ end function Is_Negative;
+
+ -- compare functions
+ -- =, /=, >=, <=, <, >
+
+ function eq ( -- equal =
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN
+ is
+ variable lfptype, rfptype : valid_fpstate;
+ variable is_equal, is_unordered : BOOLEAN;
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- equal
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ return false;
+ else
+ lfptype := Classfp (l, check_error);
+ rfptype := Classfp (r, check_error);
+ end if;
+ if (lfptype = neg_zero or lfptype = pos_zero) and
+ (rfptype = neg_zero or rfptype = pos_zero) then
+ is_equal := true;
+ else
+ lresize := resize (arg => to_X01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rresize := resize (arg => to_X01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ is_equal := (to_slv(lresize) = to_slv(rresize));
+ end if;
+ if (check_error) then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return is_equal and not is_unordered;
+ end function eq;
+
+ function lt ( -- less than <
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN
+ is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable expl, expr : UNSIGNED (exponent_width-1 downto 0);
+ variable fractl, fractr : UNSIGNED (fraction_width-1 downto 0);
+ variable is_less_than, is_unordered : BOOLEAN;
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ is_less_than := false;
+ else
+ lresize := resize (arg => to_X01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rresize := resize (arg => to_X01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ if to_x01(l(l'high)) = to_x01(r(r'high)) then -- sign bits
+ expl := UNSIGNED(lresize(exponent_width-1 downto 0));
+ expr := UNSIGNED(rresize(exponent_width-1 downto 0));
+ if expl = expr then
+ fractl := UNSIGNED (to_slv(lresize(-1 downto -fraction_width)));
+ fractr := UNSIGNED (to_slv(rresize(-1 downto -fraction_width)));
+ if to_x01(l(l'high)) = '0' then -- positive number
+ is_less_than := (fractl < fractr);
+ else
+ is_less_than := (fractl > fractr); -- negative
+ end if;
+ else
+ if to_x01(l(l'high)) = '0' then -- positive number
+ is_less_than := (expl < expr);
+ else
+ is_less_than := (expl > expr); -- negative
+ end if;
+ end if;
+ else
+ lfptype := Classfp (l, check_error);
+ rfptype := Classfp (r, check_error);
+ if (lfptype = neg_zero and rfptype = pos_zero) then
+ is_less_than := false; -- -0 < 0 returns false.
+ else
+ is_less_than := (to_x01(l(l'high)) > to_x01(r(r'high)));
+ end if;
+ end if;
+ end if;
+ if check_error then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return is_less_than and not is_unordered;
+ end function lt;
+
+ function gt ( -- greater than >
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN
+ is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable expl, expr : UNSIGNED (exponent_width-1 downto 0);
+ variable fractl, fractr : UNSIGNED (fraction_width-1 downto 0);
+ variable is_greater_than : BOOLEAN;
+ variable is_unordered : BOOLEAN;
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- greater_than
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ is_greater_than := false;
+ else
+ lresize := resize (arg => to_X01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rresize := resize (arg => to_X01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ if to_x01(l(l'high)) = to_x01(r(r'high)) then -- sign bits
+ expl := UNSIGNED(lresize(exponent_width-1 downto 0));
+ expr := UNSIGNED(rresize(exponent_width-1 downto 0));
+ if expl = expr then
+ fractl := UNSIGNED (to_slv(lresize(-1 downto -fraction_width)));
+ fractr := UNSIGNED (to_slv(rresize(-1 downto -fraction_width)));
+ if to_x01(l(l'high)) = '0' then -- positive number
+ is_greater_than := fractl > fractr;
+ else
+ is_greater_than := fractl < fractr; -- negative
+ end if;
+ else
+ if to_x01(l(l'high)) = '0' then -- positive number
+ is_greater_than := expl > expr;
+ else
+ is_greater_than := expl < expr; -- negative
+ end if;
+ end if;
+ else
+ lfptype := Classfp (l, check_error);
+ rfptype := Classfp (r, check_error);
+ if (lfptype = pos_zero and rfptype = neg_zero) then
+ is_greater_than := false; -- 0 > -0 returns false.
+ else
+ is_greater_than := to_x01(l(l'high)) < to_x01(r(r'high));
+ end if;
+ end if;
+ end if;
+ if check_error then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return is_greater_than and not is_unordered;
+ end function gt;
+
+ -- purpose: /= function
+ function ne ( -- not equal /=
+ l, r : UNRESOLVED_float;
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN
+ is
+ variable is_equal, is_unordered : BOOLEAN;
+ begin
+ is_equal := eq (l => l,
+ r => r,
+ check_error => false,
+ denormalize => denormalize);
+ if check_error then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return not (is_equal and not is_unordered);
+ end function ne;
+
+ function le ( -- less than or equal to <=
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN
+ is
+ variable is_greater_than, is_unordered : BOOLEAN;
+ begin
+ is_greater_than := gt (l => l,
+ r => r,
+ check_error => false,
+ denormalize => denormalize);
+ if check_error then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return not is_greater_than and not is_unordered;
+ end function le;
+
+ function ge ( -- greater than or equal to >=
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN
+ is
+ variable is_less_than, is_unordered : BOOLEAN;
+ begin
+ is_less_than := lt (l => l,
+ r => r,
+ check_error => false,
+ denormalize => denormalize);
+ if check_error then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return not is_less_than and not is_unordered;
+ end function ge;
+
+ function "?=" (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(L'low, R'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(L'high, R'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable is_equal, is_unordered : STD_ULOGIC;
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- ?=
+ if (fraction_width = 0 or L'length < 7 or R'length < 7) then
+ return 'X';
+ else
+ lfptype := Classfp (L, float_check_error);
+ rfptype := Classfp (R, float_check_error);
+ end if;
+ if (lfptype = neg_zero or lfptype = pos_zero) and
+ (rfptype = neg_zero or rfptype = pos_zero) then
+ is_equal := '1';
+ else
+ lresize := resize (arg => L,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => float_denormalize,
+ denormalize => float_denormalize);
+ rresize := resize (arg => R,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => float_denormalize,
+ denormalize => float_denormalize);
+ is_equal := to_sulv(lresize) ?= to_sulv(rresize);
+ end if;
+ if (float_check_error) then
+ if (lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan) then
+ is_unordered := '1';
+ else
+ is_unordered := '0';
+ end if;
+ else
+ is_unordered := '0';
+ end if;
+ return is_equal and not is_unordered;
+ end function "?=";
+
+ function "?/=" (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(L'low, R'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(L'high, R'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable is_equal, is_unordered : STD_ULOGIC;
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- ?/=
+ if (fraction_width = 0 or L'length < 7 or R'length < 7) then
+ return 'X';
+ else
+ lfptype := Classfp (L, float_check_error);
+ rfptype := Classfp (R, float_check_error);
+ end if;
+ if (lfptype = neg_zero or lfptype = pos_zero) and
+ (rfptype = neg_zero or rfptype = pos_zero) then
+ is_equal := '1';
+ else
+ lresize := resize (arg => L,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => float_denormalize,
+ denormalize => float_denormalize);
+ rresize := resize (arg => R,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => float_denormalize,
+ denormalize => float_denormalize);
+ is_equal := to_sulv(lresize) ?= to_sulv(rresize);
+ end if;
+ if (float_check_error) then
+ if (lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan) then
+ is_unordered := '1';
+ else
+ is_unordered := '0';
+ end if;
+ else
+ is_unordered := '0';
+ end if;
+ return not (is_equal and not is_unordered);
+ end function "?/=";
+
+ function "?>" (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(L'low, R'low);
+ variable founddash : BOOLEAN := false;
+ begin
+ if (fraction_width = 0 or L'length < 7 or R'length < 7) then
+ return 'X';
+ else
+ for i in L'range loop
+ if L(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ for i in R'range loop
+ if R(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ if founddash then
+ report float_generic_pkg'instance_name
+ & " ""?>"": '-' found in compare string"
+ severity error;
+ return 'X';
+ elsif Is_X(L) or Is_X(R) then
+ return 'X';
+ elsif L > R then
+ return '1';
+ else
+ return '0';
+ end if;
+ end if;
+ end function "?>";
+
+ function "?>=" (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(L'low, R'low);
+ variable founddash : BOOLEAN := false;
+ begin
+ if (fraction_width = 0 or L'length < 7 or R'length < 7) then
+ return 'X';
+ else
+ for i in L'range loop
+ if L(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ for i in R'range loop
+ if R(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ if founddash then
+ report float_generic_pkg'instance_name
+ & " ""?>="": '-' found in compare string"
+ severity error;
+ return 'X';
+ elsif Is_X(L) or Is_X(R) then
+ return 'X';
+ elsif L >= R then
+ return '1';
+ else
+ return '0';
+ end if;
+ end if;
+ end function "?>=";
+
+ function "?<" (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(L'low, R'low);
+ variable founddash : BOOLEAN := false;
+ begin
+ if (fraction_width = 0 or L'length < 7 or R'length < 7) then
+ return 'X';
+ else
+ for i in L'range loop
+ if L(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ for i in R'range loop
+ if R(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ if founddash then
+ report float_generic_pkg'instance_name
+ & " ""?<"": '-' found in compare string"
+ severity error;
+ return 'X';
+ elsif Is_X(L) or Is_X(R) then
+ return 'X';
+ elsif L < R then
+ return '1';
+ else
+ return '0';
+ end if;
+ end if;
+ end function "?<";
+
+ function "?<=" (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(L'low, R'low);
+ variable founddash : BOOLEAN := false;
+ begin
+ if (fraction_width = 0 or L'length < 7 or R'length < 7) then
+ return 'X';
+ else
+ for i in L'range loop
+ if L(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ for i in R'range loop
+ if R(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ if founddash then
+ report float_generic_pkg'instance_name
+ & " ""?<="": '-' found in compare string"
+ severity error;
+ return 'X';
+ elsif Is_X(L) or Is_X(R) then
+ return 'X';
+ elsif L <= R then
+ return '1';
+ else
+ return '0';
+ end if;
+ end if;
+ end function "?<=";
+
+ function std_match (L, R : UNRESOLVED_float) return BOOLEAN is
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ return std_match(to_sulv(L), to_sulv(R));
+ else
+ report float_generic_pkg'instance_name
+ & "STD_MATCH: L'RANGE /= R'RANGE, returning FALSE"
+ severity warning;
+ return false;
+ end if;
+ end function std_match;
+
+ function find_rightmost (arg : UNRESOLVED_float; y : STD_ULOGIC) return INTEGER is
+ begin
+ for_loop : for i in arg'reverse_range loop
+ if arg(i) ?= y then
+ return i;
+ end if;
+ end loop;
+ return arg'high+1; -- return out of bounds 'high
+ end function find_rightmost;
+
+ function find_leftmost (arg : UNRESOLVED_float; y : STD_ULOGIC) return INTEGER is
+ begin
+ for_loop : for i in arg'range loop
+ if arg(i) ?= y then
+ return i;
+ end if;
+ end loop;
+ return arg'low-1; -- return out of bounds 'low
+ end function find_leftmost;
+
+ -- These override the defaults for the compare operators.
+ function "=" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return eq(l, r);
+ end function "=";
+
+ function "/=" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return ne(l, r);
+ end function "/=";
+
+ function ">=" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return ge(l, r);
+ end function ">=";
+
+ function "<=" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return le(l, r);
+ end function "<=";
+
+ function ">" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return gt(l, r);
+ end function ">";
+
+ function "<" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return lt(l, r);
+ end function "<";
+
+ -- purpose: maximum of two numbers (overrides default)
+ function maximum (
+ L, R : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := -mine(L'low, R'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(L'high, R'high); -- length of FP output exponent
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin
+ if ((L'length < 1) or (R'length < 1)) then return NAFP;
+ end if;
+ lresize := resize (L, exponent_width, fraction_width);
+ rresize := resize (R, exponent_width, fraction_width);
+ if lresize > rresize then return lresize;
+ else return rresize;
+ end if;
+ end function maximum;
+
+ function minimum (
+ L, R : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := -mine(L'low, R'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(L'high, R'high); -- length of FP output exponent
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin
+ if ((L'length < 1) or (R'length < 1)) then return NAFP;
+ end if;
+ lresize := resize (L, exponent_width, fraction_width);
+ rresize := resize (R, exponent_width, fraction_width);
+ if lresize > rresize then return rresize;
+ else return lresize;
+ end if;
+ end function minimum;
+
+ -----------------------------------------------------------------------------
+ -- conversion functions
+ -----------------------------------------------------------------------------
+
+ -- Converts a floating point number of one format into another format
+ function resize (
+ arg : UNRESOLVED_float; -- Floating point input
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ constant in_fraction_width : NATURAL := -arg'low; -- length of FP output fraction
+ constant in_exponent_width : NATURAL := arg'high; -- length of FP output exponent
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ -- result value
+ variable fptype : valid_fpstate;
+ variable expon_in : SIGNED (in_exponent_width-1 downto 0);
+ variable fract_in : UNSIGNED (in_fraction_width downto 0);
+ variable expon_out : SIGNED (exponent_width-1 downto 0); -- output fract
+ variable fract_out : UNSIGNED (fraction_width downto 0); -- output fract
+ begin
+ fptype := Classfp(arg, check_error);
+ if ((fptype = pos_denormal or fptype = neg_denormal) and denormalize_in
+ and (in_exponent_width < exponent_width
+ or in_fraction_width < fraction_width))
+ or in_exponent_width > exponent_width
+ or in_fraction_width > fraction_width then
+ -- size reduction
+ classcase : case fptype is
+ when isx =>
+ result := (others => 'X');
+ when nan | quiet_nan =>
+ result := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf =>
+ result := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when neg_inf =>
+ result := neg_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_zero | neg_zero =>
+ result := zerofp (fraction_width => fraction_width, -- hate -0
+ exponent_width => exponent_width);
+ when others =>
+ break_number (
+ arg => arg,
+ fptyp => fptype,
+ denormalize => denormalize_in,
+ fract => fract_in,
+ expon => expon_in);
+ if fraction_width > in_fraction_width and denormalize_in then
+ -- You only get here if you have a denormal input
+ fract_out := (others => '0'); -- pad with zeros
+ fract_out (fraction_width downto
+ fraction_width - in_fraction_width) := fract_in;
+ result := normalize (
+ fract => fract_out,
+ expon => expon_in,
+ sign => arg(arg'high),
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => 0);
+ else
+ result := normalize (
+ fract => fract_in,
+ expon => expon_in,
+ sign => arg(arg'high),
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => in_fraction_width - fraction_width);
+ end if;
+ end case classcase;
+ else -- size increase or the same size
+ if exponent_width > in_exponent_width then
+ expon_in := SIGNED(arg (in_exponent_width-1 downto 0));
+ if fptype = pos_zero or fptype = neg_zero then
+ result (exponent_width-1 downto 0) := (others => '0');
+ elsif expon_in = -1 then -- inf or nan (shorts out check_error)
+ result (exponent_width-1 downto 0) := (others => '1');
+ else
+ -- invert top BIT
+ expon_in(expon_in'high) := not expon_in(expon_in'high);
+ expon_out := resize (expon_in, expon_out'length); -- signed expand
+ -- Flip it back.
+ expon_out(expon_out'high) := not expon_out(expon_out'high);
+ result (exponent_width-1 downto 0) := UNRESOLVED_float(expon_out);
+ end if;
+ result (exponent_width) := arg (in_exponent_width); -- sign
+ else -- exponent_width = in_exponent_width
+ result (exponent_width downto 0) := arg (in_exponent_width downto 0);
+ end if;
+ if fraction_width > in_fraction_width then
+ result (-1 downto -fraction_width) := (others => '0'); -- zeros
+ result (-1 downto -in_fraction_width) :=
+ arg (-1 downto -in_fraction_width);
+ else -- fraction_width = in_fraciton_width
+ result (-1 downto -fraction_width) :=
+ arg (-1 downto -in_fraction_width);
+ end if;
+ end if;
+ return result;
+ end function resize;
+
+ function resize (
+ arg : UNRESOLVED_float; -- floating point input
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := resize (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize_in => denormalize_in,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function resize;
+
+ function to_float32 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float32 is
+ begin
+ return resize (arg => arg,
+ exponent_width => float32'high,
+ fraction_width => -float32'low,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize_in => denormalize_in,
+ denormalize => denormalize);
+ end function to_float32;
+
+ function to_float64 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float64 is
+ begin
+ return resize (arg => arg,
+ exponent_width => float64'high,
+ fraction_width => -float64'low,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize_in => denormalize_in,
+ denormalize => denormalize);
+ end function to_float64;
+
+ function to_float128 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float128 is
+ begin
+ return resize (arg => arg,
+ exponent_width => float128'high,
+ fraction_width => -float128'low,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize_in => denormalize_in,
+ denormalize => denormalize);
+ end function to_float128;
+
+ -- to_float (Real)
+ -- typically not Synthesizable unless the input is a constant.
+ function to_float (
+ arg : REAL;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable arg_real : REAL; -- Real version of argument
+ variable validfp : boundary_type; -- Check for valid results
+ variable exp : INTEGER; -- Integer version of exponent
+ variable expon : UNSIGNED (exponent_width - 1 downto 0);
+ -- Unsigned version of exp.
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable fract : UNSIGNED (fraction_width-1 downto 0);
+ variable frac : REAL; -- Real version of fraction
+ constant roundfrac : REAL := 2.0 ** (-2 - fract'high); -- used for rounding
+ variable round : BOOLEAN; -- to round or not to round
+ begin
+ result := (others => '0');
+ arg_real := arg;
+ if arg_real < 0.0 then
+ result (exponent_width) := '1';
+ arg_real := - arg_real; -- Make it positive.
+ else
+ result (exponent_width) := '0';
+ end if;
+ test_boundary (arg => arg_real,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ denormalize => denormalize,
+ btype => validfp,
+ log2i => exp);
+ if validfp = zero then
+ return result; -- Result initialized to "0".
+ elsif validfp = infinity then
+ result (exponent_width - 1 downto 0) := (others => '1'); -- Exponent all "1"
+ -- return infinity.
+ return result;
+ else
+ if validfp = denormal then -- Exponent will default to "0".
+ expon := (others => '0');
+ frac := arg_real * (2.0 ** (to_integer(expon_base)-1));
+ else -- Number less than 1. "normal" number
+ expon := UNSIGNED (to_signed (exp-1, exponent_width));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ frac := (arg_real / 2.0 ** exp) - 1.0; -- Number less than 1.
+ end if;
+ for i in 0 to fract'high loop
+ if frac >= 2.0 ** (-1 - i) then
+ fract (fract'high - i) := '1';
+ frac := frac - 2.0 ** (-1 - i);
+ else
+ fract (fract'high - i) := '0';
+ end if;
+ end loop;
+ round := false;
+ case round_style is
+ when round_nearest =>
+ if frac > roundfrac or ((frac = roundfrac) and fract(0) = '1') then
+ round := true;
+ end if;
+ when round_inf =>
+ if frac /= 0.0 and result(exponent_width) = '0' then
+ round := true;
+ end if;
+ when round_neginf =>
+ if frac /= 0.0 and result(exponent_width) = '1' then
+ round := true;
+ end if;
+ when others =>
+ null; -- don't round
+ end case;
+ if (round) then
+ if and(fract) = '1' then -- fraction is all "1"
+ expon := expon + 1;
+ fract := (others => '0');
+ else
+ fract := fract + 1;
+ end if;
+ end if;
+ result (exponent_width-1 downto 0) := UNRESOLVED_float(expon);
+ result (-1 downto -fraction_width) := UNRESOLVED_float(fract);
+ return result;
+ end if;
+ end function to_float;
+
+ -- to_float (Integer)
+ function to_float (
+ arg : INTEGER;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable arg_int : NATURAL; -- Natural version of argument
+ variable expon : SIGNED (exponent_width-1 downto 0);
+ variable exptmp : SIGNED (exponent_width-1 downto 0);
+ -- Unsigned version of exp.
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable fract : UNSIGNED (fraction_width-1 downto 0) := (others => '0');
+ variable fracttmp : UNSIGNED (fraction_width-1 downto 0);
+ variable round : BOOLEAN;
+ variable shift : NATURAL;
+ variable shiftr : NATURAL;
+ variable roundfrac : NATURAL; -- used in rounding
+ begin
+ if arg < 0 then
+ result (exponent_width) := '1';
+ arg_int := -arg; -- Make it positive.
+ else
+ result (exponent_width) := '0';
+ arg_int := arg;
+ end if;
+ if arg_int = 0 then
+ result := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ -- If the number is larger than we can represent in this number system
+ -- we need to return infinity.
+ shift := log2(arg_int);
+ if shift > to_integer(expon_base) then
+ -- worry about infinity
+ if result (exponent_width) = '0' then
+ result := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ -- return negative infinity.
+ result := neg_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ end if;
+ else -- Normal number (can't be denormal)
+ -- Compute Exponent
+ expon := to_signed (shift-1, expon'length); -- positive fraction.
+ -- Compute Fraction
+ arg_int := arg_int - 2**shift; -- Subtract off the 1.0
+ shiftr := shift;
+ for I in fract'high downto maximum (fract'high - shift + 1, 0) loop
+ shiftr := shiftr - 1;
+ if (arg_int >= 2**shiftr) then
+ arg_int := arg_int - 2**shiftr;
+ fract(I) := '1';
+ else
+ fract(I) := '0';
+ end if;
+ end loop;
+ -- Rounding routine
+ round := false;
+ if arg_int > 0 then
+ roundfrac := 2**(shiftr-1);
+ case round_style is
+ when round_nearest =>
+ if arg_int > roundfrac or
+ ((arg_int = roundfrac) and fract(0) = '1') then
+ round := true;
+ end if;
+ when round_inf =>
+ if arg_int /= 0 and result (exponent_width) = '0' then
+ round := true;
+ end if;
+ when round_neginf =>
+ if arg_int /= 0 and result (exponent_width) = '1' then
+ round := true;
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+ if round then
+ fp_round(fract_in => fract,
+ expon_in => expon,
+ fract_out => fracttmp,
+ expon_out => exptmp);
+ fract := fracttmp;
+ expon := exptmp;
+ end if;
+ -- Put the number together and return
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ result (exponent_width-1 downto 0) := UNRESOLVED_float(expon);
+ result (-1 downto -fraction_width) := UNRESOLVED_float(fract);
+ end if;
+ end if;
+ return result;
+ end function to_float;
+
+ -- to_float (unsigned)
+ function to_float (
+ arg : UNRESOLVED_UNSIGNED;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ constant ARG_LEFT : INTEGER := arg'length-1;
+ alias XARG : UNRESOLVED_UNSIGNED(ARG_LEFT downto 0) is arg;
+ variable sarg : SIGNED (ARG_LEFT+1 downto 0); -- signed version of arg
+ begin
+ if arg'length < 1 then
+ return NAFP;
+ end if;
+ sarg (XARG'range) := SIGNED (XARG);
+ sarg (sarg'high) := '0';
+ result := to_float (arg => sarg,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ round_style => round_style);
+ return result;
+ end function to_float;
+
+ -- to_float (signed)
+ function to_float (
+ arg : UNRESOLVED_SIGNED;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ constant ARG_LEFT : INTEGER := arg'length-1;
+ alias XARG : UNRESOLVED_SIGNED(ARG_LEFT downto 0) is arg;
+ variable arg_int : UNSIGNED(XARG'range); -- Real version of argument
+ variable argb2 : UNSIGNED(XARG'high/2 downto 0); -- log2 of input
+ variable rexp : SIGNED (exponent_width - 1 downto 0);
+ variable exp : SIGNED (exponent_width - 1 downto 0);
+ -- signed version of exp.
+ variable expon : UNSIGNED (exponent_width - 1 downto 0);
+ -- Unsigned version of exp.
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable round : BOOLEAN;
+ variable fract : UNSIGNED (fraction_width-1 downto 0);
+ variable rfract : UNSIGNED (fraction_width-1 downto 0);
+ variable sign : STD_ULOGIC; -- sign bit
+ begin
+ if arg'length < 1 then
+ return NAFP;
+ end if;
+ if Is_X (XARG) then
+ result := (others => 'X');
+ elsif (XARG = 0) then
+ result := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else -- Normal number (can't be denormal)
+ sign := to_X01(XARG (XARG'high));
+ arg_int := UNSIGNED(abs (to_01(XARG)));
+ -- Compute Exponent
+ argb2 := to_unsigned(find_leftmost(arg_int, '1'), argb2'length); -- Log2
+ if argb2 > UNSIGNED(expon_base) then
+ result := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ result (exponent_width) := sign;
+ else
+ exp := SIGNED(resize(argb2, exp'length));
+ arg_int := shift_left (arg_int, arg_int'high-to_integer(exp));
+ if (arg_int'high > fraction_width) then
+ fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width));
+ round := check_round (
+ fract_in => fract (0),
+ sign => sign,
+ remainder => arg_int((arg_int'high-fraction_width-1)
+ downto 0),
+ round_style => round_style);
+ if round then
+ fp_round(fract_in => fract,
+ expon_in => exp,
+ fract_out => rfract,
+ expon_out => rexp);
+ else
+ rfract := fract;
+ rexp := exp;
+ end if;
+ else
+ rexp := exp;
+ rfract := (others => '0');
+ rfract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) :=
+ arg_int (arg_int'high-1 downto 0);
+ end if;
+ result (exponent_width) := sign;
+ expon := UNSIGNED (rexp-1);
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ result (exponent_width-1 downto 0) := UNRESOLVED_float(expon);
+ result (-1 downto -fraction_width) := UNRESOLVED_float(rfract);
+ end if;
+ end if;
+ return result;
+ end function to_float;
+
+ -- std_logic_vector to float
+ function to_float (
+ arg : STD_ULOGIC_VECTOR;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction
+ return UNRESOLVED_float
+ is
+ variable fpvar : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin
+ if arg'length < 1 then
+ return NAFP;
+ end if;
+ fpvar := UNRESOLVED_float(arg);
+ return fpvar;
+ end function to_float;
+
+ -- purpose: converts a ufixed to a floating point
+ function to_float (
+ arg : UNRESOLVED_ufixed; -- unsigned fixed point input
+ constant exponent_width : NATURAL := float_exponent_width; -- width of exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- width of fraction
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions
+ return UNRESOLVED_float
+ is
+ variable sarg : sfixed (arg'high+1 downto arg'low); -- Signed version of arg
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- function to_float
+ if (arg'length < 1) then
+ return NAFP;
+ end if;
+ sarg (arg'range) := sfixed (arg);
+ sarg (sarg'high) := '0';
+ result := to_float (arg => sarg,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ round_style => round_style,
+ denormalize => denormalize);
+ return result;
+ end function to_float;
+
+ function to_float (
+ arg : UNRESOLVED_sfixed; -- signed fixed point
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- rounding option
+ return UNRESOLVED_float
+ is
+ constant integer_width : INTEGER := arg'high;
+ constant in_fraction_width : INTEGER := arg'low;
+ variable xresult : sfixed (integer_width downto in_fraction_width);
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable arg_int : UNSIGNED(integer_width - in_fraction_width
+ downto 0); -- unsigned version of argument
+ variable argx : SIGNED (integer_width - in_fraction_width downto 0);
+ variable exp, exptmp : SIGNED (exponent_width + 1 downto 0);
+ variable expon : UNSIGNED (exponent_width - 1 downto 0);
+ -- Unsigned version of exp.
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable fract, fracttmp : UNSIGNED (fraction_width-1 downto 0) :=
+ (others => '0');
+ variable round : BOOLEAN := false;
+ begin
+ if (arg'length < 1) then
+ return NAFP;
+ end if;
+ xresult := to_01(arg, 'X');
+ argx := SIGNED(to_slv(xresult));
+ if (Is_X (arg)) then
+ result := (others => 'X');
+ elsif (argx = 0) then
+ result := (others => '0');
+ else
+ result := (others => '0'); -- zero out the result
+ if argx(argx'left) = '1' then -- toss the sign bit
+ result (exponent_width) := '1'; -- Negative number
+ arg_int := UNSIGNED(to_x01(not STD_LOGIC_VECTOR (argx))) + 1; -- Make it positive with two's complement
+ else
+ result (exponent_width) := '0';
+ arg_int := UNSIGNED(to_x01(STD_LOGIC_VECTOR (argx))); -- new line: direct conversion to unsigned
+ end if;
+ -- Compute Exponent
+ exp := to_signed(find_leftmost(arg_int, '1'), exp'length); -- Log2
+ if exp + in_fraction_width > expon_base then -- return infinity
+ result (-1 downto -fraction_width) := (others => '0');
+ result (exponent_width -1 downto 0) := (others => '1');
+ return result;
+ elsif (denormalize and
+ (exp + in_fraction_width <= -resize(expon_base, exp'length))) then
+ exp := -resize(expon_base, exp'length);
+ -- shift by a constant
+ arg_int := shift_left (arg_int,
+ (arg_int'high + to_integer(expon_base)
+ + in_fraction_width - 1));
+ if (arg_int'high > fraction_width) then
+ fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width));
+ round := check_round (
+ fract_in => arg_int(arg_int'high-fraction_width),
+ sign => result(result'high),
+ remainder => arg_int((arg_int'high-fraction_width-1)
+ downto 0),
+ round_style => round_style);
+ if (round) then
+ fp_round (fract_in => arg_int (arg_int'high-1 downto
+ (arg_int'high-fraction_width)),
+ expon_in => exp,
+ fract_out => fract,
+ expon_out => exptmp);
+ exp := exptmp;
+ end if;
+ else
+ fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) :=
+ arg_int (arg_int'high-1 downto 0);
+ end if;
+ else
+ arg_int := shift_left (arg_int, arg_int'high-to_integer(exp));
+ exp := exp + in_fraction_width;
+ if (arg_int'high > fraction_width) then
+ fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width));
+ round := check_round (
+ fract_in => fract(0),
+ sign => result(result'high),
+ remainder => arg_int((arg_int'high-fraction_width-1)
+ downto 0),
+ round_style => round_style);
+ if (round) then
+ fp_round (fract_in => fract,
+ expon_in => exp,
+ fract_out => fracttmp,
+ expon_out => exptmp);
+ fract := fracttmp;
+ exp := exptmp;
+ end if;
+ else
+ fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) :=
+ arg_int (arg_int'high-1 downto 0);
+ end if;
+ end if;
+ expon := UNSIGNED (resize(exp-1, exponent_width));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ result (exponent_width-1 downto 0) := UNRESOLVED_float(expon);
+ result (-1 downto -fraction_width) := UNRESOLVED_float(fract);
+ end if;
+ return result;
+ end function to_float;
+
+ -- size_res functions
+ -- Integer to float
+ function to_float (
+ arg : INTEGER;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style);
+ return result;
+ end if;
+ end function to_float;
+
+ -- real to float
+ function to_float (
+ arg : REAL;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function to_float;
+
+ -- unsigned to float
+ function to_float (
+ arg : UNRESOLVED_UNSIGNED;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style);
+ return result;
+ end if;
+ end function to_float;
+
+ -- signed to float
+ function to_float (
+ arg : UNRESOLVED_SIGNED;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style);
+ return result;
+ end if;
+ end function to_float;
+
+ -- std_ulogic_vector to float
+ function to_float (
+ arg : STD_ULOGIC_VECTOR;
+ size_res : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ return result;
+ end if;
+ end function to_float;
+
+ -- unsigned fixed point to float
+ function to_float (
+ arg : UNRESOLVED_ufixed; -- unsigned fixed point input
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function to_float;
+
+ -- signed fixed point to float
+ function to_float (
+ arg : UNRESOLVED_sfixed;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- rounding option
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function to_float;
+
+ -- to_integer (float)
+ function to_integer (
+ arg : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return INTEGER
+ is
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable frac : UNSIGNED (-arg'low downto 0); -- Fraction
+ variable fract : UNSIGNED (1-arg'low downto 0); -- Fraction
+ variable expon : SIGNED (arg'high-1 downto 0);
+ variable isign : STD_ULOGIC; -- internal version of sign
+ variable round : STD_ULOGIC; -- is rounding needed?
+ variable result : INTEGER;
+ variable base : INTEGER; -- Integer exponent
+ begin
+ validfp := Classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | nan | quiet_nan | pos_zero | neg_zero | pos_denormal | neg_denormal =>
+ result := 0; -- return 0
+ when pos_inf =>
+ result := INTEGER'high;
+ when neg_inf =>
+ result := INTEGER'low;
+ when others =>
+ break_number (
+ arg => arg,
+ fptyp => validfp,
+ denormalize => false,
+ fract => frac,
+ expon => expon);
+ fract (fract'high) := '0'; -- Add extra bit for 0.6 case
+ fract (fract'high-1 downto 0) := frac;
+ isign := to_x01 (arg (arg'high));
+ base := to_integer (expon) + 1;
+ if base < -1 then
+ result := 0;
+ elsif base >= frac'high then
+ result := to_integer (fract) * 2**(base - frac'high);
+ else -- We need to round
+ if base = -1 then -- trap for 0.6 case.
+ result := 0;
+ else
+ result := to_integer (fract (frac'high downto frac'high-base));
+ end if;
+ -- rounding routine
+ case round_style is
+ when round_nearest =>
+ if frac'high - base > 1 then
+ round := fract (frac'high - base - 1) and
+ (fract (frac'high - base)
+ or (or (fract (frac'high - base - 2 downto 0))));
+ else
+ round := fract (frac'high - base - 1) and
+ fract (frac'high - base);
+ end if;
+ when round_inf =>
+ round := fract(frac'high - base - 1) and not isign;
+ when round_neginf =>
+ round := fract(frac'high - base - 1) and isign;
+ when others =>
+ round := '0';
+ end case;
+ if round = '1' then
+ result := result + 1;
+ end if;
+ end if;
+ if isign = '1' then
+ result := - result;
+ end if;
+ end case classcase;
+ return result;
+ end function to_integer;
+
+ -- to_unsigned (float)
+ function to_unsigned (
+ arg : UNRESOLVED_float; -- floating point input
+ constant size : NATURAL; -- length of output
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNRESOLVED_UNSIGNED
+ is
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable frac : UNRESOLVED_UNSIGNED (size-1 downto 0); -- Fraction
+ variable sign : STD_ULOGIC; -- not used
+ begin
+ validfp := Classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | nan | quiet_nan =>
+ frac := (others => 'X');
+ when pos_zero | neg_inf | neg_zero | neg_normal | pos_denormal | neg_denormal =>
+ frac := (others => '0'); -- return 0
+ when pos_inf =>
+ frac := (others => '1');
+ when others =>
+ float_to_unsigned (
+ arg => arg,
+ frac => frac,
+ sign => sign,
+ denormalize => false,
+ bias => 0,
+ round_style => round_style);
+ end case classcase;
+ return (frac);
+ end function to_unsigned;
+
+ -- to_signed (float)
+ function to_signed (
+ arg : UNRESOLVED_float; -- floating point input
+ constant size : NATURAL; -- length of output
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNRESOLVED_SIGNED
+ is
+ variable sign : STD_ULOGIC; -- true if negative
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable frac : UNRESOLVED_UNSIGNED (size-1 downto 0); -- Fraction
+ variable result : UNRESOLVED_SIGNED (size-1 downto 0);
+ begin
+ validfp := Classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | nan | quiet_nan =>
+ result := (others => 'X');
+ when pos_zero | neg_zero | pos_denormal | neg_denormal =>
+ result := (others => '0'); -- return 0
+ when pos_inf =>
+ result := (others => '1');
+ result (result'high) := '0';
+ when neg_inf =>
+ result := (others => '0');
+ result (result'high) := '1';
+ when others =>
+ float_to_unsigned (
+ arg => arg,
+ sign => sign,
+ frac => frac,
+ denormalize => false,
+ bias => 0,
+ round_style => round_style);
+ result (size-1) := '0';
+ result (size-2 downto 0) := UNRESOLVED_SIGNED(frac (size-2 downto 0));
+ if sign = '1' then
+ -- Because the most negative signed number is 1 less than the most
+ -- positive signed number, we need this code.
+ if frac(frac'high) = '1' then -- return most negative number
+ result := (others => '0');
+ result (result'high) := '1';
+ else
+ result := -result;
+ end if;
+ else
+ if frac(frac'high) = '1' then -- return most positive number
+ result := (others => '1');
+ result (result'high) := '0';
+ end if;
+ end if;
+ end case classcase;
+ return result;
+ end function to_signed;
+
+ -- purpose: Converts a float to ufixed
+ function to_ufixed (
+ arg : UNRESOLVED_float; -- fp input
+ constant left_index : INTEGER; -- integer part
+ constant right_index : INTEGER; -- fraction part
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_ufixed
+ is
+ constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction
+ constant exponent_width : INTEGER := arg'high; -- length of FP output exponent
+ constant size : INTEGER := left_index - right_index + 4; -- unsigned size
+ variable expon_base : INTEGER; -- exponent offset
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable exp : INTEGER; -- Exponent
+ variable expon : UNSIGNED (exponent_width-1 downto 0); -- Vectorized exponent
+ -- Base to divide fraction by
+ variable frac : UNSIGNED (size-1 downto 0) := (others => '0'); -- Fraction
+ variable frac_shift : UNSIGNED (size-1 downto 0); -- Fraction shifted
+ variable shift : INTEGER;
+ variable result_big : UNRESOLVED_ufixed (left_index downto right_index-3);
+ variable result : UNRESOLVED_ufixed (left_index downto right_index); -- result
+ begin -- function to_ufixed
+ validfp := Classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | nan | quiet_nan =>
+ frac := (others => 'X');
+ when pos_zero | neg_inf | neg_zero | neg_normal | neg_denormal =>
+ frac := (others => '0'); -- return 0
+ when pos_inf =>
+ frac := (others => '1'); -- always saturate
+ when others =>
+ expon_base := 2**(exponent_width-1) -1; -- exponent offset
+ -- Figure out the fraction
+ if (validfp = pos_denormal) and denormalize then
+ exp := -expon_base +1;
+ frac (frac'high) := '0'; -- Remove the "1.0".
+ else
+ -- exponent /= '0', normal floating point
+ expon := UNSIGNED(arg (exponent_width-1 downto 0));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ exp := to_integer (SIGNED(expon)) +1;
+ frac (frac'high) := '1'; -- Add the "1.0".
+ end if;
+ shift := (frac'high - 3 + right_index) - exp;
+ if fraction_width > frac'high then -- Can only use size-2 bits
+ frac (frac'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto
+ -frac'high)));
+ else -- can use all bits
+ frac (frac'high-1 downto frac'high-fraction_width) :=
+ UNSIGNED (to_slv (arg(-1 downto -fraction_width)));
+ end if;
+ frac_shift := frac srl shift;
+ if shift < 0 then -- Overflow
+ frac := (others => '1');
+ else
+ frac := frac_shift;
+ end if;
+ end case classcase;
+ result_big := to_ufixed (
+ arg => STD_ULOGIC_VECTOR(frac),
+ left_index => left_index,
+ right_index => (right_index-3));
+ result := resize (arg => result_big,
+ left_index => left_index,
+ right_index => right_index,
+ round_style => round_style,
+ overflow_style => overflow_style);
+ return result;
+ end function to_ufixed;
+
+ -- purpose: Converts a float to sfixed
+ function to_sfixed (
+ arg : UNRESOLVED_float; -- fp input
+ constant left_index : INTEGER; -- integer part
+ constant right_index : INTEGER; -- fraction part
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_sfixed
+ is
+ constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction
+ constant exponent_width : INTEGER := arg'high; -- length of FP output exponent
+ constant size : INTEGER := left_index - right_index + 4; -- unsigned size
+ variable expon_base : INTEGER; -- exponent offset
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable exp : INTEGER; -- Exponent
+ variable sign : BOOLEAN; -- true if negative
+ variable expon : UNSIGNED (exponent_width-1 downto 0); -- Vectorized exponent
+ -- Base to divide fraction by
+ variable frac : UNSIGNED (size-2 downto 0) := (others => '0'); -- Fraction
+ variable frac_shift : UNSIGNED (size-2 downto 0); -- Fraction shifted
+ variable shift : INTEGER;
+ variable rsigned : SIGNED (size-1 downto 0); -- signed version of result
+ variable result_big : UNRESOLVED_sfixed (left_index downto right_index-3);
+ variable result : UNRESOLVED_sfixed (left_index downto right_index)
+ := (others => '0'); -- result
+ begin -- function to_sfixed
+ validfp := Classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | nan | quiet_nan =>
+ result := (others => 'X');
+ when pos_zero | neg_zero =>
+ result := (others => '0'); -- return 0
+ when neg_inf =>
+ result (left_index) := '1'; -- return smallest negative number
+ when pos_inf =>
+ result := (others => '1'); -- return largest number
+ result (left_index) := '0';
+ when others =>
+ expon_base := 2**(exponent_width-1) -1; -- exponent offset
+ if arg(exponent_width) = '0' then
+ sign := false;
+ else
+ sign := true;
+ end if;
+ -- Figure out the fraction
+ if (validfp = pos_denormal or validfp = neg_denormal)
+ and denormalize then
+ exp := -expon_base +1;
+ frac (frac'high) := '0'; -- Add the "1.0".
+ else
+ -- exponent /= '0', normal floating point
+ expon := UNSIGNED(arg (exponent_width-1 downto 0));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ exp := to_integer (SIGNED(expon)) +1;
+ frac (frac'high) := '1'; -- Add the "1.0".
+ end if;
+ shift := (frac'high - 3 + right_index) - exp;
+ if fraction_width > frac'high then -- Can only use size-2 bits
+ frac (frac'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto
+ -frac'high)));
+ else -- can use all bits
+ frac (frac'high-1 downto frac'high-fraction_width) :=
+ UNSIGNED (to_slv (arg(-1 downto -fraction_width)));
+ end if;
+ frac_shift := frac srl shift;
+ if shift < 0 then -- Overflow
+ frac := (others => '1');
+ else
+ frac := frac_shift;
+ end if;
+ if not sign then
+ rsigned := SIGNED("0" & frac);
+ else
+ rsigned := -(SIGNED("0" & frac));
+ end if;
+ result_big := to_sfixed (
+ arg => STD_LOGIC_VECTOR(rsigned),
+ left_index => left_index,
+ right_index => (right_index-3));
+ result := resize (arg => result_big,
+ left_index => left_index,
+ right_index => right_index,
+ round_style => round_style,
+ overflow_style => overflow_style);
+ end case classcase;
+ return result;
+ end function to_sfixed;
+
+ -- size_res versions
+ -- float to unsigned
+ function to_unsigned (
+ arg : UNRESOLVED_float; -- floating point input
+ size_res : UNRESOLVED_UNSIGNED;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNRESOLVED_UNSIGNED
+ is
+ variable result : UNRESOLVED_UNSIGNED (size_res'range);
+ begin
+ if (size_res'length = 0) then
+ return result;
+ else
+ result := to_unsigned (
+ arg => arg,
+ size => size_res'length,
+ round_style => round_style,
+ check_error => check_error);
+ return result;
+ end if;
+ end function to_unsigned;
+
+ -- float to signed
+ function to_signed (
+ arg : UNRESOLVED_float; -- floating point input
+ size_res : UNRESOLVED_SIGNED;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNRESOLVED_SIGNED
+ is
+ variable result : UNRESOLVED_SIGNED (size_res'range);
+ begin
+ if (size_res'length = 0) then
+ return result;
+ else
+ result := to_signed (
+ arg => arg,
+ size => size_res'length,
+ round_style => round_style,
+ check_error => check_error);
+ return result;
+ end if;
+ end function to_signed;
+
+ -- purpose: Converts a float to unsigned fixed point
+ function to_ufixed (
+ arg : UNRESOLVED_float; -- fp input
+ size_res : UNRESOLVED_ufixed;
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_ufixed
+ is
+ variable result : UNRESOLVED_ufixed (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_ufixed (
+ arg => arg,
+ left_index => size_res'high,
+ right_index => size_res'low,
+ overflow_style => overflow_style,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function to_ufixed;
+
+ -- float to signed fixed point
+ function to_sfixed (
+ arg : UNRESOLVED_float; -- fp input
+ size_res : UNRESOLVED_sfixed;
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_sfixed
+ is
+ variable result : UNRESOLVED_sfixed (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_sfixed (
+ arg => arg,
+ left_index => size_res'high,
+ right_index => size_res'low,
+ overflow_style => overflow_style,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function to_sfixed;
+
+ -- to_real (float)
+ -- typically not Synthesizable unless the input is a constant.
+ function to_real (
+ arg : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return REAL
+ is
+ constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction
+ constant exponent_width : INTEGER := arg'high; -- length of FP output exponent
+ variable sign : REAL; -- Sign, + or - 1
+ variable exp : INTEGER; -- Exponent
+ variable expon_base : INTEGER; -- exponent offset
+ variable frac : REAL := 0.0; -- Fraction
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable expon : UNSIGNED (exponent_width - 1 downto 0)
+ := (others => '1'); -- Vectorized exponent
+ begin
+ validfp := Classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | pos_zero | neg_zero | nan | quiet_nan =>
+ return 0.0;
+ when neg_inf =>
+ return REAL'low; -- Negative infinity.
+ when pos_inf =>
+ return REAL'high; -- Positive infinity
+ when others =>
+ expon_base := 2**(exponent_width-1) -1;
+ if to_X01(arg(exponent_width)) = '0' then
+ sign := 1.0;
+ else
+ sign := -1.0;
+ end if;
+ -- Figure out the fraction
+ for i in 0 to fraction_width-1 loop
+ if to_X01(arg (-1 - i)) = '1' then
+ frac := frac + (2.0 **(-1 - i));
+ end if;
+ end loop; -- i
+ if validfp = pos_normal or validfp = neg_normal or not denormalize then
+ -- exponent /= '0', normal floating point
+ expon := UNSIGNED(arg (exponent_width-1 downto 0));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ exp := to_integer (SIGNED(expon)) +1;
+ sign := sign * (2.0 ** exp) * (1.0 + frac);
+ else -- exponent = '0', IEEE extended floating point
+ exp := 1 - expon_base;
+ sign := sign * (2.0 ** exp) * frac;
+ end if;
+ return sign;
+ end case classcase;
+ end function to_real;
+
+ -- For Verilog compatability
+ function realtobits (arg : REAL) return STD_ULOGIC_VECTOR is
+ variable result : float64; -- 64 bit floating point
+ begin
+ result := to_float (arg => arg,
+ exponent_width => float64'high,
+ fraction_width => -float64'low);
+ return to_sulv (result);
+ end function realtobits;
+
+ function bitstoreal (arg : STD_ULOGIC_VECTOR) return REAL is
+ variable arg64 : float64; -- arg converted to float
+ begin
+ arg64 := to_float (arg => arg,
+ exponent_width => float64'high,
+ fraction_width => -float64'low);
+ return to_real (arg64);
+ end function bitstoreal;
+
+ -- purpose: Removes meta-logical values from FP string
+ function to_01 (
+ arg : UNRESOLVED_float; -- floating point input
+ XMAP : STD_LOGIC := '0')
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (arg'range);
+ begin -- function to_01
+ if (arg'length < 1) then
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & "TO_01: null detected, returning NULL"
+ severity warning;
+ return NAFP;
+ end if;
+ result := UNRESOLVED_float (STD_LOGIC_VECTOR(to_01(UNSIGNED(to_slv(arg)), XMAP)));
+ return result;
+ end function to_01;
+
+ function Is_X
+ (arg : UNRESOLVED_float)
+ return BOOLEAN is
+ begin
+ return Is_X (to_slv(arg));
+ end function Is_X;
+
+ function to_X01 (arg : UNRESOLVED_float) return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (arg'range);
+ begin
+ if (arg'length < 1) then
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & "TO_X01: null detected, returning NULL"
+ severity warning;
+ return NAFP;
+ else
+ result := UNRESOLVED_float (to_X01(to_slv(arg)));
+ return result;
+ end if;
+ end function to_X01;
+
+ function to_X01Z (arg : UNRESOLVED_float) return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (arg'range);
+ begin
+ if (arg'length < 1) then
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & "TO_X01Z: null detected, returning NULL"
+ severity warning;
+ return NAFP;
+ else
+ result := UNRESOLVED_float (to_X01Z(to_slv(arg)));
+ return result;
+ end if;
+ end function to_X01Z;
+
+ function to_UX01 (arg : UNRESOLVED_float) return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (arg'range);
+ begin
+ if (arg'length < 1) then
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & "TO_UX01: null detected, returning NULL"
+ severity warning;
+ return NAFP;
+ else
+ result := UNRESOLVED_float (to_UX01(to_slv(arg)));
+ return result;
+ end if;
+ end function to_UX01;
+
+ -- These allows the base math functions to use the default values
+ -- of their parameters. Thus they do full IEEE floating point.
+ function "+" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return add (l, r);
+ end function "+";
+
+ function "-" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return subtract (l, r);
+ end function "-";
+
+ function "*" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return multiply (l, r);
+ end function "*";
+
+ function "/" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return divide (l, r);
+ end function "/";
+
+ function "rem" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return remainder (l, r);
+ end function "rem";
+
+ function "mod" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return modulo (l, r);
+ end function "mod";
+
+ -- overloaded versions
+ function "+" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return add (l, r_float);
+ end function "+";
+
+ function "+" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return add (l_float, r);
+ end function "+";
+
+ function "+" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return add (l, r_float);
+ end function "+";
+
+ function "+" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return add (l_float, r);
+ end function "+";
+
+ function "-" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return subtract (l, r_float);
+ end function "-";
+
+ function "-" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return subtract (l_float, r);
+ end function "-";
+
+ function "-" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return subtract (l, r_float);
+ end function "-";
+
+ function "-" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return subtract (l_float, r);
+ end function "-";
+
+ function "*" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return multiply (l, r_float);
+ end function "*";
+
+ function "*" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return multiply (l_float, r);
+ end function "*";
+
+ function "*" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return multiply (l, r_float);
+ end function "*";
+
+ function "*" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return multiply (l_float, r);
+ end function "*";
+
+ function "/" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return divide (l, r_float);
+ end function "/";
+
+ function "/" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return divide (l_float, r);
+ end function "/";
+
+ function "/" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return divide (l, r_float);
+ end function "/";
+
+ function "/" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return divide (l_float, r);
+ end function "/";
+
+ function "rem" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return remainder (l, r_float);
+ end function "rem";
+
+ function "rem" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return remainder (l_float, r);
+ end function "rem";
+
+ function "rem" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return remainder (l, r_float);
+ end function "rem";
+
+ function "rem" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return remainder (l_float, r);
+ end function "rem";
+
+ function "mod" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return modulo (l, r_float);
+ end function "mod";
+
+ function "mod" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return modulo (l_float, r);
+ end function "mod";
+
+ function "mod" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return modulo (l, r_float);
+ end function "mod";
+
+ function "mod" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return modulo (l_float, r);
+ end function "mod";
+
+ function "=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return eq (l, r_float);
+ end function "=";
+
+ function "/=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return ne (l, r_float);
+ end function "/=";
+
+ function ">=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return ge (l, r_float);
+ end function ">=";
+
+ function "<=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return le (l, r_float);
+ end function "<=";
+
+ function ">" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return gt (l, r_float);
+ end function ">";
+
+ function "<" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return lt (l, r_float);
+ end function "<";
+
+ function "=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return eq (l_float, r);
+ end function "=";
+
+ function "/=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return ne (l_float, r);
+ end function "/=";
+
+ function ">=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return ge (l_float, r);
+ end function ">=";
+
+ function "<=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return le (l_float, r);
+ end function "<=";
+
+ function ">" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return gt (l_float, r);
+ end function ">";
+
+ function "<" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return lt (l_float, r);
+ end function "<";
+
+ function "=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return eq (l, r_float);
+ end function "=";
+
+ function "/=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return ne (l, r_float);
+ end function "/=";
+
+ function ">=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return ge (l, r_float);
+ end function ">=";
+
+ function "<=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return le (l, r_float);
+ end function "<=";
+
+ function ">" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return gt (l, r_float);
+ end function ">";
+
+ function "<" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return lt (l, r_float);
+ end function "<";
+
+ function "=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return eq (l_float, r);
+ end function "=";
+
+ function "/=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return ne (l_float, r);
+ end function "/=";
+
+ function ">=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return ge (l_float, r);
+ end function ">=";
+
+ function "<=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return le (l_float, r);
+ end function "<=";
+
+ function ">" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return gt (l_float, r);
+ end function ">";
+
+ function "<" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return lt (l_float, r);
+ end function "<";
+
+ -- ?= overloads
+ function "?=" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?= r_float;
+ end function "?=";
+
+ function "?/=" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?/= r_float;
+ end function "?/=";
+
+ function "?>" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?> r_float;
+ end function "?>";
+
+ function "?>=" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?>= r_float;
+ end function "?>=";
+
+ function "?<" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?< r_float;
+ end function "?<";
+
+ function "?<=" (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?<= r_float;
+ end function "?<=";
+
+ -- real and float
+ function "?=" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?= r;
+ end function "?=";
+
+ function "?/=" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?/= r;
+ end function "?/=";
+
+ function "?>" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?> r;
+ end function "?>";
+
+ function "?>=" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?>= r;
+ end function "?>=";
+
+ function "?<" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?< r;
+ end function "?<";
+
+ function "?<=" (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?<= r;
+ end function "?<=";
+
+ -- ?= overloads
+ function "?=" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?= r_float;
+ end function "?=";
+
+ function "?/=" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?/= r_float;
+ end function "?/=";
+
+ function "?>" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?> r_float;
+ end function "?>";
+
+ function "?>=" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?>= r_float;
+ end function "?>=";
+
+ function "?<" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?< r_float;
+ end function "?<";
+
+ function "?<=" (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return l ?<= r_float;
+ end function "?<=";
+
+ -- integer and float
+ function "?=" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?= r;
+ end function "?=";
+
+ function "?/=" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?/= r;
+ end function "?/=";
+
+ function "?>" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?> r;
+ end function "?>";
+
+ function "?>=" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?>= r;
+ end function "?>=";
+
+ function "?<" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?< r;
+ end function "?<";
+
+ function "?<=" (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return l_float ?<= r;
+ end function "?<=";
+
+ -- minimum and maximum overloads
+ function minimum (l : UNRESOLVED_float; r : REAL)
+ return UNRESOLVED_float
+ is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return minimum (l, r_float);
+ end function minimum;
+
+ function maximum (l : UNRESOLVED_float; r : REAL)
+ return UNRESOLVED_float
+ is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return maximum (l, r_float);
+ end function maximum;
+
+ function minimum (l : REAL; r : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return minimum (l_float, r);
+ end function minimum;
+
+ function maximum (l : REAL; r : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return maximum (l_float, r);
+ end function maximum;
+
+ function minimum (l : UNRESOLVED_float; r : INTEGER)
+ return UNRESOLVED_float
+ is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return minimum (l, r_float);
+ end function minimum;
+
+ function maximum (l : UNRESOLVED_float; r : INTEGER)
+ return UNRESOLVED_float
+ is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return maximum (l, r_float);
+ end function maximum;
+
+ function minimum (l : INTEGER; r : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return minimum (l_float, r);
+ end function minimum;
+
+ function maximum (l : INTEGER; r : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return maximum (l_float, r);
+ end function maximum;
+
+ ----------------------------------------------------------------------------
+ -- logical functions
+ ----------------------------------------------------------------------------
+ function "not" (L : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ RESULT := not to_sulv(L);
+ return to_float (RESULT, L'high, -L'low);
+ end function "not";
+
+ function "and" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) and to_sulv(R);
+ else
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & """and"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "and";
+
+ function "or" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) or to_sulv(R);
+ else
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & """or"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "or";
+
+ function "nand" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) nand to_sulv(R);
+ else
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & """nand"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "nand";
+
+ function "nor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) nor to_sulv(R);
+ else
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & """nor"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "nor";
+
+ function "xor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) xor to_sulv(R);
+ else
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & """xor"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "xor";
+
+ function "xnor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) xnor to_sulv(R);
+ else
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & """xnor"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "xnor";
+
+ -- Vector and std_ulogic functions, same as functions in numeric_std
+ function "and" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ result := UNRESOLVED_float (L and to_sulv(R));
+ return result;
+ end function "and";
+
+ function "and" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ result := UNRESOLVED_float (to_sulv(L) and R);
+ return result;
+ end function "and";
+
+ function "or" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ result := UNRESOLVED_float (L or to_sulv(R));
+ return result;
+ end function "or";
+
+ function "or" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ result := UNRESOLVED_float (to_sulv(L) or R);
+ return result;
+ end function "or";
+
+ function "nand" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ result := UNRESOLVED_float (L nand to_sulv(R));
+ return result;
+ end function "nand";
+
+ function "nand" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ result := UNRESOLVED_float (to_sulv(L) nand R);
+ return result;
+ end function "nand";
+
+ function "nor" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ result := UNRESOLVED_float (L nor to_sulv(R));
+ return result;
+ end function "nor";
+
+ function "nor" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ result := UNRESOLVED_float (to_sulv(L) nor R);
+ return result;
+ end function "nor";
+
+ function "xor" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ result := UNRESOLVED_float (L xor to_sulv(R));
+ return result;
+ end function "xor";
+
+ function "xor" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ result := UNRESOLVED_float (to_sulv(L) xor R);
+ return result;
+ end function "xor";
+
+ function "xnor" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ result := UNRESOLVED_float (L xnor to_sulv(R));
+ return result;
+ end function "xnor";
+
+ function "xnor" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ result := UNRESOLVED_float (to_sulv(L) xnor R);
+ return result;
+ end function "xnor";
+
+ -- Reduction operators, same as numeric_std functions
+
+ function "and" (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return and to_sulv(l);
+ end function "and";
+
+ function "nand" (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return nand to_sulv(l);
+ end function "nand";
+
+ function "or" (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return or to_sulv(l);
+ end function "or";
+
+ function "nor" (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return nor to_sulv(l);
+ end function "nor";
+
+ function "xor" (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return xor to_sulv(l);
+ end function "xor";
+
+ function "xnor" (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return xnor to_sulv(l);
+ end function "xnor";
+
+ -----------------------------------------------------------------------------
+ -- Recommended Functions from the IEEE 754 Appendix
+ -----------------------------------------------------------------------------
+ -- returns x with the sign of y.
+ function Copysign (
+ x, y : UNRESOLVED_float) -- floating point input
+ return UNRESOLVED_float is
+ begin
+ return y(y'high) & x (x'high-1 downto x'low);
+ end function Copysign;
+
+ -- Returns y * 2**n for integral values of N without computing 2**n
+ function Scalb (
+ y : UNRESOLVED_float; -- floating point input
+ N : INTEGER; -- exponent to add
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := -mine(y'low, y'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := y'high; -- length of FP output exponent
+ variable arg, result : UNRESOLVED_float (exponent_width downto -fraction_width); -- internal argument
+ variable expon : SIGNED (exponent_width-1 downto 0); -- Vectorized exp
+ variable exp : SIGNED (exponent_width downto 0);
+ variable ufract : UNSIGNED (fraction_width downto 0);
+ variable fptype : valid_fpstate;
+ begin
+ -- This can be done by simply adding N to the exponent.
+ arg := to_01 (y, 'X');
+ fptype := Classfp(arg, check_error);
+ classcase : case fptype is
+ when isx =>
+ result := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ result := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when others =>
+ break_number (
+ arg => arg,
+ fptyp => fptype,
+ denormalize => denormalize,
+ fract => ufract,
+ expon => expon);
+ exp := resize (expon, exp'length) + N;
+ result := normalize (
+ fract => ufract,
+ expon => exp,
+ sign => to_x01 (arg (arg'high)),
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => 0);
+ end case classcase;
+ return result;
+ end function Scalb;
+
+ -- Returns y * 2**n for integral values of N without computing 2**n
+ function Scalb (
+ y : UNRESOLVED_float; -- floating point input
+ N : UNRESOLVED_SIGNED; -- exponent to add
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float
+ is
+ variable n_int : INTEGER;
+ begin
+ n_int := to_integer(N);
+ return Scalb (y => y,
+ N => n_int,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize => denormalize);
+ end function Scalb;
+
+ -- returns the unbiased exponent of x
+ function Logb (
+ x : UNRESOLVED_float) -- floating point input
+ return INTEGER
+ is
+ constant fraction_width : NATURAL := -mine (x'low, x'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := x'high; -- length of FP output exponent
+ variable result : INTEGER; -- result
+ variable arg : UNRESOLVED_float (exponent_width downto -fraction_width); -- internal argument
+ variable expon : SIGNED (exponent_width - 1 downto 0);
+ variable fract : UNSIGNED (fraction_width downto 0);
+ constant expon_base : INTEGER := 2**(exponent_width-1) -1; -- exponent
+ -- offset +1
+ variable fptype : valid_fpstate;
+ begin
+ -- Just return the exponent.
+ arg := to_01 (x, 'X');
+ fptype := Classfp(arg);
+ classcase : case fptype is
+ when isx | nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ result := 0;
+ when pos_denormal | neg_denormal =>
+ fract (fraction_width) := '0';
+ fract (fraction_width-1 downto 0) :=
+ UNSIGNED (to_slv(arg(-1 downto -fraction_width)));
+ result := find_leftmost (fract, '1') -- Find the first "1"
+ - fraction_width; -- subtract the length we want
+ result := -expon_base + 1 + result;
+ when others =>
+ expon := SIGNED(arg (exponent_width - 1 downto 0));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ expon := expon + 1;
+ result := to_integer (expon);
+ end case classcase;
+ return result;
+ end function Logb;
+
+ -- returns the unbiased exponent of x
+ function Logb (
+ x : UNRESOLVED_float) -- floating point input
+ return UNRESOLVED_SIGNED
+ is
+ constant exponent_width : NATURAL := x'high; -- length of FP output exponent
+ variable result : SIGNED (exponent_width - 1 downto 0); -- result
+ begin
+ -- Just return the exponent.
+ result := to_signed (Logb (x), exponent_width);
+ return result;
+ end function Logb;
+
+ -- returns the next representable neighbor of x in the direction toward y
+ function Nextafter (
+ x, y : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_float
+ is
+ constant fraction_width : NATURAL := -mine(x'low, x'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := x'high; -- length of FP output exponent
+ function "=" (
+ l, r : UNRESOLVED_float) -- inputs
+ return BOOLEAN is
+ begin -- function "="
+ return eq (l => l,
+ r => r,
+ check_error => false);
+ end function "=";
+ function ">" (
+ l, r : UNRESOLVED_float) -- inputs
+ return BOOLEAN is
+ begin -- function ">"
+ return gt (l => l,
+ r => r,
+ check_error => false);
+ end function ">";
+ variable fract : UNSIGNED (fraction_width-1 downto 0);
+ variable expon : UNSIGNED (exponent_width-1 downto 0);
+ variable sign : STD_ULOGIC;
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable validfpx, validfpy : valid_fpstate; -- Valid FP state
+ begin -- fp_Nextafter
+ -- If Y > X, add one to the fraction, otherwise subtract.
+ validfpx := Classfp (x, check_error);
+ validfpy := Classfp (y, check_error);
+ if validfpx = isx or validfpy = isx then
+ result := (others => 'X');
+ return result;
+ elsif (validfpx = nan or validfpy = nan) then
+ return nanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (validfpx = quiet_nan or validfpy = quiet_nan) then
+ return qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif x = y then -- Return X
+ return x;
+ else
+ fract := UNSIGNED (to_slv (x (-1 downto -fraction_width))); -- Fraction
+ expon := UNSIGNED (x (exponent_width - 1 downto 0)); -- exponent
+ sign := x(exponent_width); -- sign bit
+ if (y > x) then
+ -- Increase the number given
+ if validfpx = neg_inf then
+ -- return most negative number
+ expon := (others => '1');
+ expon (0) := '0';
+ fract := (others => '1');
+ elsif validfpx = pos_zero or validfpx = neg_zero then
+ -- return smallest denormal number
+ sign := '0';
+ expon := (others => '0');
+ fract := (others => '0');
+ fract(0) := '1';
+ elsif validfpx = pos_normal then
+ if and (fract) = '1' then -- fraction is all "1".
+ if and (expon (exponent_width-1 downto 1)) = '1'
+ and expon (0) = '0' then
+ -- Exponent is one away from infinity.
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & "FP_NEXTAFTER: NextAfter overflow"
+ severity warning;
+ return pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ expon := expon + 1;
+ fract := (others => '0');
+ end if;
+ else
+ fract := fract + 1;
+ end if;
+ elsif validfpx = pos_denormal then
+ if and (fract) = '1' then -- fraction is all "1".
+ -- return smallest possible normal number
+ expon := (others => '0');
+ expon(0) := '1';
+ fract := (others => '0');
+ else
+ fract := fract + 1;
+ end if;
+ elsif validfpx = neg_normal then
+ if or (fract) = '0' then -- fraction is all "0".
+ if or (expon (exponent_width-1 downto 1)) = '0' and
+ expon (0) = '1' then -- Smallest exponent
+ -- return the largest negative denormal number
+ expon := (others => '0');
+ fract := (others => '1');
+ else
+ expon := expon - 1;
+ fract := (others => '1');
+ end if;
+ else
+ fract := fract - 1;
+ end if;
+ elsif validfpx = neg_denormal then
+ if or (fract(fract'high downto 1)) = '0'
+ and fract (0) = '1' then -- Smallest possible fraction
+ return zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ fract := fract - 1;
+ end if;
+ end if;
+ else
+ -- Decrease the number
+ if validfpx = pos_inf then
+ -- return most positive number
+ expon := (others => '1');
+ expon (0) := '0';
+ fract := (others => '1');
+ elsif validfpx = pos_zero
+ or Classfp (x) = neg_zero then
+ -- return smallest negative denormal number
+ sign := '1';
+ expon := (others => '0');
+ fract := (others => '0');
+ fract(0) := '1';
+ elsif validfpx = neg_normal then
+ if and (fract) = '1' then -- fraction is all "1".
+ if and (expon (exponent_width-1 downto 1)) = '1'
+ and expon (0) = '0' then
+ -- Exponent is one away from infinity.
+ assert no_warning
+ report float_generic_pkg'instance_name
+ & "FP_NEXTAFTER: NextAfter overflow"
+ severity warning;
+ return neg_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ expon := expon + 1; -- Fraction overflow
+ fract := (others => '0');
+ end if;
+ else
+ fract := fract + 1;
+ end if;
+ elsif validfpx = neg_denormal then
+ if and (fract) = '1' then -- fraction is all "1".
+ -- return smallest possible normal number
+ expon := (others => '0');
+ expon(0) := '1';
+ fract := (others => '0');
+ else
+ fract := fract + 1;
+ end if;
+ elsif validfpx = pos_normal then
+ if or (fract) = '0' then -- fraction is all "0".
+ if or (expon (exponent_width-1 downto 1)) = '0' and
+ expon (0) = '1' then -- Smallest exponent
+ -- return the largest positive denormal number
+ expon := (others => '0');
+ fract := (others => '1');
+ else
+ expon := expon - 1;
+ fract := (others => '1');
+ end if;
+ else
+ fract := fract - 1;
+ end if;
+ elsif validfpx = pos_denormal then
+ if or (fract(fract'high downto 1)) = '0'
+ and fract (0) = '1' then -- Smallest possible fraction
+ return zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ fract := fract - 1;
+ end if;
+ end if;
+ end if;
+ result (-1 downto -fraction_width) := UNRESOLVED_float(fract);
+ result (exponent_width -1 downto 0) := UNRESOLVED_float(expon);
+ result (exponent_width) := sign;
+ return result;
+ end if;
+ end function Nextafter;
+
+ -- Returns True if X is unordered with Y.
+ function Unordered (
+ x, y : UNRESOLVED_float) -- floating point input
+ return BOOLEAN
+ is
+ variable lfptype, rfptype : valid_fpstate;
+ begin
+ lfptype := Classfp (x);
+ rfptype := Classfp (y);
+ if (lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan or
+ lfptype = isx or rfptype = isx) then
+ return true;
+ else
+ return false;
+ end if;
+ end function Unordered;
+
+ function Finite (
+ x : UNRESOLVED_float)
+ return BOOLEAN
+ is
+ variable fp_state : valid_fpstate; -- fp state
+ begin
+ fp_state := Classfp (x);
+ if (fp_state = pos_inf) or (fp_state = neg_inf) then
+ return true;
+ else
+ return false;
+ end if;
+ end function Finite;
+
+ function Isnan (
+ x : UNRESOLVED_float)
+ return BOOLEAN
+ is
+ variable fp_state : valid_fpstate; -- fp state
+ begin
+ fp_state := Classfp (x);
+ if (fp_state = nan) or (fp_state = quiet_nan) then
+ return true;
+ else
+ return false;
+ end if;
+ end function Isnan;
+
+ -- Function to return constants.
+ function zerofp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float
+ is
+ constant result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ return result;
+ end function zerofp;
+
+ function nanfp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ result (exponent_width-1 downto 0) := (others => '1');
+ -- Exponent all "1"
+ result (-1) := '1'; -- MSB of Fraction "1"
+ -- Note: From W. Khan "IEEE Standard 754 for Binary Floating Point"
+ -- The difference between a signaling NAN and a quiet NAN is that
+ -- the MSB of the Fraction is a "1" in a Signaling NAN, and is a
+ -- "0" in a quiet NAN.
+ return result;
+ end function nanfp;
+
+ function qnanfp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ result (exponent_width-1 downto 0) := (others => '1');
+ -- Exponent all "1"
+ result (-fraction_width) := '1'; -- LSB of Fraction "1"
+ -- (Could have been any bit)
+ return result;
+ end function qnanfp;
+
+ function pos_inffp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ result (exponent_width-1 downto 0) := (others => '1'); -- Exponent all "1"
+ return result;
+ end function pos_inffp;
+
+ function neg_inffp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ result (exponent_width downto 0) := (others => '1'); -- top bits all "1"
+ return result;
+ end function neg_inffp;
+
+ function neg_zerofp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ result (exponent_width) := '1';
+ return result;
+ end function neg_zerofp;
+
+ -- size_res versions
+ function zerofp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return zerofp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function zerofp;
+
+ function nanfp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return nanfp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function nanfp;
+
+ function qnanfp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return qnanfp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function qnanfp;
+
+ function pos_inffp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return pos_inffp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function pos_inffp;
+
+ function neg_inffp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return neg_inffp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function neg_inffp;
+
+ function neg_zerofp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return neg_zerofp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function neg_zerofp;
+
+ -- Textio functions
+ -- purpose: writes float into a line (NOTE changed basetype)
+ type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', error);
+ type char_indexed_by_MVL9 is array (STD_ULOGIC) of CHARACTER;
+ type MVL9_indexed_by_char is array (CHARACTER) of STD_ULOGIC;
+ type MVL9plus_indexed_by_char is array (CHARACTER) of MVL9plus;
+
+ constant NBSP : CHARACTER := CHARACTER'val(160); -- space character
+ constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-";
+ constant char_to_MVL9 : MVL9_indexed_by_char :=
+ ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
+ 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U');
+ constant char_to_MVL9plus : MVL9plus_indexed_by_char :=
+ ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
+ 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => error);
+
+ -- purpose: Skips white space
+ procedure skip_whitespace (
+ L : inout LINE) is
+ variable c : CHARACTER;
+ variable left : positive;
+ begin
+ while L /= null and L.all'length /= 0 loop
+ left := L.all'left;
+ c := L.all(left);
+ if (c = ' ' or c = NBSP or c = HT) then
+ read (L, c);
+ else
+ exit;
+ end if;
+ end loop;
+ end procedure skip_whitespace;
+
+ -- purpose: Checks the punctuation in a line
+ procedure check_punctuation (
+ arg : in STRING;
+ colon : out BOOLEAN; -- There was a colon in the line
+ dot : out BOOLEAN; -- There was a dot in the line
+ good : out BOOLEAN; -- True if enough characters found
+ chars : in INTEGER) is
+ -- Examples. Legal inputs are "0000000", "0000.000", "0:000:000"
+ alias xarg : STRING (1 to arg'length) is arg; -- make it downto range
+ variable icolon, idot : BOOLEAN; -- internal
+ variable j : INTEGER := 0; -- charters read
+ begin
+ good := false;
+ icolon := false;
+ idot := false;
+ for i in 1 to arg'length loop
+ if xarg(i) = ' ' or xarg(i) = NBSP or xarg(i) = HT or j = chars then
+ exit;
+ elsif xarg(i) = ':' then
+ icolon := true;
+ elsif xarg(i) = '.' then
+ idot := true;
+ elsif xarg (i) /= '_' then
+ j := j + 1;
+ end if;
+ end loop;
+ if j = chars then
+ good := true; -- There are enough charactes to read
+ end if;
+ colon := icolon;
+ if idot and icolon then
+ dot := false;
+ else
+ dot := idot;
+ end if;
+ end procedure check_punctuation;
+
+ -- purpose: Searches a line for a ":" and replaces it with a ".".
+ procedure fix_colon (
+ arg : inout STRING;
+ chars : in integer) is
+ alias xarg : STRING (1 to arg'length) is arg; -- make it downto range
+ variable j : INTEGER := 0; -- charters read
+ begin
+ for i in 1 to arg'length loop
+ if xarg(i) = ' ' or xarg(i) = NBSP or xarg(i) = HT or j > chars then
+ exit;
+ elsif xarg(i) = ':' then
+ xarg (i) := '.';
+ elsif xarg (i) /= '_' then
+ j := j + 1;
+ end if;
+ end loop;
+ end procedure fix_colon;
+
+ procedure WRITE (
+ L : inout LINE; -- input line
+ VALUE : in UNRESOLVED_float; -- floating point input
+ JUSTIFIED : in SIDE := right;
+ FIELD : in WIDTH := 0) is
+ variable s : STRING(1 to VALUE'high - VALUE'low +3);
+ variable sindx : INTEGER;
+ begin -- function write
+ s(1) := MVL9_to_char(STD_ULOGIC(VALUE(VALUE'high)));
+ s(2) := ':';
+ sindx := 3;
+ for i in VALUE'high-1 downto 0 loop
+ s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i)));
+ sindx := sindx + 1;
+ end loop;
+ s(sindx) := ':';
+ sindx := sindx + 1;
+ for i in -1 downto VALUE'low loop
+ s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i)));
+ sindx := sindx + 1;
+ end loop;
+ WRITE (L, s, JUSTIFIED, FIELD);
+ end procedure WRITE;
+
+ procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float) is
+ -- Possible data: 0:0000:0000000
+ -- 000000000000
+ variable c : CHARACTER;
+ variable mv : UNRESOLVED_float (VALUE'range);
+ variable readOk : BOOLEAN;
+ variable lastu : BOOLEAN := false; -- last character was an "_"
+ variable i : INTEGER; -- index variable
+ begin -- READ
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ skip_whitespace (L);
+ READ (L, c, readOk);
+ if VALUE'length > 0 then
+ i := VALUE'high;
+ readloop : loop
+ if readOk = false then -- Bail out if there was a bad read
+ report float_generic_pkg'instance_name
+ & "READ(float): "
+ & "Error end of file encountered."
+ severity error;
+ return;
+ elsif c = ' ' or c = CR or c = HT then -- reading done.
+ if (i /= VALUE'low) then
+ report float_generic_pkg'instance_name
+ & "READ(float): "
+ & "Warning: Value truncated."
+ severity warning;
+ return;
+ end if;
+ elsif c = '_' then
+ if i = VALUE'high then -- Begins with an "_"
+ report float_generic_pkg'instance_name
+ & "READ(float): "
+ & "String begins with an ""_""" severity error;
+ return;
+ elsif lastu then -- "__" detected
+ report float_generic_pkg'instance_name
+ & "READ(float): "
+ & "Two underscores detected in input string ""__"""
+ severity error;
+ return;
+ else
+ lastu := true;
+ end if;
+ elsif c = ':' or c = '.' then -- separator, ignore
+ if not (i = -1 or i = VALUE'high-1) then
+ report float_generic_pkg'instance_name
+ & "READ(float): "
+ & "Warning: Separator point does not match number format: '"
+ & c & "' encountered at location " & INTEGER'image(i) & "."
+ severity warning;
+ end if;
+ lastu := false;
+ elsif (char_to_MVL9plus(c) = error) then
+ report float_generic_pkg'instance_name
+ & "READ(float): "
+ & "Error: Character '" & c & "' read, expected STD_ULOGIC literal."
+ severity error;
+ return;
+ else
+ mv (i) := char_to_MVL9(c);
+ i := i - 1;
+ if i < VALUE'low then
+ VALUE := mv;
+ return;
+ end if;
+ lastu := false;
+ end if;
+ READ (L, c, readOk);
+ end loop readloop;
+ end if;
+ end procedure READ;
+
+ procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is
+ -- Possible data: 0:0000:0000000
+ -- 000000000000
+ variable c : CHARACTER;
+ variable mv : UNRESOLVED_float (VALUE'range);
+ variable lastu : BOOLEAN := false; -- last character was an "_"
+ variable i : INTEGER; -- index variable
+ variable readOk : BOOLEAN;
+ begin -- READ
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ skip_whitespace (L);
+ READ (L, c, readOk);
+ if VALUE'length > 0 then
+ i := VALUE'high;
+ GOOD := false;
+ readloop : loop
+ if readOk = false then -- Bail out if there was a bad read
+ return;
+ elsif c = ' ' or c = CR or c = HT then -- reading done
+ return;
+ elsif c = '_' then
+ if i = 0 then -- Begins with an "_"
+ return;
+ elsif lastu then -- "__" detected
+ return;
+ else
+ lastu := true;
+ end if;
+ elsif c = ':' or c = '.' then -- separator, ignore
+ -- good := (i = -1 or i = value'high-1);
+ lastu := false;
+ elsif (char_to_MVL9plus(c) = error) then
+ return;
+ else
+ mv (i) := char_to_MVL9(c);
+ i := i - 1;
+ if i < VALUE'low then
+ GOOD := true;
+ VALUE := mv;
+ return;
+ end if;
+ lastu := false;
+ end if;
+ READ (L, c, readOk);
+ end loop readloop;
+ else
+ GOOD := true; -- read into a null array
+ end if;
+ end procedure READ;
+
+ procedure OWRITE (
+ L : inout LINE; -- access type (pointer)
+ VALUE : in UNRESOLVED_float; -- value to write
+ JUSTIFIED : in SIDE := right; -- which side to justify text
+ FIELD : in WIDTH := 0) is -- width of field
+ begin
+ WRITE (L => L,
+ VALUE => to_ostring(VALUE),
+ JUSTIFIED => JUSTIFIED,
+ FIELD => FIELD);
+ end procedure OWRITE;
+
+ procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float) is
+ constant ne : INTEGER := ((VALUE'length+2)/3) * 3; -- pad
+ variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv
+ variable slvu : ufixed (VALUE'range); -- Unsigned fixed point
+ variable c : CHARACTER;
+ variable ok : BOOLEAN;
+ variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits
+ variable colon, dot : BOOLEAN;
+ begin
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ skip_whitespace (L);
+ if VALUE'length > 0 then
+ check_punctuation (arg => L.all,
+ colon => colon,
+ dot => dot,
+ good => ok,
+ chars => ne/3);
+ if not ok then
+ report float_generic_pkg'instance_name & "OREAD: "
+ & "short string encounted: " & L.all
+ & " needs to have " & integer'image (ne/3)
+ & " valid octal characters."
+ severity error;
+ return;
+ elsif dot then
+ OREAD (L, slvu, ok); -- read it like a UFIXED number
+ if not ok then
+ report float_generic_pkg'instance_name & "OREAD: "
+ & "error encounted reading STRING " & L.all
+ severity error;
+ return;
+ else
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ elsif colon then
+ OREAD (L, nybble, ok); -- read the sign bit
+ if not ok then
+ report float_generic_pkg'instance_name & "OREAD: "
+ & "End of string encountered"
+ severity error;
+ return;
+ elsif nybble (2 downto 1) /= "00" then
+ report float_generic_pkg'instance_name & "OREAD: "
+ & "Illegal sign bit STRING encounted "
+ severity error;
+ return;
+ end if;
+ read (L, c, ok); -- read the colon
+ fix_colon (L.all, ne/3); -- replaces the colon with a ".".
+ OREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number
+ if not ok then
+ report float_generic_pkg'instance_name & "OREAD: "
+ & "error encounted reading STRING " & L.all
+ severity error;
+ return;
+ else
+ slvu (slvu'high) := nybble (0);
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ else
+ OREAD (L, slv, ok);
+ if not ok then
+ report float_generic_pkg'instance_name & "OREAD: "
+ & "Error encounted during read"
+ severity error;
+ return;
+ end if;
+ if (or (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then
+ report float_generic_pkg'instance_name & "OREAD: "
+ & "Vector truncated."
+ severity error;
+ return;
+ end if;
+ VALUE := to_float (slv(VALUE'high-VALUE'low downto 0),
+ VALUE'high, -VALUE'low);
+ end if;
+ end if;
+ end procedure OREAD;
+
+ procedure OREAD(L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is
+ constant ne : INTEGER := ((VALUE'length+2)/3) * 3; -- pad
+ variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv
+ variable slvu : ufixed (VALUE'range); -- Unsigned fixed point
+ variable c : CHARACTER;
+ variable ok : BOOLEAN;
+ variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits
+ variable colon, dot : BOOLEAN;
+ begin
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ GOOD := false;
+ skip_whitespace (L);
+ if VALUE'length > 0 then
+ check_punctuation (arg => L.all,
+ colon => colon,
+ dot => dot,
+ good => ok,
+ chars => ne/3);
+ if not ok then
+ return;
+ elsif dot then
+ OREAD (L, slvu, ok); -- read it like a UFIXED number
+ if not ok then
+ return;
+ else
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ elsif colon then
+ OREAD (L, nybble, ok); -- read the sign bit
+ if not ok then
+ return;
+ elsif nybble (2 downto 1) /= "00" then
+ return;
+ end if;
+ read (L, c, ok); -- read the colon
+ fix_colon (L.all, ne/3); -- replaces the colon with a ".".
+ OREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number
+ if not ok then
+ return;
+ else
+ slvu (slvu'high) := nybble (0);
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ else
+ OREAD (L, slv, ok);
+ if not ok then
+ return;
+ end if;
+ if (or (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then
+ return;
+ end if;
+ VALUE := to_float (slv(VALUE'high-VALUE'low downto 0),
+ VALUE'high, -VALUE'low);
+ end if;
+ GOOD := true;
+ end if;
+ end procedure OREAD;
+
+ procedure HWRITE (
+ L : inout LINE; -- access type (pointer)
+ VALUE : in UNRESOLVED_float; -- value to write
+ JUSTIFIED : in SIDE := right; -- which side to justify text
+ FIELD : in WIDTH := 0) is -- width of field
+ begin
+ WRITE (L => L,
+ VALUE => to_hstring(VALUE),
+ JUSTIFIED => JUSTIFIED,
+ FIELD => FIELD);
+ end procedure HWRITE;
+
+ procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float) is
+ constant ne : INTEGER := ((VALUE'length+3)/4) * 4; -- pad
+ variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv
+ variable slvu : ufixed (VALUE'range); -- Unsigned fixed point
+ variable c : CHARACTER;
+ variable ok : BOOLEAN;
+ variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits
+ variable colon, dot : BOOLEAN;
+ begin
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ skip_whitespace (L);
+ if VALUE'length > 0 then
+ check_punctuation (arg => L.all,
+ colon => colon,
+ dot => dot,
+ good => ok,
+ chars => ne/4);
+ if not ok then
+ report float_generic_pkg'instance_name & "HREAD: "
+ & "short string encounted: " & L.all
+ & " needs to have " & integer'image (ne/4)
+ & " valid hex characters."
+ severity error;
+ return;
+ elsif dot then
+ HREAD (L, slvu, ok); -- read it like a UFIXED number
+ if not ok then
+ report float_generic_pkg'instance_name & "HREAD: "
+ & "error encounted reading STRING " & L.all
+ severity error;
+ return;
+ else
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ elsif colon then
+ HREAD (L, nybble, ok); -- read the sign bit
+ if not ok then
+ report float_generic_pkg'instance_name & "HREAD: "
+ & "End of string encountered"
+ severity error;
+ return;
+ elsif nybble (3 downto 1) /= "000" then
+ report float_generic_pkg'instance_name & "HREAD: "
+ & "Illegal sign bit STRING encounted "
+ severity error;
+ return;
+ end if;
+ read (L, c, ok); -- read the colon
+ fix_colon (L.all, ne/4); -- replaces the colon with a ".".
+ HREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number
+ if not ok then
+ report float_generic_pkg'instance_name & "HREAD: "
+ & "error encounted reading STRING " & L.all
+ severity error;
+ return;
+ else
+ slvu (slvu'high) := nybble (0);
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ else
+ HREAD (L, slv, ok);
+ if not ok then
+ report float_generic_pkg'instance_name & "HREAD: "
+ & "Error encounted during read"
+ severity error;
+ return;
+ end if;
+ if (or (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then
+ report float_generic_pkg'instance_name & "HREAD: "
+ & "Vector truncated."
+ severity error;
+ return;
+ end if;
+ VALUE := to_float (slv(VALUE'high-VALUE'low downto 0),
+ VALUE'high, -VALUE'low);
+ end if;
+ end if;
+ end procedure HREAD;
+
+ procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is
+ constant ne : INTEGER := ((VALUE'length+3)/4) * 4; -- pad
+ variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv
+ variable slvu : ufixed (VALUE'range); -- Unsigned fixed point
+ variable c : CHARACTER;
+ variable ok : BOOLEAN;
+ variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits
+ variable colon, dot : BOOLEAN;
+ begin
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ GOOD := false;
+ skip_whitespace (L);
+ if VALUE'length > 0 then
+ check_punctuation (arg => L.all,
+ colon => colon,
+ dot => dot,
+ good => ok,
+ chars => ne/4);
+ if not ok then
+ return;
+ elsif dot then
+ HREAD (L, slvu, ok); -- read it like a UFIXED number
+ if not ok then
+ return;
+ else
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ elsif colon then
+ HREAD (L, nybble, ok); -- read the sign bit
+ if not ok then
+ return;
+ elsif nybble (3 downto 1) /= "000" then
+ return;
+ end if;
+ read (L, c, ok); -- read the colon
+ fix_colon (L.all, ne/4); -- replaces the colon with a ".".
+ HREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number
+ if not ok then
+ return;
+ else
+ slvu (slvu'high) := nybble (0);
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ else
+ HREAD (L, slv, ok);
+ if not ok then
+ return;
+ end if;
+ if (or (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then
+ return;
+ end if;
+ VALUE := to_float (slv(VALUE'high-VALUE'low downto 0),
+ VALUE'high, -VALUE'low);
+ end if;
+ GOOD := true;
+ end if;
+ end procedure HREAD;
+
+ function to_string (value : UNRESOLVED_float) return STRING is
+ variable s : STRING(1 to value'high - value'low +3);
+ variable sindx : INTEGER;
+ begin -- function write
+ s(1) := MVL9_to_char(STD_ULOGIC(value(value'high)));
+ s(2) := ':';
+ sindx := 3;
+ for i in value'high-1 downto 0 loop
+ s(sindx) := MVL9_to_char(STD_ULOGIC(value(i)));
+ sindx := sindx + 1;
+ end loop;
+ s(sindx) := ':';
+ sindx := sindx + 1;
+ for i in -1 downto value'low loop
+ s(sindx) := MVL9_to_char(STD_ULOGIC(value(i)));
+ sindx := sindx + 1;
+ end loop;
+ return s;
+ end function to_string;
+
+ function to_hstring (value : UNRESOLVED_float) return STRING is
+ variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0);
+ begin
+ floop : for i in slv'range loop
+ slv(i) := to_X01Z (value(i + value'low));
+ end loop floop;
+ return to_hstring (slv);
+ end function to_hstring;
+
+ function to_ostring (value : UNRESOLVED_float) return STRING is
+ variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0);
+ begin
+ floop : for i in slv'range loop
+ slv(i) := to_X01Z (value(i + value'low));
+ end loop floop;
+ return to_ostring (slv);
+ end function to_ostring;
+
+ function from_string (
+ bstring : STRING; -- binary string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable L : LINE;
+ variable good : BOOLEAN;
+ begin
+ L := new STRING'(bstring);
+ READ (L, result, good);
+ deallocate (L);
+ assert (good)
+ report float_generic_pkg'instance_name
+ & "from_string: Bad string " & bstring
+ severity error;
+ return result;
+ end function from_string;
+
+ function from_ostring (
+ ostring : STRING; -- Octal string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable L : LINE;
+ variable good : BOOLEAN;
+ begin
+ L := new STRING'(ostring);
+ OREAD (L, result, good);
+ deallocate (L);
+ assert (good)
+ report float_generic_pkg'instance_name
+ & "from_ostring: Bad string " & ostring
+ severity error;
+ return result;
+ end function from_ostring;
+
+ function from_hstring (
+ hstring : STRING; -- hex string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float
+ is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable L : LINE;
+ variable good : BOOLEAN;
+ begin
+ L := new STRING'(hstring);
+ HREAD (L, result, good);
+ deallocate (L);
+ assert (good)
+ report float_generic_pkg'instance_name
+ & "from_hstring: Bad string " & hstring
+ severity error;
+ return result;
+ end function from_hstring;
+
+ function from_string (
+ bstring : STRING; -- binary string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float is
+ begin
+ return from_string (bstring => bstring,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function from_string;
+
+ function from_ostring (
+ ostring : STRING; -- Octal string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float is
+ begin
+ return from_ostring (ostring => ostring,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function from_ostring;
+
+ function from_hstring (
+ hstring : STRING; -- hex string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float is
+ begin
+ return from_hstring (hstring => hstring,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function from_hstring;
+
+end package body float_generic_pkg;
diff --git a/common_pkg/float_pkg_c.vhd b/common_pkg/float_pkg_c.vhd
new file mode 100644
index 00000000..4443ce05
--- /dev/null
+++ b/common_pkg/float_pkg_c.vhd
@@ -0,0 +1,7074 @@
+-- --------------------------------------------------------------------
+-- "float_pkg" package contains functions for floating point math.
+-- Please see the documentation for the floating point package.
+-- This package should be compiled into "ieee_proposed" and used as follows:
+-- use ieee.std_logic_1164.all;
+-- use ieee.numeric_std.all;
+-- use ieee_proposed.fixed_float_types.all;
+-- use ieee_proposed.fixed_pkg.all;
+-- use ieee_proposed.float_pkg.all;
+--
+-- This verison is designed to work with the VHDL-93 compilers. Please
+-- note the "%%%" comments. These are where we diverge from the
+-- VHDL-200X LRM.
+--
+-- --------------------------------------------------------------------
+-- Version : $Revision: 1.2 $
+-- Date : $Date: 2011/03/24 07:44:24 $
+-- --------------------------------------------------------------------
+
+use STD.TEXTIO.all;
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.NUMERIC_STD.all;
+library common_pkg_lib;
+use common_pkg_lib.common_fixed_float_types.all;
+use common_pkg_lib.fixed_pkg.all;
+
+package float_pkg is
+-- generic (
+ -- Defaults for sizing routines, when you do a "to_float" this will be
+ -- the default size. Example float32 would be 8 and 23 (8 downto -23)
+ constant float_exponent_width : NATURAL := 8;
+ constant float_fraction_width : NATURAL := 23;
+ -- Rounding algorithm, "round_nearest" is default, other valid values
+ -- are "round_zero" (truncation), "round_inf" (round up), and
+ -- "round_neginf" (round down)
+ constant float_round_style : com_round_type := round_nearest;
+ -- Denormal numbers (very small numbers near zero) true or false
+ constant float_denormalize : BOOLEAN := true;
+ -- Turns on NAN processing (invalid numbers and overflow) true of false
+ constant float_check_error : BOOLEAN := true;
+ -- Guard bits are added to the bottom of every operation for rounding.
+ -- any natural number (including 0) are valid.
+ constant float_guard_bits : NATURAL := 3;
+ -- If TRUE, then turn off warnings on "X" propagation
+ constant no_warning : BOOLEAN := (false
+ );
+
+ -- Author David Bishop (dbishop@vhdl.org)
+
+ -- Note that the size of the vector is not defined here, but in
+ -- the package which calls this one.
+ type UNRESOLVED_float is array (INTEGER range <>) of STD_ULOGIC; -- main type
+ subtype U_float is UNRESOLVED_float;
+
+ subtype float is UNRESOLVED_float;
+ -----------------------------------------------------------------------------
+ -- Use the float type to define your own floating point numbers.
+ -- There must be a negative index or the packages will error out.
+ -- Minimum supported is "subtype float7 is float (3 downto -3);"
+ -- "subtype float16 is float (6 downto -9);" is probably the smallest
+ -- practical one to use.
+ -----------------------------------------------------------------------------
+
+ -- IEEE 754 single precision
+ subtype UNRESOLVED_float32 is UNRESOLVED_float (8 downto -23);
+ alias U_float32 is UNRESOLVED_float32;
+ subtype float32 is float (8 downto -23);
+ -----------------------------------------------------------------------------
+ -- IEEE-754 single precision floating point. This is a "float"
+ -- in C, and a FLOAT in Fortran. The exponent is 8 bits wide, and
+ -- the fraction is 23 bits wide. This format can hold roughly 7 decimal
+ -- digits. Infinity is 2**127 = 1.7E38 in this number system.
+ -- The bit representation is as follows:
+ -- 1 09876543 21098765432109876543210
+ -- 8 76543210 12345678901234567890123
+ -- 0 00000000 00000000000000000000000
+ -- 8 7 0 -1 -23
+ -- +/- exp. fraction
+ -----------------------------------------------------------------------------
+
+ -- IEEE 754 double precision
+ subtype UNRESOLVED_float64 is UNRESOLVED_float (11 downto -52);
+ alias U_float64 is UNRESOLVED_float64;
+ subtype float64 is float (11 downto -52);
+ -----------------------------------------------------------------------------
+ -- IEEE-754 double precision floating point. This is a "double float"
+ -- in C, and a FLOAT*8 in Fortran. The exponent is 11 bits wide, and
+ -- the fraction is 52 bits wide. This format can hold roughly 15 decimal
+ -- digits. Infinity is 2**2047 in this number system.
+ -- The bit representation is as follows:
+ -- 3 21098765432 1098765432109876543210987654321098765432109876543210
+ -- 1 09876543210 1234567890123456789012345678901234567890123456789012
+ -- S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ -- 11 10 0 -1 -52
+ -- +/- exponent fraction
+ -----------------------------------------------------------------------------
+
+ -- IEEE 854 & C extended precision
+ subtype UNRESOLVED_float128 is UNRESOLVED_float (15 downto -112);
+ alias U_float128 is UNRESOLVED_float128;
+ subtype float128 is float (15 downto -112);
+ -----------------------------------------------------------------------------
+ -- The 128 bit floating point number is "long double" in C (on
+ -- some systems this is a 70 bit floating point number) and FLOAT*32
+ -- in Fortran. The exponent is 15 bits wide and the fraction is 112
+ -- bits wide. This number can handle approximately 33 decimal digits.
+ -- Infinity is 2**32,767 in this number system.
+ -----------------------------------------------------------------------------
+
+ -- purpose: Checks for a valid floating point number
+ type valid_fpstate is (nan, -- Signaling NaN (C FP_NAN)
+ quiet_nan, -- Quiet NaN (C FP_NAN)
+ neg_inf, -- Negative infinity (C FP_INFINITE)
+ neg_normal, -- negative normalized nonzero
+ neg_denormal, -- negative denormalized (FP_SUBNORMAL)
+ neg_zero, -- -0 (C FP_ZERO)
+ pos_zero, -- +0 (C FP_ZERO)
+ pos_denormal, -- Positive denormalized (FP_SUBNORMAL)
+ pos_normal, -- positive normalized nonzero
+ pos_inf, -- positive infinity
+ isx); -- at least one input is unknown
+
+ -- This deferred constant will tell you if the package body is synthesizable
+ -- or implemented as real numbers.
+ constant fphdlsynth_or_real : BOOLEAN; -- deferred constant
+
+ -- Returns the class which X falls into
+ function Classfp (
+ x : UNRESOLVED_float; -- floating point input
+ check_error : BOOLEAN := float_check_error) -- check for errors
+ return valid_fpstate;
+
+ -- Arithmetic functions, these operators do not require parameters.
+ function "abs" (arg : UNRESOLVED_float) return UNRESOLVED_float;
+ function "-" (arg : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- These allows the base math functions to use the default values
+ -- of their parameters. Thus they do full IEEE floating point.
+
+ function "+" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "-" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "*" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "/" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "rem" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "mod" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- Basic parameter list
+ -- round_style - Selects the rounding algorithm to use
+ -- guard - extra bits added to the end if the operation to add precision
+ -- check_error - When "false" turns off NAN and overflow checks
+ -- denormalize - When "false" turns off denormal number processing
+
+ function add (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function subtract (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function multiply (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function divide (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function remainder (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function modulo (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- reciprocal
+ function reciprocal (
+ arg : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function dividebyp2 (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- Multiply accumulate result = l*r + c
+ function mac (
+ l, r, c : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- Square root (all 754 based implementations need this)
+ function sqrt (
+ arg : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style;
+ constant guard : NATURAL := float_guard_bits;
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_float;
+
+ function Is_Negative (arg : UNRESOLVED_float) return BOOLEAN;
+
+ -----------------------------------------------------------------------------
+ -- compare functions
+ -- =, /=, >=, <=, <, >, maximum, minimum
+
+ function eq ( -- equal =
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ function ne ( -- not equal /=
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ function lt ( -- less than <
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ function gt ( -- greater than >
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ function le ( -- less than or equal to <=
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ function ge ( -- greater than or equal to >=
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN;
+
+ -- Need to overload the default versions of these
+ function "=" (l, r : UNRESOLVED_float) return BOOLEAN;
+ function "/=" (l, r : UNRESOLVED_float) return BOOLEAN;
+ function ">=" (l, r : UNRESOLVED_float) return BOOLEAN;
+ function "<=" (l, r : UNRESOLVED_float) return BOOLEAN;
+ function ">" (l, r : UNRESOLVED_float) return BOOLEAN;
+ function "<" (l, r : UNRESOLVED_float) return BOOLEAN;
+
+ function \?=\ (l, r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?/=\ (l, r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?>\ (l, r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?>=\ (l, r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?<\ (l, r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?<=\ (l, r : UNRESOLVED_float) return STD_ULOGIC;
+
+ function std_match (l, r : UNRESOLVED_float) return BOOLEAN;
+ function find_rightmost (arg : UNRESOLVED_float; y : STD_ULOGIC)
+ return INTEGER;
+ function find_leftmost (arg : UNRESOLVED_float; y : STD_ULOGIC)
+ return INTEGER;
+ function maximum (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function minimum (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- conversion functions
+ -- Converts one floating point number into another.
+
+ function resize (
+ arg : UNRESOLVED_float; -- Floating point input
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function resize (
+ arg : UNRESOLVED_float; -- Floating point input
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ function to_float32 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float32;
+
+ function to_float64 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float64;
+
+ function to_float128 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float128;
+
+ -- Converts an fp into an SLV (needed for synthesis)
+ function to_slv (arg : UNRESOLVED_float) return STD_LOGIC_VECTOR;
+ alias to_StdLogicVector is to_slv [UNRESOLVED_float return STD_LOGIC_VECTOR];
+ alias to_Std_Logic_Vector is to_slv [UNRESOLVED_float return STD_LOGIC_VECTOR];
+
+ -- Converts an fp into an std_ulogic_vector (sulv)
+ function to_sulv (arg : UNRESOLVED_float) return STD_ULOGIC_VECTOR;
+ alias to_StdULogicVector is to_sulv [UNRESOLVED_float return STD_ULOGIC_VECTOR];
+ alias to_Std_ULogic_Vector is to_sulv [UNRESOLVED_float return STD_ULOGIC_VECTOR];
+
+ -- std_ulogic_vector to float
+ function to_float (
+ arg : STD_ULOGIC_VECTOR;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction
+ return UNRESOLVED_float;
+
+ -- Integer to float
+ function to_float (
+ arg : INTEGER;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- real to float
+ function to_float (
+ arg : REAL;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- unsigned to float
+ function to_float (
+ arg : UNSIGNED;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- signed to float
+ function to_float (
+ arg : SIGNED;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- unsigned fixed point to float
+ function to_float (
+ arg : UNRESOLVED_ufixed; -- unsigned fixed point input
+ constant exponent_width : NATURAL := float_exponent_width; -- width of exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- width of fraction
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions
+ return UNRESOLVED_float;
+
+ -- signed fixed point to float
+ function to_float (
+ arg : UNRESOLVED_sfixed;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- rounding option
+ return UNRESOLVED_float;
+
+ -- size_res functions
+ -- Integer to float
+ function to_float (
+ arg : INTEGER;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- real to float
+ function to_float (
+ arg : REAL;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- unsigned to float
+ function to_float (
+ arg : UNSIGNED;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- signed to float
+ function to_float (
+ arg : SIGNED;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float;
+
+ -- sulv to float
+ function to_float (
+ arg : STD_ULOGIC_VECTOR;
+ size_res : UNRESOLVED_float)
+ return UNRESOLVED_float;
+
+ -- unsigned fixed point to float
+ function to_float (
+ arg : UNRESOLVED_ufixed; -- unsigned fixed point input
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions
+ return UNRESOLVED_float;
+
+ -- signed fixed point to float
+ function to_float (
+ arg : UNRESOLVED_sfixed;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- rounding option
+ return UNRESOLVED_float;
+
+ -- float to unsigned
+ function to_unsigned (
+ arg : UNRESOLVED_float; -- floating point input
+ constant size : NATURAL; -- length of output
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNSIGNED;
+
+ -- float to signed
+ function to_signed (
+ arg : UNRESOLVED_float; -- floating point input
+ constant size : NATURAL; -- length of output
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return SIGNED;
+
+ -- purpose: Converts a float to unsigned fixed point
+ function to_ufixed (
+ arg : UNRESOLVED_float; -- fp input
+ constant left_index : INTEGER; -- integer part
+ constant right_index : INTEGER; -- fraction part
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_ufixed;
+
+ -- float to signed fixed point
+ function to_sfixed (
+ arg : UNRESOLVED_float; -- fp input
+ constant left_index : INTEGER; -- integer part
+ constant right_index : INTEGER; -- fraction part
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_sfixed;
+
+ -- size_res versions
+ -- float to unsigned
+ function to_unsigned (
+ arg : UNRESOLVED_float; -- floating point input
+ size_res : UNSIGNED;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNSIGNED;
+
+ -- float to signed
+ function to_signed (
+ arg : UNRESOLVED_float; -- floating point input
+ size_res : SIGNED;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return SIGNED;
+
+ -- purpose: Converts a float to unsigned fixed point
+ function to_ufixed (
+ arg : UNRESOLVED_float; -- fp input
+ size_res : UNRESOLVED_ufixed;
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_ufixed;
+
+ -- float to signed fixed point
+ function to_sfixed (
+ arg : UNRESOLVED_float; -- fp input
+ size_res : UNRESOLVED_sfixed;
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_sfixed;
+
+ -- float to real
+ function to_real (
+ arg : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return REAL;
+
+ -- float to integer
+ function to_integer (
+ arg : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return INTEGER;
+
+ -- For Verilog compatability
+ function realtobits (arg : REAL) return STD_ULOGIC_VECTOR;
+ function bitstoreal (arg : STD_ULOGIC_VECTOR) return REAL;
+
+ -- Maps metalogical values
+ function to_01 (
+ arg : UNRESOLVED_float; -- floating point input
+ XMAP : STD_LOGIC := '0')
+ return UNRESOLVED_float;
+
+ function Is_X (arg : UNRESOLVED_float) return BOOLEAN;
+ function to_X01 (arg : UNRESOLVED_float) return UNRESOLVED_float;
+ function to_X01Z (arg : UNRESOLVED_float) return UNRESOLVED_float;
+ function to_UX01 (arg : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- These two procedures were copied out of the body because they proved
+ -- very useful for vendor specific algorithm development
+ -- Break_number converts a floating point number into it's parts
+ -- Exponent is biased by -1
+
+ procedure break_number (
+ arg : in UNRESOLVED_float;
+ denormalize : in BOOLEAN := float_denormalize;
+ check_error : in BOOLEAN := float_check_error;
+ fract : out UNSIGNED;
+ expon : out SIGNED; -- NOTE: Add 1 to get the real exponent!
+ sign : out STD_ULOGIC);
+
+ procedure break_number (
+ arg : in UNRESOLVED_float;
+ denormalize : in BOOLEAN := float_denormalize;
+ check_error : in BOOLEAN := float_check_error;
+ fract : out ufixed; -- a number between 1.0 and 2.0
+ expon : out SIGNED; -- NOTE: Add 1 to get the real exponent!
+ sign : out STD_ULOGIC);
+
+ -- Normalize takes a fraction and and exponent and converts them into
+ -- a floating point number. Does the shifting and the rounding.
+ -- Exponent is assumed to be biased by -1
+
+ function normalize (
+ fract : UNSIGNED; -- fraction, unnormalized
+ expon : SIGNED; -- exponent - 1, normalized
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float;
+
+ -- Exponent is assumed to be biased by -1
+ function normalize (
+ fract : ufixed; -- unsigned fixed point
+ expon : SIGNED; -- exponent - 1, normalized
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float;
+
+ function normalize (
+ fract : UNSIGNED; -- unsigned
+ expon : SIGNED; -- exponent - 1, normalized
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ size_res : UNRESOLVED_float; -- used for sizing only
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float;
+
+ -- Exponent is assumed to be biased by -1
+ function normalize (
+ fract : ufixed; -- unsigned fixed point
+ expon : SIGNED; -- exponent - 1, normalized
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ size_res : UNRESOLVED_float; -- used for sizing only
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float;
+
+ -- overloaded versions
+ function "+" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "+" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "+" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "+" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "-" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "-" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "-" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "-" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "*" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "*" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "*" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "*" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "/" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "/" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "/" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "/" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "rem" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "rem" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "rem" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "rem" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "mod" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function "mod" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "mod" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function "mod" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- overloaded compare functions
+ function "=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function "/=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function ">=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function "<=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function ">" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function "<" (l : UNRESOLVED_float; r : REAL) return BOOLEAN;
+ function "=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function "/=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function ">=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function "<=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function ">" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function "<" (l : REAL; r : UNRESOLVED_float) return BOOLEAN;
+ function "=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function "/=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function ">=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function "<=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function ">" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function "<" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN;
+ function "=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function "/=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function ">=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function "<=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function ">" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function "<" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN;
+ function \?=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function \?/=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function \?>\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function \?>=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function \?<\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function \?<=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC;
+ function \?=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?/=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?>\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?>=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?<\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?<=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function \?/=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function \?>\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function \?>=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function \?<\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function \?<=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC;
+ function \?=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?/=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?>\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?>=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?<\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ function \?<=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC;
+ -- minimum and maximum overloads
+ function maximum (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function minimum (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float;
+ function maximum (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function minimum (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function maximum (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function minimum (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float;
+ function maximum (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+ function minimum (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float;
+----------------------------------------------------------------------------
+ -- logical functions
+ ----------------------------------------------------------------------------
+
+ function "not" (l : UNRESOLVED_float) return UNRESOLVED_float;
+ function "and" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "or" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "nand" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "nor" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "xor" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ function "xnor" (l, r : UNRESOLVED_float) return UNRESOLVED_float;
+ -- Vector and std_ulogic functions, same as functions in numeric_std
+ function "and" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "and" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ function "or" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "or" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ function "nand" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "nand" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ function "nor" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "nor" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ function "xor" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "xor" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ function "xnor" (l : STD_ULOGIC; r : UNRESOLVED_float)
+ return UNRESOLVED_float;
+ function "xnor" (l : UNRESOLVED_float; r : STD_ULOGIC)
+ return UNRESOLVED_float;
+ -- Reduction operators, same as numeric_std functions
+ function and_reduce (l : UNRESOLVED_float) return STD_ULOGIC;
+ function nand_reduce (l : UNRESOLVED_float) return STD_ULOGIC;
+ function or_reduce (l : UNRESOLVED_float) return STD_ULOGIC;
+ function nor_reduce (l : UNRESOLVED_float) return STD_ULOGIC;
+ function xor_reduce (l : UNRESOLVED_float) return STD_ULOGIC;
+ function xnor_reduce (l : UNRESOLVED_float) return STD_ULOGIC;
+
+ -- Note: "sla", "sra", "sll", "slr", "rol" and "ror" not implemented.
+
+ -----------------------------------------------------------------------------
+ -- Recommended Functions from the IEEE 754 Appendix
+ -----------------------------------------------------------------------------
+
+ -- returns x with the sign of y.
+ function Copysign (x, y : UNRESOLVED_float) return UNRESOLVED_float;
+
+ -- Returns y * 2**n for integral values of N without computing 2**n
+ function Scalb (
+ y : UNRESOLVED_float; -- floating point input
+ N : INTEGER; -- exponent to add
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- Returns y * 2**n for integral values of N without computing 2**n
+ function Scalb (
+ y : UNRESOLVED_float; -- floating point input
+ N : SIGNED; -- exponent to add
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float;
+
+ -- returns the unbiased exponent of x
+ function Logb (x : UNRESOLVED_float) return INTEGER;
+ function Logb (x : UNRESOLVED_float) return SIGNED;
+
+ -- returns the next representable neighbor of x in the direction toward y
+ function Nextafter (
+ x, y : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_float;
+
+ -- Returns TRUE if X is unordered with Y.
+ function Unordered (x, y : UNRESOLVED_float) return BOOLEAN;
+ function Finite (x : UNRESOLVED_float) return BOOLEAN;
+ function Isnan (x : UNRESOLVED_float) return BOOLEAN;
+
+ -- Function to return constants.
+ function zerofp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ function nanfp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ function qnanfp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ function pos_inffp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ function neg_inffp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ function neg_zerofp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float;
+ -- size_res versions
+ function zerofp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+ function nanfp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+ function qnanfp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+ function pos_inffp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+ function neg_inffp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+ function neg_zerofp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float;
+
+ -- ===========================================================================
+ -- string and textio Functions
+ -- ===========================================================================
+-- rtl_synthesis off
+-- pragma synthesis_off
+ -- writes S:EEEE:FFFFFFFF
+ procedure WRITE (
+ L : inout LINE; -- access type (pointer)
+ VALUE : in UNRESOLVED_float; -- value to write
+ JUSTIFIED : in SIDE := right; -- which side to justify text
+ FIELD : in WIDTH := 0); -- width of field
+
+ -- Reads SEEEEFFFFFFFF, "." and ":" are ignored
+ procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float);
+ procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float;
+ GOOD : out BOOLEAN);
+
+ alias BREAD is READ [LINE, UNRESOLVED_float, BOOLEAN];
+ alias BREAD is READ [LINE, UNRESOLVED_float];
+ alias BWRITE is WRITE [LINE, UNRESOLVED_float, SIDE, WIDTH];
+ alias BINARY_READ is READ [LINE, UNRESOLVED_FLOAT, BOOLEAN];
+ alias BINARY_READ is READ [LINE, UNRESOLVED_FLOAT];
+ alias BINARY_WRITE is WRITE [LINE, UNRESOLVED_float, SIDE, WIDTH];
+
+ procedure OWRITE (
+ L : inout LINE; -- access type (pointer)
+ VALUE : in UNRESOLVED_float; -- value to write
+ JUSTIFIED : in SIDE := right; -- which side to justify text
+ FIELD : in WIDTH := 0); -- width of field
+
+ -- Octal read with padding, no separators used
+ procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float);
+ procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float;
+ GOOD : out BOOLEAN);
+ alias OCTAL_READ is OREAD [LINE, UNRESOLVED_FLOAT, BOOLEAN];
+ alias OCTAL_READ is OREAD [LINE, UNRESOLVED_FLOAT];
+ alias OCTAL_WRITE is OWRITE [LINE, UNRESOLVED_FLOAT, SIDE, WIDTH];
+
+ -- Hex write with padding, no separators
+ procedure HWRITE (
+ L : inout LINE; -- access type (pointer)
+ VALUE : in UNRESOLVED_float; -- value to write
+ JUSTIFIED : in SIDE := right; -- which side to justify text
+ FIELD : in WIDTH := 0); -- width of field
+
+ -- Hex read with padding, no separators used
+ procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float);
+ procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float;
+ GOOD : out BOOLEAN);
+ alias HEX_READ is HREAD [LINE, UNRESOLVED_FLOAT, BOOLEAN];
+ alias HEX_READ is HREAD [LINE, UNRESOLVED_FLOAT];
+ alias HEX_WRITE is HWRITE [LINE, UNRESOLVED_FLOAT, SIDE, WIDTH];
+
+ -- returns "S:EEEE:FFFFFFFF"
+ function to_string (value : UNRESOLVED_float) return STRING;
+ alias TO_BSTRING is TO_STRING [UNRESOLVED_FLOAT return STRING];
+ alias TO_BINARY_STRING is TO_STRING [UNRESOLVED_FLOAT return STRING];
+
+ -- Returns a HEX string, with padding
+ function to_hstring (value : UNRESOLVED_float) return STRING;
+ alias TO_HEX_STRING is TO_HSTRING [UNRESOLVED_FLOAT return STRING];
+
+ -- Returns and octal string, with padding
+ function to_ostring (value : UNRESOLVED_float) return STRING;
+ alias TO_OCTAL_STRING is TO_OSTRING [UNRESOLVED_FLOAT return STRING];
+
+ function from_string (
+ bstring : STRING; -- binary string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float;
+ alias from_bstring is from_string [STRING, NATURAL, NATURAL
+ return UNRESOLVED_float];
+ alias from_binary_string is from_string [STRING, NATURAL, NATURAL
+ return UNRESOLVED_float];
+ function from_ostring (
+ ostring : STRING; -- Octal string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float;
+ alias from_octal_string is from_ostring [STRING, NATURAL, NATURAL
+ return UNRESOLVED_float];
+
+ function from_hstring (
+ hstring : STRING; -- hex string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float;
+ alias from_hex_string is from_hstring [STRING, NATURAL, NATURAL
+ return UNRESOLVED_float];
+
+ function from_string (
+ bstring : STRING; -- binary string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float;
+ alias from_bstring is from_string [STRING, UNRESOLVED_float
+ return UNRESOLVED_float];
+ alias from_binary_string is from_string [STRING, UNRESOLVED_float
+ return UNRESOLVED_float];
+
+ function from_ostring (
+ ostring : STRING; -- Octal string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float;
+ alias from_octal_string is from_ostring [STRING, UNRESOLVED_float
+ return UNRESOLVED_float];
+
+ function from_hstring (
+ hstring : STRING; -- hex string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float;
+ alias from_hex_string is from_hstring [STRING, UNRESOLVED_float
+ return UNRESOLVED_float];
+-- rtl_synthesis on
+-- pragma synthesis_on
+ -- IN VHDL-2006 std_logic_vector is a subtype of std_ulogic_vector, so these
+ -- extra functions are needed for compatability.
+
+
+
+
+end package float_pkg;
+-------------------------------------------------------------------------------
+-- Proposed package body for the VHDL-200x-FT float_pkg package
+-- This version is optimized for Synthesis, and not for simulation.
+-- Note that there are functional differences between the synthesis and
+-- simulation packages bodies. The Synthesis version is preferred.
+-- This package body supplies a recommended implementation of these functions
+-- Version : $Revision: 1.2 $
+-- Date : $Date: 2011/03/24 07:44:24 $
+--
+-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org)
+-------------------------------------------------------------------------------
+
+package body float_pkg is
+
+ -- Author David Bishop (dbishop@vhdl.org)
+ -----------------------------------------------------------------------------
+ -- type declarations
+ -----------------------------------------------------------------------------
+
+ -- This deferred constant will tell you if the package body is synthesizable
+ -- or implemented as real numbers, set to "true" if synthesizable.
+ constant fphdlsynth_or_real : BOOLEAN := true; -- deferred constant
+
+ -- types of boundary conditions
+ type boundary_type is (normal, infinity, zero, denormal);
+
+ -- null range array constant
+ constant NAFP : UNRESOLVED_float (0 downto 1) := (others => '0');
+ constant NSLV : STD_ULOGIC_VECTOR (0 downto 1) := (others => '0');
+
+ -- %%% Replicated functions
+ -- These functions are replicated so that we don't need to reference the new
+ -- 2006 package std.standard, std_logic_1164 and numeric_std.
+ function maximum (
+ l, r : INTEGER) -- inputs
+ return INTEGER is
+ begin -- function max
+ if l > r then return l;
+ else return r;
+ end if;
+ end function maximum;
+
+ function minimum (
+ l, r : INTEGER) -- inputs
+ return INTEGER is
+ begin -- function min
+ if l > r then return r;
+ else return l;
+ end if;
+ end function minimum;
+
+ function or_reduce (arg : STD_ULOGIC_VECTOR)
+ return STD_LOGIC is
+ variable Upper, Lower : STD_ULOGIC;
+ variable Half : INTEGER;
+ variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0);
+ variable Result : STD_ULOGIC;
+ begin
+ if (arg'length < 1) then -- In the case of a NULL range
+ Result := '0';
+ else
+ BUS_int := to_ux01 (arg);
+ if (BUS_int'length = 1) then
+ Result := BUS_int (BUS_int'left);
+ elsif (BUS_int'length = 2) then
+ Result := BUS_int (BUS_int'right) or BUS_int (BUS_int'left);
+ else
+ Half := (BUS_int'length + 1) / 2 + BUS_int'right;
+ Upper := or_reduce (BUS_int (BUS_int'left downto Half));
+ Lower := or_reduce (BUS_int (Half - 1 downto BUS_int'right));
+ Result := Upper or Lower;
+ end if;
+ end if;
+ return Result;
+ end function or_reduce;
+
+ function or_reduce (arg : UNSIGNED)
+ return STD_ULOGIC is
+ begin
+ return or_reduce (STD_ULOGIC_VECTOR (arg));
+ end function or_reduce;
+
+ function or_reduce (arg : SIGNED)
+ return STD_ULOGIC is
+ begin
+ return or_reduce (STD_ULOGIC_VECTOR (arg));
+ end function or_reduce;
+
+
+ -- purpose: AND all of the bits in a vector together
+ -- This is a copy of the proposed "and_reduce" from 1076.3
+ function and_reduce (arg : STD_ULOGIC_VECTOR)
+ return STD_LOGIC is
+ variable Upper, Lower : STD_ULOGIC;
+ variable Half : INTEGER;
+ variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0);
+ variable Result : STD_ULOGIC;
+ begin
+ if (arg'length < 1) then -- In the case of a NULL range
+ Result := '1';
+ else
+ BUS_int := to_ux01 (arg);
+ if (BUS_int'length = 1) then
+ Result := BUS_int (BUS_int'left);
+ elsif (BUS_int'length = 2) then
+ Result := BUS_int (BUS_int'right) and BUS_int (BUS_int'left);
+ else
+ Half := (BUS_int'length + 1) / 2 + BUS_int'right;
+ Upper := and_reduce (BUS_int (BUS_int'left downto Half));
+ Lower := and_reduce (BUS_int (Half - 1 downto BUS_int'right));
+ Result := Upper and Lower;
+ end if;
+ end if;
+ return Result;
+ end function and_reduce;
+
+ function and_reduce (arg : UNSIGNED)
+ return STD_ULOGIC is
+ begin
+ return and_reduce (STD_ULOGIC_VECTOR (arg));
+ end function and_reduce;
+
+ function and_reduce (arg : SIGNED)
+ return STD_ULOGIC is
+ begin
+ return and_reduce (STD_ULOGIC_VECTOR (arg));
+ end function and_reduce;
+
+ function xor_reduce (arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is
+ variable Upper, Lower : STD_ULOGIC;
+ variable Half : INTEGER;
+ variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0);
+ variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range
+ begin
+ if (arg'length >= 1) then
+ BUS_int := to_ux01 (arg);
+ if (BUS_int'length = 1) then
+ Result := BUS_int (BUS_int'left);
+ elsif (BUS_int'length = 2) then
+ Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left);
+ else
+ Half := (BUS_int'length + 1) / 2 + BUS_int'right;
+ Upper := xor_reduce (BUS_int (BUS_int'left downto Half));
+ Lower := xor_reduce (BUS_int (Half - 1 downto BUS_int'right));
+ Result := Upper xor Lower;
+ end if;
+ end if;
+ return Result;
+ end function xor_reduce;
+
+ function nand_reduce(arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is
+ begin
+ return not and_reduce (arg);
+ end function nand_reduce;
+
+ function nor_reduce(arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is
+ begin
+ return not or_reduce (arg);
+ end function nor_reduce;
+
+ function xnor_reduce(arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is
+ begin
+ return not xor_reduce (arg);
+ end function xnor_reduce;
+
+ function find_leftmost (ARG : UNSIGNED; Y : STD_ULOGIC)
+ return INTEGER is
+ begin
+ for INDEX in ARG'range loop
+ if ARG(INDEX) = Y then
+ return INDEX;
+ end if;
+ end loop;
+ return -1;
+ end function find_leftmost;
+
+ -- Match table, copied form new std_logic_1164
+ type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC;
+ constant match_logic_table : stdlogic_table := (
+ -----------------------------------------------------
+ -- U X 0 1 Z W L H - | |
+ -----------------------------------------------------
+ ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1'), -- | U |
+ ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | X |
+ ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | 0 |
+ ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | 1 |
+ ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | Z |
+ ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | W |
+ ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | L |
+ ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | H |
+ ('1', '1', '1', '1', '1', '1', '1', '1', '1') -- | - |
+ );
+
+
+ -------------------------------------------------------------------
+ -- ?= functions, Similar to "std_match", but returns "std_ulogic".
+ -------------------------------------------------------------------
+ -- %%% FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic IS
+ function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is
+ begin
+ return match_logic_table (l, r);
+ end function \?=\;
+ -- %%% END FUNCTION "?=";
+
+ -- %%% FUNCTION "?/=" ( l, r : std_ulogic ) RETURN std_ulogic is
+ function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is
+ begin
+ return not match_logic_table (l, r);
+ end function \?/=\;
+ -- %%% END FUNCTION "?/=";
+
+ function \?=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is
+ alias lv : STD_ULOGIC_VECTOR(1 to l'length) is l;
+ alias rv : STD_ULOGIC_VECTOR(1 to r'length) is r;
+ variable result, result1 : STD_ULOGIC;
+ begin
+ -- Logically identical to an "=" operator.
+ if ((l'length < 1) and (r'length < 1)) then
+ -- VHDL-2008 LRM 9.2.3 Two NULL arrays of the same type are equal
+ return '1';
+ elsif lv'length /= rv'length then
+ -- Two arrays of different lengths are false
+ return '0';
+ else
+ result := '1';
+ for i in lv'low to lv'high loop
+ result1 := match_logic_table(lv(i), rv(i));
+ result := result and result1;
+ end loop;
+ return result;
+ end if;
+ end function \?=\;
+
+ function Is_X (s : UNSIGNED) return BOOLEAN is
+ begin
+ return Is_X (STD_LOGIC_VECTOR (s));
+ end function Is_X;
+
+ function Is_X (s : SIGNED) return BOOLEAN is
+ begin
+ return Is_X (STD_LOGIC_VECTOR (s));
+ end function Is_X;
+-- %%% END replicated functions
+
+ -- Special version of "minimum" to do some boundary checking
+ function mine (L, R : INTEGER)
+ return INTEGER is
+ begin -- function minimum
+ if (L = INTEGER'low or R = INTEGER'low) then
+ report float_pkg'instance_name
+ & " Unbounded number passed, was a literal used?"
+ severity error;
+ return 0;
+ end if;
+ return minimum (L, R);
+ end function mine;
+
+ -- Generates the base number for the exponent normalization offset.
+ function gen_expon_base (
+ constant exponent_width : NATURAL)
+ return SIGNED is
+ variable result : SIGNED (exponent_width-1 downto 0);
+ begin
+ result := (others => '1');
+ result (exponent_width-1) := '0';
+ return result;
+ end function gen_expon_base;
+
+ -- Integer version of the "log2" command (contributed by Peter Ashenden)
+ function log2 (A : NATURAL) return NATURAL is
+ variable quotient : NATURAL;
+ variable result : NATURAL := 0;
+ begin
+ quotient := A / 2;
+ while quotient > 0 loop
+ quotient := quotient / 2;
+ result := result + 1;
+ end loop;
+ return result;
+ end function log2;
+
+ -- Function similar to the ILOGB function in MATH_REAL
+ function log2 (A : REAL) return INTEGER is
+ variable Y : REAL;
+ variable N : INTEGER := 0;
+ begin
+ if (A = 1.0 or A = 0.0) then
+ return 0;
+ end if;
+ Y := A;
+ if(A > 1.0) then
+ while Y >= 2.0 loop
+ Y := Y / 2.0;
+ N := N + 1;
+ end loop;
+ return N;
+ end if;
+ -- O < Y < 1
+ while Y < 1.0 loop
+ Y := Y * 2.0;
+ N := N - 1;
+ end loop;
+ return N;
+ end function log2;
+
+ -- purpose: Test the boundary conditions of a Real number
+ procedure test_boundary (
+ arg : in REAL; -- Input, converted to real
+ constant fraction_width : in NATURAL; -- length of FP output fraction
+ constant exponent_width : in NATURAL; -- length of FP exponent
+ constant denormalize : in BOOLEAN := true; -- Use IEEE extended FP
+ variable btype : out boundary_type;
+ variable log2i : out INTEGER
+ ) is
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ constant exp_min : SIGNED (12 downto 0) :=
+ -(resize(expon_base, 13)) + 1; -- Minimum normal exponent
+ constant exp_ext_min : SIGNED (12 downto 0) :=
+ exp_min - fraction_width; -- Minimum for denormal exponent
+ variable log2arg : INTEGER; -- log2 of argument
+ begin -- function test_boundary
+ -- Check to see if the exponent is big enough
+ -- Note that the argument is always an absolute value at this point.
+ log2arg := log2(arg);
+ if arg = 0.0 then
+ btype := zero;
+ elsif exponent_width > 11 then -- Exponent for Real is 11 (64 bit)
+ btype := normal;
+ else
+ if log2arg < to_integer(exp_min) then
+ if denormalize then
+ if log2arg < to_integer(exp_ext_min) then
+ btype := zero;
+ else
+ btype := denormal;
+ end if;
+ else
+ if log2arg < to_integer(exp_min)-1 then
+ btype := zero;
+ else
+ btype := normal; -- Can still represent this number
+ end if;
+ end if;
+ elsif exponent_width < 11 then
+ if log2arg > to_integer(expon_base)+1 then
+ btype := infinity;
+ else
+ btype := normal;
+ end if;
+ else
+ btype := normal;
+ end if;
+ end if;
+ log2i := log2arg;
+ end procedure test_boundary;
+
+ -- purpose: Rounds depending on the state of the "round_style"
+ -- Logic taken from
+ -- "What Every Computer Scientist Should Know About Floating Point Arithmetic"
+ -- by David Goldberg (1991)
+ function check_round (
+ fract_in : STD_ULOGIC; -- input fraction
+ sign : STD_ULOGIC; -- sign bit
+ remainder : UNSIGNED; -- remainder to round from
+ sticky : STD_ULOGIC := '0'; -- Sticky bit
+ constant round_style : com_round_type) -- rounding type
+ return BOOLEAN is
+ variable result : BOOLEAN;
+ variable or_reduced : STD_ULOGIC;
+ begin -- function check_round
+ result := false;
+ if (remainder'length > 0) then -- if remainder in a null array
+ or_reduced := or_reduce (remainder & sticky);
+ rounding_case : case round_style is
+ when round_nearest => -- Round Nearest, default mode
+ if remainder(remainder'high) = '1' then -- round
+ if (remainder'length > 1) then
+ if ((or_reduce (remainder(remainder'high-1
+ downto remainder'low)) = '1'
+ or sticky = '1')
+ or fract_in = '1') then
+ -- Make the bottom bit zero if possible if we are at 1/2
+ result := true;
+ end if;
+ else
+ result := (fract_in = '1' or sticky = '1');
+ end if;
+ end if;
+ when round_inf => -- round up if positive, else truncate.
+ if or_reduced = '1' and sign = '0' then
+ result := true;
+ end if;
+ when round_neginf => -- round down if negative, else truncate.
+ if or_reduced = '1' and sign = '1' then
+ result := true;
+ end if;
+ when round_zero => -- round toward 0 Truncate
+ null;
+ end case rounding_case;
+ end if;
+ return result;
+ end function check_round;
+
+ -- purpose: Rounds depending on the state of the "round_style"
+ -- unsigned version
+ procedure fp_round (
+ fract_in : in UNSIGNED; -- input fraction
+ expon_in : in SIGNED; -- input exponent
+ fract_out : out UNSIGNED; -- output fraction
+ expon_out : out SIGNED) is -- output exponent
+ begin -- procedure fp_round
+ if and_reduce (fract_in) = '1' then -- Fraction is all "1"
+ expon_out := expon_in + 1;
+ fract_out := to_unsigned(0, fract_out'high+1);
+ else
+ expon_out := expon_in;
+ fract_out := fract_in + 1;
+ end if;
+ end procedure fp_round;
+
+ -- This version of break_number doesn't call "classfp"
+ procedure break_number ( -- internal version
+ arg : in UNRESOLVED_float;
+ fptyp : in valid_fpstate;
+ denormalize : in BOOLEAN := true;
+ fract : out UNSIGNED;
+ expon : out SIGNED) is
+ constant fraction_width : NATURAL := -arg'low; -- length of FP output fraction
+ constant exponent_width : NATURAL := arg'high; -- length of FP output exponent
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable exp : SIGNED (expon'range);
+ begin
+ fract (fraction_width-1 downto 0) :=
+ UNSIGNED (to_slv(arg(-1 downto -fraction_width)));
+ breakcase : case fptyp is
+ when pos_zero | neg_zero =>
+ fract (fraction_width) := '0';
+ exp := -expon_base;
+ when pos_denormal | neg_denormal =>
+ if denormalize then
+ exp := -expon_base;
+ fract (fraction_width) := '0';
+ else
+ exp := -expon_base - 1;
+ fract (fraction_width) := '1';
+ end if;
+ when pos_normal | neg_normal | pos_inf | neg_inf =>
+ fract (fraction_width) := '1';
+ exp := SIGNED(arg(exponent_width-1 downto 0));
+ exp (exponent_width-1) := not exp(exponent_width-1);
+ when others =>
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & "BREAK_NUMBER: " &
+ "Meta state detected in fp_break_number process"
+ severity warning;
+ -- complete the case, if a NAN goes in, a NAN comes out.
+ exp := (others => '1');
+ fract (fraction_width) := '1';
+ end case breakcase;
+ expon := exp;
+ end procedure break_number;
+
+ -- purpose: floating point to UNSIGNED
+ -- Used by to_integer, to_unsigned, and to_signed functions
+ procedure float_to_unsigned (
+ arg : in UNRESOLVED_float; -- floating point input
+ variable sign : out STD_ULOGIC; -- sign of output
+ variable frac : out UNSIGNED; -- unsigned biased output
+ constant denormalize : in BOOLEAN; -- turn on denormalization
+ constant bias : in NATURAL; -- bias for fixed point
+ constant round_style : in com_round_type) is -- rounding method
+ constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction
+ constant exponent_width : INTEGER := arg'high; -- length of FP output exponent
+ variable fract : UNSIGNED (frac'range); -- internal version of frac
+ variable isign : STD_ULOGIC; -- internal version of sign
+ variable exp : INTEGER; -- Exponent
+ variable expon : SIGNED (exponent_width-1 downto 0); -- Vectorized exp
+ -- Base to divide fraction by
+ variable frac_shift : UNSIGNED (frac'high+3 downto 0); -- Fraction shifted
+ variable shift : INTEGER;
+ variable remainder : UNSIGNED (2 downto 0);
+ variable round : STD_ULOGIC; -- round BIT
+ begin
+ isign := to_x01(arg(arg'high));
+ -- exponent /= '0', normal floating point
+ expon := to_01(SIGNED(arg (exponent_width-1 downto 0)), 'X');
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ exp := to_integer (expon);
+ -- Figure out the fraction
+ fract := (others => '0'); -- fill with zero
+ fract (fract'high) := '1'; -- Add the "1.0".
+ shift := (fract'high-1) - exp;
+ if fraction_width > fract'high then -- Can only use size-2 bits
+ fract (fract'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto
+ -fract'high)));
+ else -- can use all bits
+ fract (fract'high-1 downto fract'high-fraction_width) :=
+ UNSIGNED (to_slv (arg(-1 downto -fraction_width)));
+ end if;
+ frac_shift := fract & "000";
+ if shift < 0 then -- Overflow
+ fract := (others => '1');
+ else
+ frac_shift := shift_right (frac_shift, shift);
+ fract := frac_shift (frac_shift'high downto 3);
+ remainder := frac_shift (2 downto 0);
+ -- round (round_zero will bypass this and truncate)
+ case round_style is
+ when round_nearest =>
+ round := remainder(2) and
+ (fract (0) or (or_reduce (remainder (1 downto 0))));
+ when round_inf =>
+ round := remainder(2) and not isign;
+ when round_neginf =>
+ round := remainder(2) and isign;
+ when others =>
+ round := '0';
+ end case;
+ if round = '1' then
+ fract := fract + 1;
+ end if;
+ end if;
+ frac := fract;
+ sign := isign;
+ end procedure float_to_unsigned;
+
+ -- purpose: returns a part of a vector, this function is here because
+ -- or (fractr (to_integer(shiftx) downto 0));
+ -- can't be synthesized in some synthesis tools.
+ function smallfract (
+ arg : UNSIGNED;
+ shift : NATURAL)
+ return STD_ULOGIC is
+ variable orx : STD_ULOGIC;
+ begin
+ orx := arg(shift);
+ for i in arg'range loop
+ if i < shift then
+ orx := arg(i) or orx;
+ end if;
+ end loop;
+ return orx;
+ end function smallfract;
+ ---------------------------------------------------------------------------
+ -- Visible functions
+ ---------------------------------------------------------------------------
+
+ -- purpose: converts the negative index to a positive one
+ -- negative indices are illegal in 1164 and 1076.3
+ function to_sulv (
+ arg : UNRESOLVED_float) -- fp vector
+ return STD_ULOGIC_VECTOR is
+ variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0);
+ begin -- function to_std_ulogic_vector
+ if arg'length < 1 then
+ return NSLV;
+ end if;
+ result := STD_ULOGIC_VECTOR (arg);
+ return result;
+ end function to_sulv;
+
+ -- Converts an fp into an SLV
+ function to_slv (arg : UNRESOLVED_float) return STD_LOGIC_VECTOR is
+ begin
+ return to_stdlogicvector (to_sulv (arg));
+ end function to_slv;
+
+ -- purpose: normalizes a floating point number
+ -- This version assumes an "unsigned" input with
+ function normalize (
+ fract : UNSIGNED; -- fraction, unnormalized
+ expon : SIGNED; -- exponent, normalized by -1
+ sign : STD_ULOGIC; -- sign BIT
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float is
+ variable sfract : UNSIGNED (fract'high downto 0); -- shifted fraction
+ variable rfract : UNSIGNED (fraction_width-1 downto 0); -- fraction
+ variable exp : SIGNED (exponent_width+1 downto 0); -- exponent
+ variable rexp : SIGNED (exponent_width+1 downto 0); -- result exponent
+ variable rexpon : UNSIGNED (exponent_width-1 downto 0); -- exponent
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width); -- result
+ variable shiftr : INTEGER; -- shift amount
+ variable stickyx : STD_ULOGIC; -- version of sticky
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable round, zerores, infres : BOOLEAN;
+ begin -- function normalize
+ zerores := false;
+ infres := false;
+ round := false;
+ shiftr := find_leftmost (to_01(fract), '1') -- Find the first "1"
+ - fraction_width - nguard; -- subtract the length we want
+ exp := resize (expon, exp'length) + shiftr;
+ if (or_reduce (fract) = '0') then -- Zero
+ zerores := true;
+ elsif ((exp <= -resize(expon_base, exp'length)-1) and denormalize)
+ or ((exp < -resize(expon_base, exp'length)-1) and not denormalize) then
+ if (exp >= -resize(expon_base, exp'length)-fraction_width-1)
+ and denormalize then
+ exp := -resize(expon_base, exp'length)-1;
+ shiftr := -to_integer (expon + expon_base); -- new shift
+ else -- return zero
+ zerores := true;
+ end if;
+ elsif (exp > expon_base-1) then -- infinity
+ infres := true;
+ end if;
+ if zerores then
+ result := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif infres then
+ result := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ sfract := fract srl shiftr; -- shift
+ if shiftr > 0 then
+-- stickyx := sticky or (or_reduce(fract (shiftr-1 downto 0)));
+ stickyx := sticky or smallfract (fract, shiftr-1);
+ else
+ stickyx := sticky;
+ end if;
+ if nguard > 0 then
+ round := check_round (
+ fract_in => sfract (nguard),
+ sign => sign,
+ remainder => sfract(nguard-1 downto 0),
+ sticky => stickyx,
+ round_style => round_style);
+ end if;
+ if round then
+ fp_round(fract_in => sfract (fraction_width-1+nguard downto nguard),
+ expon_in => exp(rexp'range),
+ fract_out => rfract,
+ expon_out => rexp);
+ else
+ rfract := sfract (fraction_width-1+nguard downto nguard);
+ rexp := exp(rexp'range);
+ end if;
+ -- result
+ rexpon := UNSIGNED (rexp(exponent_width-1 downto 0));
+ rexpon (exponent_width-1) := not rexpon(exponent_width-1);
+ result (rexpon'range) := UNRESOLVED_float(rexpon);
+ result (-1 downto -fraction_width) := UNRESOLVED_float(rfract);
+ end if;
+ result (exponent_width) := sign; -- sign BIT
+ return result;
+ end function normalize;
+
+ -- purpose: normalizes a floating point number
+ -- This version assumes a "ufixed" input
+ function normalize (
+ fract : ufixed; -- unsigned fixed point
+ expon : SIGNED; -- exponent, normalized by -1
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable arguns : UNSIGNED (fract'high + fraction_width + nguard
+ downto 0) := (others => '0');
+ begin -- function normalize
+ arguns (arguns'high downto maximum (arguns'high-fract'length+1, 0)) :=
+ UNSIGNED (to_slv (fract));
+ result := normalize (fract => arguns,
+ expon => expon,
+ sign => sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => nguard);
+ return result;
+ end function normalize;
+
+ -- purpose: normalizes a floating point number
+ -- This version assumes a "ufixed" input with a "size_res" input
+ function normalize (
+ fract : ufixed; -- unsigned fixed point
+ expon : SIGNED; -- exponent, normalized by -1
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ size_res : UNRESOLVED_float; -- used for sizing only
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := -size_res'low;
+ constant exponent_width : NATURAL := size_res'high;
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable arguns : UNSIGNED (fract'high + fraction_width + nguard
+ downto 0) := (others => '0');
+ begin -- function normalize
+ arguns (arguns'high downto maximum (arguns'high-fract'length+1, 0)) :=
+ UNSIGNED (to_slv (fract));
+ result := normalize (fract => arguns,
+ expon => expon,
+ sign => sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => nguard);
+ return result;
+ end function normalize;
+
+ -- Regular "normalize" function with a "size_res" input.
+ function normalize (
+ fract : UNSIGNED; -- unsigned
+ expon : SIGNED; -- exponent - 1, normalized
+ sign : STD_ULOGIC; -- sign bit
+ sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding)
+ size_res : UNRESOLVED_float; -- used for sizing only
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant nguard : NATURAL := float_guard_bits) -- guard bits
+ return UNRESOLVED_float is
+ begin
+ return normalize (fract => fract,
+ expon => expon,
+ sign => sign,
+ sticky => sticky,
+ fraction_width => -size_res'low,
+ exponent_width => size_res'high,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => nguard);
+ end function normalize;
+
+ -- Returns the class which X falls into
+ function Classfp (
+ x : UNRESOLVED_float; -- floating point input
+ check_error : BOOLEAN := float_check_error) -- check for errors
+ return valid_fpstate is
+ constant fraction_width : INTEGER := -mine(x'low, x'low); -- length of FP output fraction
+ constant exponent_width : INTEGER := x'high; -- length of FP output exponent
+ variable arg : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- classfp
+ if (arg'length < 1 or fraction_width < 3 or exponent_width < 3
+ or x'left < x'right) then
+ report float_pkg'instance_name
+ & "CLASSFP: " &
+ "Floating point number detected with a bad range"
+ severity error;
+ return isx;
+ end if;
+ -- Check for "X".
+ arg := to_01 (x, 'X');
+ if (arg(0) = 'X') then
+ return isx; -- If there is an X in the number
+ -- Special cases, check for illegal number
+ elsif check_error and
+ (and_reduce (STD_ULOGIC_VECTOR (arg (exponent_width-1 downto 0)))
+ = '1') then -- Exponent is all "1".
+ if or_reduce (to_slv (arg (-1 downto -fraction_width)))
+ /= '0' then -- Fraction must be all "0" or this is not a number.
+ if (arg(-1) = '1') then -- From "W. Khan - IEEE standard
+ return nan; -- 754 binary FP Signaling nan (Not a number)
+ else
+ return quiet_nan;
+ end if;
+ -- Check for infinity
+ elsif arg(exponent_width) = '0' then
+ return pos_inf; -- Positive infinity
+ else
+ return neg_inf; -- Negative infinity
+ end if;
+ -- check for "0"
+ elsif or_reduce (STD_LOGIC_VECTOR (arg (exponent_width-1 downto 0)))
+ = '0' then -- Exponent is all "0"
+ if or_reduce (to_slv (arg (-1 downto -fraction_width)))
+ = '0' then -- Fraction is all "0"
+ if arg(exponent_width) = '0' then
+ return pos_zero; -- Zero
+ else
+ return neg_zero;
+ end if;
+ else
+ if arg(exponent_width) = '0' then
+ return pos_denormal; -- Denormal number (ieee extended fp)
+ else
+ return neg_denormal;
+ end if;
+ end if;
+ else
+ if arg(exponent_width) = '0' then
+ return pos_normal; -- Normal FP number
+ else
+ return neg_normal;
+ end if;
+ end if;
+ end function Classfp;
+
+ procedure break_number (
+ arg : in UNRESOLVED_float;
+ denormalize : in BOOLEAN := float_denormalize;
+ check_error : in BOOLEAN := float_check_error;
+ fract : out UNSIGNED;
+ expon : out SIGNED;
+ sign : out STD_ULOGIC) is
+ constant fraction_width : NATURAL := -mine(arg'low, arg'low); -- length of FP output fraction
+ variable fptyp : valid_fpstate;
+ begin
+ fptyp := Classfp (arg, check_error);
+ sign := to_x01(arg(arg'high));
+ break_number (
+ arg => arg,
+ fptyp => fptyp,
+ denormalize => denormalize,
+ fract => fract,
+ expon => expon);
+ end procedure break_number;
+
+ procedure break_number (
+ arg : in UNRESOLVED_float;
+ denormalize : in BOOLEAN := float_denormalize;
+ check_error : in BOOLEAN := float_check_error;
+ fract : out ufixed; -- 1 downto -fraction_width
+ expon : out SIGNED; -- exponent_width-1 downto 0
+ sign : out STD_ULOGIC) is
+ constant fraction_width : NATURAL := -mine(arg'low, arg'low); -- length of FP output fraction
+ variable fptyp : valid_fpstate;
+ variable ufract : UNSIGNED (fraction_width downto 0); -- unsigned fraction
+ begin
+ fptyp := Classfp (arg, check_error);
+ sign := to_x01(arg(arg'high));
+ break_number (
+ arg => arg,
+ fptyp => fptyp,
+ denormalize => denormalize,
+ fract => ufract,
+ expon => expon);
+ fract (0 downto -fraction_width) := ufixed (ufract);
+ end procedure break_number;
+
+ -- Arithmetic functions
+ function "abs" (
+ arg : UNRESOLVED_float) -- floating point input
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (arg'range); -- result
+ begin
+ if (arg'length > 0) then
+ result := to_01 (arg, 'X');
+ result (arg'high) := '0'; -- set the sign bit to positive
+ return result;
+ else
+ return NAFP;
+ end if;
+ end function "abs";
+
+ -- IEEE 754 "negative" function
+ function "-" (
+ arg : UNRESOLVED_float) -- floating point input
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (arg'range); -- result
+ begin
+ if (arg'length > 0) then
+ result := to_01 (arg, 'X');
+ result (arg'high) := not result (arg'high); -- invert sign bit
+ return result;
+ else
+ return NAFP;
+ end if;
+ end function "-";
+
+ -- Addition, adds two floating point numbers
+ function add (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ constant addguard : NATURAL := guard; -- add one guard bit
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable fractl, fractr : UNSIGNED (fraction_width+1+addguard downto 0); -- fractions
+ variable fractc, fracts : UNSIGNED (fractl'range); -- constant and shifted variables
+ variable urfract, ulfract : UNSIGNED (fraction_width downto 0);
+ variable ufract : UNSIGNED (fraction_width+1+addguard downto 0);
+ variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable rexpon : SIGNED (exponent_width downto 0); -- result exponent
+ variable shiftx : SIGNED (exponent_width downto 0); -- shift fractions
+ variable sign : STD_ULOGIC; -- sign of the output
+ variable leftright : BOOLEAN; -- left or right used
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable sticky : STD_ULOGIC; -- Holds precision for rounding
+ begin -- addition
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := classfp (l, check_error);
+ rfptype := classfp (r, check_error);
+ end if;
+ if (lfptype = isx or rfptype = isx) then
+ fpresult := (others => 'X');
+ elsif (lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan)
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ or (lfptype = pos_inf and rfptype = neg_inf)
+ or (lfptype = neg_inf and rfptype = pos_inf) then
+ -- Return quiet NAN, IEEE754-1985-7.1,2
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (lfptype = pos_inf or rfptype = pos_inf) then -- x + inf = inf
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (lfptype = neg_inf or rfptype = neg_inf) then -- x - inf = -inf
+ fpresult := neg_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (lfptype = neg_zero and rfptype = neg_zero) then -- -0 + -0 = -0
+ fpresult := neg_zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ lresize := resize (arg => to_x01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_x01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := classfp (rresize, false); -- errors already checked
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => ulfract,
+ expon => exponl);
+ fractl := (others => '0');
+ fractl (fraction_width+addguard downto addguard) := ulfract;
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => urfract,
+ expon => exponr);
+ fractr := (others => '0');
+ fractr (fraction_width+addguard downto addguard) := urfract;
+ shiftx := (exponl(exponent_width-1) & exponl) - exponr;
+ if shiftx < -fractl'high then
+ rexpon := exponr(exponent_width-1) & exponr;
+ fractc := fractr;
+ fracts := (others => '0'); -- add zero
+ leftright := false;
+ sticky := or_reduce (fractl);
+ elsif shiftx < 0 then
+ shiftx := - shiftx;
+ fracts := shift_right (fractl, to_integer(shiftx));
+ fractc := fractr;
+ rexpon := exponr(exponent_width-1) & exponr;
+ leftright := false;
+-- sticky := or_reduce (fractl (to_integer(shiftx) downto 0));
+ sticky := smallfract (fractl, to_integer(shiftx));
+ elsif shiftx = 0 then
+ rexpon := exponl(exponent_width-1) & exponl;
+ sticky := '0';
+ if fractr > fractl then
+ fractc := fractr;
+ fracts := fractl;
+ leftright := false;
+ else
+ fractc := fractl;
+ fracts := fractr;
+ leftright := true;
+ end if;
+ elsif shiftx > fractr'high then
+ rexpon := exponl(exponent_width-1) & exponl;
+ fracts := (others => '0'); -- add zero
+ fractc := fractl;
+ leftright := true;
+ sticky := or_reduce (fractr);
+ elsif shiftx > 0 then
+ fracts := shift_right (fractr, to_integer(shiftx));
+ fractc := fractl;
+ rexpon := exponl(exponent_width-1) & exponl;
+ leftright := true;
+-- sticky := or_reduce (fractr (to_integer(shiftx) downto 0));
+ sticky := smallfract (fractr, to_integer(shiftx));
+ end if;
+ -- add
+ fracts (0) := fracts (0) or sticky; -- Or the sticky bit into the LSB
+ if l(l'high) = r(r'high) then
+ ufract := fractc + fracts;
+ sign := l(l'high);
+ else -- signs are different
+ ufract := fractc - fracts; -- always positive result
+ if leftright then -- Figure out which sign to use
+ sign := l(l'high);
+ else
+ sign := r(r'high);
+ end if;
+ end if;
+ if or_reduce (ufract) = '0' then
+ sign := '0'; -- IEEE 854, 6.3, paragraph 2.
+ end if;
+ -- normalize
+ fpresult := normalize (fract => ufract,
+ expon => rexpon,
+ sign => sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => addguard);
+ end if;
+ return fpresult;
+ end function add;
+
+ -- Subtraction, Calls "add".
+ function subtract (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ variable negr : UNRESOLVED_float (r'range); -- negative version of r
+ begin
+ negr := -r;
+ return add (l => l,
+ r => negr,
+ round_style => round_style,
+ guard => guard,
+ check_error => check_error,
+ denormalize => denormalize);
+ end function subtract;
+
+ -- Floating point multiply
+ function multiply (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ constant multguard : NATURAL := guard; -- guard bits
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable fractl, fractr : UNSIGNED (fraction_width downto 0); -- fractions
+ variable rfract : UNSIGNED ((2*(fraction_width))+1 downto 0); -- result fraction
+ variable sfract : UNSIGNED (fraction_width+1+multguard downto 0); -- result fraction
+ variable shifty : INTEGER; -- denormal shift
+ variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable rexpon : SIGNED (exponent_width+1 downto 0); -- result exponent
+ variable fp_sign : STD_ULOGIC; -- sign of result
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable sticky : STD_ULOGIC; -- Holds precision for rounding
+ begin -- multiply
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := classfp (l, check_error);
+ rfptype := classfp (r, check_error);
+ end if;
+ if (lfptype = isx or rfptype = isx) then
+ fpresult := (others => 'X');
+ elsif ((lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan)) then
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (((lfptype = pos_inf or lfptype = neg_inf) and
+ (rfptype = pos_zero or rfptype = neg_zero)) or
+ ((rfptype = pos_inf or rfptype = neg_inf) and
+ (lfptype = pos_zero or lfptype = neg_zero))) then -- 0 * inf
+ -- Return quiet NAN, IEEE754-1985-7.1,3
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (lfptype = pos_inf or rfptype = pos_inf
+ or lfptype = neg_inf or rfptype = neg_inf) then -- x * inf = inf
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ -- figure out the sign
+ fp_sign := l(l'high) xor r(r'high); -- figure out the sign
+ fpresult (exponent_width) := fp_sign;
+ else
+ fp_sign := l(l'high) xor r(r'high); -- figure out the sign
+ lresize := resize (arg => to_x01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_x01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := classfp (rresize, false); -- errors already checked
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => fractl,
+ expon => exponl);
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => fractr,
+ expon => exponr);
+ if (rfptype = pos_denormal or rfptype = neg_denormal) then
+ shifty := fraction_width - find_leftmost(fractr, '1');
+ fractr := shift_left (fractr, shifty);
+ elsif (lfptype = pos_denormal or lfptype = neg_denormal) then
+ shifty := fraction_width - find_leftmost(fractl, '1');
+ fractl := shift_left (fractl, shifty);
+ else
+ shifty := 0;
+ -- Note that a denormal number * a denormal number is always zero.
+ end if;
+ -- multiply
+ -- add the exponents
+ rexpon := resize (exponl, rexpon'length) + exponr - shifty + 1;
+ rfract := fractl * fractr; -- Multiply the fraction
+ sfract := rfract (rfract'high downto
+ rfract'high - (fraction_width+1+multguard));
+ sticky := or_reduce (rfract (rfract'high-(fraction_width+1+multguard)
+ downto 0));
+ -- normalize
+ fpresult := normalize (fract => sfract,
+ expon => rexpon,
+ sign => fp_sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => multguard);
+ end if;
+ return fpresult;
+ end function multiply;
+
+ function short_divide (
+ lx, rx : UNSIGNED)
+ return UNSIGNED is
+ -- This is a special divider for the floating point routines.
+ -- For a true unsigned divider, "stages" needs to = lx'high
+ constant stages : INTEGER := lx'high - rx'high; -- number of stages
+ variable partial : UNSIGNED (lx'range);
+ variable q : UNSIGNED (stages downto 0);
+ variable partial_argl : SIGNED (rx'high + 2 downto 0);
+ variable partial_arg : SIGNED (rx'high + 2 downto 0);
+ begin
+ partial := lx;
+ for i in stages downto 0 loop
+ partial_argl := resize ("0" & SIGNED (partial(lx'high downto i)),
+ partial_argl'length);
+ partial_arg := partial_argl - SIGNED ("0" & rx);
+ if (partial_arg (partial_arg'high) = '1') then -- negative
+ q(i) := '0';
+ else
+ q(i) := '1';
+ partial (lx'high+i-stages downto lx'high+i-stages-rx'high) :=
+ UNSIGNED (partial_arg(rx'range));
+ end if;
+ end loop;
+ -- to make the output look like that of the unsigned IEEE divide.
+ return resize (q, lx'length);
+ end function short_divide;
+
+ -- 1/X function. Needed for algorithm development.
+ function reciprocal (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := -mine(arg'low, arg'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := arg'high; -- length of FP output exponent
+ constant divguard : NATURAL := guard; -- guard bits
+ function onedivy (
+ arg : UNSIGNED)
+ return UNSIGNED is
+ variable q : UNSIGNED((2*arg'high)+1 downto 0);
+ variable one : UNSIGNED (q'range);
+ begin
+ one := (others => '0');
+ one(one'high) := '1';
+ q := short_divide (one, arg); -- Unsigned divide
+ return resize (q, arg'length+1);
+ end function onedivy;
+ variable fptype : valid_fpstate;
+ variable expon : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable denorm_offset : NATURAL range 0 to 2;
+ variable fract : UNSIGNED (fraction_width downto 0);
+ variable fractg : UNSIGNED (fraction_width+divguard downto 0);
+ variable sfract : UNSIGNED (fraction_width+1+divguard downto 0); -- result fraction
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- reciprocal
+ fptype := classfp(arg, check_error);
+ classcase : case fptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf | neg_inf => -- 1/inf, return 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when neg_zero | pos_zero => -- 1/0
+ report float_pkg'instance_name
+ & "RECIPROCAL: Floating Point divide by zero"
+ severity error;
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when others =>
+ if (fptype = pos_denormal or fptype = neg_denormal)
+ and ((arg (-1) or arg(-2)) /= '1') then
+ -- 1/denormal = infinity, with the exception of 2**-expon_base
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fpresult (exponent_width) := to_x01 (arg (exponent_width));
+ else
+ break_number (
+ arg => arg,
+ fptyp => fptype,
+ denormalize => denormalize,
+ fract => fract,
+ expon => expon);
+ fractg := (others => '0');
+ if (fptype = pos_denormal or fptype = neg_denormal) then
+ -- The reciprocal of a denormal number is typically zero,
+ -- except for two special cases which are trapped here.
+ if (to_x01(arg (-1)) = '1') then
+ fractg (fractg'high downto divguard+1) :=
+ fract (fract'high-1 downto 0); -- Shift to not denormal
+ denorm_offset := 1; -- add 1 to exponent compensate
+ else -- arg(-2) = '1'
+ fractg (fractg'high downto divguard+2) :=
+ fract (fract'high-2 downto 0); -- Shift to not denormal
+ denorm_offset := 2; -- add 2 to exponent compensate
+ end if;
+ else
+ fractg (fractg'high downto divguard) := fract;
+ denorm_offset := 0;
+ end if;
+ expon := - expon - 3 + denorm_offset;
+ sfract := onedivy (fractg);
+ -- normalize
+ fpresult := normalize (fract => sfract,
+ expon => expon,
+ sign => arg(exponent_width),
+ sticky => '1',
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => divguard);
+ end if;
+ end case classcase;
+ return fpresult;
+ end function reciprocal;
+
+ -- floating point division
+ function divide (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ constant divguard : NATURAL := guard; -- division guard bits
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable ulfract, urfract : UNSIGNED (fraction_width downto 0);
+ variable fractl : UNSIGNED ((2*(fraction_width+divguard)+1) downto 0); -- left
+ variable fractr : UNSIGNED (fraction_width+divguard downto 0); -- right
+ variable rfract : UNSIGNED (fractl'range); -- result fraction
+ variable sfract : UNSIGNED (fraction_width+1+divguard downto 0); -- result fraction
+ variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable rexpon : SIGNED (exponent_width+1 downto 0); -- result exponent
+ variable fp_sign, sticky : STD_ULOGIC; -- sign of result
+ variable shifty, shiftx : INTEGER; -- denormal number shift
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- divide
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := classfp (l, check_error);
+ rfptype := classfp (r, check_error);
+ end if;
+ classcase : case rfptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf | neg_inf =>
+ if lfptype = pos_inf or lfptype = neg_inf -- inf / inf
+ or lfptype = quiet_nan or lfptype = nan then
+ -- Return quiet NAN, IEEE754-1985-7.1,4
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else -- x / inf = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (fpresult'high) := fp_sign; -- sign
+ end if;
+ when pos_zero | neg_zero =>
+ if lfptype = pos_zero or lfptype = neg_zero -- 0 / 0
+ or lfptype = quiet_nan or lfptype = nan then
+ -- Return quiet NAN, IEEE754-1985-7.1,4
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ report float_pkg'instance_name
+ & "DIVIDE: Floating Point divide by zero"
+ severity error;
+ -- Infinity, define in 754-1985-7.2
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (fpresult'high) := fp_sign; -- sign
+ end if;
+ when others =>
+ classcase2 : case lfptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf | neg_inf => -- inf / x = inf
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult(exponent_width) := fp_sign;
+ when pos_zero | neg_zero => -- 0 / X = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult(exponent_width) := fp_sign;
+ when others =>
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ lresize := resize (arg => to_x01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_x01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := classfp (rresize, false); -- errors already checked
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => ulfract,
+ expon => exponl);
+ -- right side
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => urfract,
+ expon => exponr);
+ -- Compute the exponent
+ rexpon := resize (exponl, rexpon'length) - exponr - 2;
+ if (rfptype = pos_denormal or rfptype = neg_denormal) then
+ -- Do the shifting here not after. That way we have a smaller
+ -- shifter, and need a smaller divider, because the top
+ -- bit in the divisor will always be a "1".
+ shifty := fraction_width - find_leftmost(urfract, '1');
+ urfract := shift_left (urfract, shifty);
+ rexpon := rexpon + shifty;
+ end if;
+ fractr := (others => '0');
+ fractr (fraction_width+divguard downto divguard) := urfract;
+ if (lfptype = pos_denormal or lfptype = neg_denormal) then
+ shiftx := fraction_width - find_leftmost(ulfract, '1');
+ ulfract := shift_left (ulfract, shiftx);
+ rexpon := rexpon - shiftx;
+ end if;
+ fractl := (others => '0');
+ fractl (fractl'high downto fractl'high-fraction_width) := ulfract;
+ -- divide
+ rfract := short_divide (fractl, fractr); -- unsigned divide
+ sfract := rfract (sfract'range); -- lower bits
+ sticky := '1';
+ -- normalize
+ fpresult := normalize (fract => sfract,
+ expon => rexpon,
+ sign => fp_sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => divguard);
+ end case classcase2;
+ end case classcase;
+ return fpresult;
+ end function divide;
+
+ -- division by a power of 2
+ function dividebyp2 (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable ulfract, urfract : UNSIGNED (fraction_width downto 0);
+ variable exponl, exponr : SIGNED(exponent_width-1 downto 0); -- exponents
+ variable rexpon : SIGNED(exponent_width downto 0); -- result exponent
+ variable fp_sign : STD_ULOGIC; -- sign of result
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- divisionbyp2
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := classfp (l, check_error);
+ rfptype := classfp (r, check_error);
+ end if;
+ classcase : case rfptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf | neg_inf =>
+ if lfptype = pos_inf or lfptype = neg_inf then -- inf / inf
+ -- Return quiet NAN, IEEE754-1985-7.1,4
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else -- x / inf = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (fpresult'high) := fp_sign; -- sign
+ end if;
+ when pos_zero | neg_zero =>
+ if lfptype = pos_zero or lfptype = neg_zero then -- 0 / 0
+ -- Return quiet NAN, IEEE754-1985-7.1,4
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ report float_pkg'instance_name
+ & "DIVIDEBYP2: Floating Point divide by zero"
+ severity error;
+ -- Infinity, define in 754-1985-7.2
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (fpresult'high) := fp_sign; -- sign
+ end if;
+ when others =>
+ classcase2 : case lfptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf | neg_inf => -- inf / x = inf
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (exponent_width) := fp_sign; -- sign
+ when pos_zero | neg_zero => -- 0 / X = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ fpresult (exponent_width) := fp_sign; -- sign
+ when others =>
+ fp_sign := l(l'high) xor r(r'high); -- sign
+ lresize := resize (arg => to_x01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_x01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := classfp (rresize, false); -- errors already checked
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => ulfract,
+ expon => exponl);
+ -- right side
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => urfract,
+ expon => exponr);
+ assert (or_reduce (urfract (fraction_width-1 downto 0)) = '0')
+ report float_pkg'instance_name
+ & "DIVIDEBYP2: "
+ & "Dividebyp2 called with a non power of two divisor"
+ severity error;
+ rexpon := (exponl(exponl'high)&exponl)
+ - (exponr(exponr'high)&exponr) - 1;
+ -- normalize
+ fpresult := normalize (fract => ulfract,
+ expon => rexpon,
+ sign => fp_sign,
+ sticky => '1',
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => 0);
+ end case classcase2;
+ end case classcase;
+ return fpresult;
+ end function dividebyp2;
+
+ -- Multiply accumulate result = l*r + c
+ function mac (
+ l, r, c : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL :=
+ -mine (mine(l'low, r'low), c'low); -- length of FP output fraction
+ constant exponent_width : NATURAL :=
+ maximum (maximum(l'high, r'high), c'high); -- length of FP output exponent
+ variable lfptype, rfptype, cfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable fractl, fractr : UNSIGNED (fraction_width downto 0); -- fractions
+ variable fractx : UNSIGNED (fraction_width+guard downto 0);
+ variable fractc, fracts : UNSIGNED (fraction_width+1+guard downto 0);
+ variable rfract : UNSIGNED ((2*(fraction_width))+1 downto 0); -- result fraction
+ variable sfract, ufract : UNSIGNED (fraction_width+1+guard downto 0); -- result fraction
+ variable exponl, exponr, exponc : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable rexpon, rexpon2 : SIGNED (exponent_width+1 downto 0); -- result exponent
+ variable shifty : INTEGER; -- denormal shift
+ variable shiftx : SIGNED (rexpon'range); -- shift fractions
+ variable fp_sign : STD_ULOGIC; -- sign of result
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable cresize : UNRESOLVED_float (exponent_width downto -fraction_width - guard);
+ variable leftright : BOOLEAN; -- left or right used
+ variable sticky : STD_ULOGIC; -- Holds precision for rounding
+ begin -- multiply
+ if (fraction_width = 0 or l'length < 7 or r'length < 7 or c'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := classfp (l, check_error);
+ rfptype := classfp (r, check_error);
+ cfptype := classfp (c, check_error);
+ end if;
+ if (lfptype = isx or rfptype = isx or cfptype = isx) then
+ fpresult := (others => 'X');
+ elsif (lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan or
+ cfptype = nan or cfptype = quiet_nan) then
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (((lfptype = pos_inf or lfptype = neg_inf) and
+ (rfptype = pos_zero or rfptype = neg_zero)) or
+ ((rfptype = pos_inf or rfptype = neg_inf) and
+ (lfptype = pos_zero or lfptype = neg_zero))) then -- 0 * inf
+ -- Return quiet NAN, IEEE754-1985-7.1,3
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (lfptype = pos_inf or rfptype = pos_inf
+ or lfptype = neg_inf or rfptype = neg_inf -- x * inf = inf
+ or cfptype = neg_inf or cfptype = pos_inf) then -- x + inf = inf
+ fpresult := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ -- figure out the sign
+ fpresult (exponent_width) := l(l'high) xor r(r'high);
+ else
+ fp_sign := l(l'high) xor r(r'high); -- figure out the sign
+ lresize := resize (arg => to_x01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_x01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := classfp (rresize, false); -- errors already checked
+ cresize := resize (arg => to_x01(c),
+ exponent_width => exponent_width,
+ fraction_width => -cresize'low,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ cfptype := classfp (cresize, false); -- errors already checked
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => fractl,
+ expon => exponl);
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => fractr,
+ expon => exponr);
+ break_number (
+ arg => cresize,
+ fptyp => cfptype,
+ denormalize => denormalize,
+ fract => fractx,
+ expon => exponc);
+ if (rfptype = pos_denormal or rfptype = neg_denormal) then
+ shifty := fraction_width - find_leftmost(fractr, '1');
+ fractr := shift_left (fractr, shifty);
+ elsif (lfptype = pos_denormal or lfptype = neg_denormal) then
+ shifty := fraction_width - find_leftmost(fractl, '1');
+ fractl := shift_left (fractl, shifty);
+ else
+ shifty := 0;
+ -- Note that a denormal number * a denormal number is always zero.
+ end if;
+ -- multiply
+ rfract := fractl * fractr; -- Multiply the fraction
+ -- add the exponents
+ rexpon := resize (exponl, rexpon'length) + exponr - shifty + 1;
+ shiftx := rexpon - exponc;
+ if shiftx < -fractl'high then
+ rexpon2 := resize (exponc, rexpon2'length);
+ fractc := "0" & fractx;
+ fracts := (others => '0');
+ sticky := or_reduce (rfract);
+ elsif shiftx < 0 then
+ shiftx := - shiftx;
+ fracts := shift_right (rfract (rfract'high downto rfract'high
+ - fracts'length+1),
+ to_integer(shiftx));
+ fractc := "0" & fractx;
+ rexpon2 := resize (exponc, rexpon2'length);
+ leftright := false;
+ sticky := or_reduce (rfract (to_integer(shiftx)+rfract'high
+ - fracts'length downto 0));
+ elsif shiftx = 0 then
+ rexpon2 := resize (exponc, rexpon2'length);
+ sticky := or_reduce (rfract (rfract'high - fractc'length downto 0));
+ if rfract (rfract'high downto rfract'high - fractc'length+1) > fractx
+ then
+ fractc := "0" & fractx;
+ fracts := rfract (rfract'high downto rfract'high
+ - fracts'length+1);
+ leftright := false;
+ else
+ fractc := rfract (rfract'high downto rfract'high
+ - fractc'length+1);
+ fracts := "0" & fractx;
+ leftright := true;
+ end if;
+ elsif shiftx > fractx'high then
+ rexpon2 := rexpon;
+ fracts := (others => '0');
+ fractc := rfract (rfract'high downto rfract'high - fractc'length+1);
+ leftright := true;
+ sticky := or_reduce (fractx & rfract (rfract'high - fractc'length
+ downto 0));
+ else -- fractx'high > shiftx > 0
+ rexpon2 := rexpon;
+ fracts := "0" & shift_right (fractx, to_integer (shiftx));
+ fractc := rfract (rfract'high downto rfract'high - fractc'length+1);
+ leftright := true;
+ sticky := or_reduce (fractx (to_integer (shiftx) downto 0)
+ & rfract (rfract'high - fractc'length downto 0));
+ end if;
+ fracts (0) := fracts (0) or sticky; -- Or the sticky bit into the LSB
+ if fp_sign = to_X01(c(c'high)) then
+ ufract := fractc + fracts;
+ fp_sign := fp_sign;
+ else -- signs are different
+ ufract := fractc - fracts; -- always positive result
+ if leftright then -- Figure out which sign to use
+ fp_sign := fp_sign;
+ else
+ fp_sign := c(c'high);
+ end if;
+ end if;
+ -- normalize
+ fpresult := normalize (fract => ufract,
+ expon => rexpon2,
+ sign => fp_sign,
+ sticky => sticky,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => guard);
+ end if;
+ return fpresult;
+ end function mac;
+
+ -- "rem" function
+ function remainder (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ constant divguard : NATURAL := guard; -- division guard bits
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable ulfract, urfract : UNSIGNED (fraction_width downto 0);
+ variable fractr, fractl : UNSIGNED (fraction_width+divguard downto 0); -- right
+ variable rfract : UNSIGNED (fractr'range); -- result fraction
+ variable sfract : UNSIGNED (fraction_width+divguard downto 0); -- result fraction
+ variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents
+ variable rexpon : SIGNED (exponent_width downto 0); -- result exponent
+ variable fp_sign : STD_ULOGIC; -- sign of result
+ variable shifty : INTEGER; -- denormal number shift
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- remainder
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := classfp (l, check_error);
+ rfptype := classfp (r, check_error);
+ end if;
+ if (lfptype = isx or rfptype = isx) then
+ fpresult := (others => 'X');
+ elsif (lfptype = nan or lfptype = quiet_nan)
+ or (rfptype = nan or rfptype = quiet_nan)
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ or (lfptype = pos_inf or lfptype = neg_inf) -- inf rem x
+ -- Return quiet NAN, IEEE754-1985-7.1,5
+ or (rfptype = pos_zero or rfptype = neg_zero) then -- x rem 0
+ -- Return quiet NAN, IEEE754-1985-7.1,5
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (rfptype = pos_inf or rfptype = neg_inf) then -- x rem inf = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (abs(l) < abs(r)) then
+ fpresult := l;
+ else
+ fp_sign := to_X01(l(l'high)); -- sign
+ lresize := resize (arg => to_x01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ lfptype := classfp (lresize, false); -- errors already checked
+ rresize := resize (arg => to_x01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rfptype := classfp (rresize, false); -- errors already checked
+ fractl := (others => '0');
+ break_number (
+ arg => lresize,
+ fptyp => lfptype,
+ denormalize => denormalize,
+ fract => ulfract,
+ expon => exponl);
+ fractl (fraction_width+divguard downto divguard) := ulfract;
+ -- right side
+ fractr := (others => '0');
+ break_number (
+ arg => rresize,
+ fptyp => rfptype,
+ denormalize => denormalize,
+ fract => urfract,
+ expon => exponr);
+ fractr (fraction_width+divguard downto divguard) := urfract;
+ rexpon := (exponr(exponr'high)&exponr);
+ shifty := to_integer(exponl - rexpon);
+ if (shifty > 0) then
+ fractr := shift_right (fractr, shifty);
+ rexpon := rexpon + shifty;
+ end if;
+ if (fractr /= 0) then
+ -- rem
+ rfract := fractl rem fractr; -- unsigned rem
+ sfract := rfract (sfract'range); -- lower bits
+ -- normalize
+ fpresult := normalize (fract => sfract,
+ expon => rexpon,
+ sign => fp_sign,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => divguard);
+ else
+ -- If we shift "fractr" so far that it becomes zero, return zero.
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ end if;
+ end if;
+ return fpresult;
+ end function remainder;
+
+ -- "mod" function
+ function modulo (
+ l, r : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant guard : NATURAL := float_guard_bits; -- number of guard bits
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := - mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable remres : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- remainder
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ lfptype := isx;
+ else
+ lfptype := classfp (l, check_error);
+ rfptype := classfp (r, check_error);
+ end if;
+ if (lfptype = isx or rfptype = isx) then
+ fpresult := (others => 'X');
+ elsif (lfptype = nan or lfptype = quiet_nan)
+ or (rfptype = nan or rfptype = quiet_nan)
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ or (lfptype = pos_inf or lfptype = neg_inf) -- inf rem x
+ -- Return quiet NAN, IEEE754-1985-7.1,5
+ or (rfptype = pos_zero or rfptype = neg_zero) then -- x rem 0
+ -- Return quiet NAN, IEEE754-1985-7.1,5
+ fpresult := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (rfptype = pos_inf or rfptype = neg_inf) then -- x rem inf = 0
+ fpresult := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ remres := remainder (l => abs(l),
+ r => abs(r),
+ round_style => round_style,
+ guard => guard,
+ check_error => false,
+ denormalize => denormalize);
+ -- MOD is the same as REM, but you do something different with
+ -- negative values
+ if (is_negative (l)) then
+ remres := - remres;
+ end if;
+ if (is_negative (l) = is_negative (r) or remres = 0) then
+ fpresult := remres;
+ else
+ fpresult := add (l => remres,
+ r => r,
+ round_style => round_style,
+ guard => guard,
+ check_error => false,
+ denormalize => denormalize);
+ end if;
+ end if;
+ return fpresult;
+ end function modulo;
+
+ -- Square root of a floating point number. Done using Newton's Iteration.
+ function sqrt (
+ arg : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style;
+ constant guard : NATURAL := float_guard_bits;
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := guard-arg'low; -- length of FP output fraction
+ constant exponent_width : NATURAL := arg'high; -- length of FP output exponent
+ variable sign : STD_ULOGIC;
+ variable fpresult : float (arg'range);
+ variable fptype : valid_fpstate;
+ variable iexpon : SIGNED(exponent_width-1 downto 0); -- exponents
+ variable expon : SIGNED(exponent_width downto 0); -- exponents
+ variable ufact : ufixed (0 downto arg'low);
+ variable fact : ufixed (2 downto -fraction_width); -- fraction
+ variable resb : ufixed (fact'high+1 downto fact'low);
+ begin -- square root
+ fptype := Classfp (arg, check_error);
+ classcase : case fptype is
+ when isx =>
+ fpresult := (others => 'X');
+ when nan | quiet_nan |
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ neg_normal | neg_denormal | neg_inf => -- sqrt (neg)
+ -- Return quiet NAN, IEEE754-1985-7.1.6
+ fpresult := qnanfp (fraction_width => fraction_width-guard,
+ exponent_width => exponent_width);
+ when pos_inf => -- Sqrt (inf), return infinity
+ fpresult := pos_inffp (fraction_width => fraction_width-guard,
+ exponent_width => exponent_width);
+ when pos_zero => -- return 0
+ fpresult := zerofp (fraction_width => fraction_width-guard,
+ exponent_width => exponent_width);
+ when neg_zero => -- IEEE754-1985-6.3 return -0
+ fpresult := neg_zerofp (fraction_width => fraction_width-guard,
+ exponent_width => exponent_width);
+ when others =>
+ break_number (arg => arg,
+ denormalize => denormalize,
+ check_error => false,
+ fract => ufact,
+ expon => iexpon,
+ sign => sign);
+ expon := resize (iexpon+1, expon'length); -- get exponent
+ fact := resize (ufact, fact'high, fact'low);
+ if (expon(0) = '1') then
+ fact := fact sla 1; -- * 2.0
+ end if;
+ expon := shift_right (expon, 1); -- exponent/2
+ -- Newton's iteration - root := (1 + arg) / 2
+ resb := (fact + 1) sra 1;
+ for j in 0 to fraction_width/4 loop
+ -- root := (root + (arg/root))/2
+ resb := resize (arg => (resb + (fact/resb)) sra 1,
+ left_index => resb'high,
+ right_index => resb'low,
+ round_style => fixed_truncate,
+ overflow_style => fixed_wrap);
+ end loop;
+ fpresult := normalize (fract => resb,
+ expon => expon-1,
+ sign => '0',
+ exponent_width => arg'high,
+ fraction_width => -arg'low,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => guard);
+ end case classcase;
+ return fpresult;
+ end function sqrt;
+
+ function Is_Negative (arg : UNRESOLVED_float) return BOOLEAN is
+ -- Technically -0 should return "false", but I'm leaving that case out.
+ begin
+ return (to_x01(arg(arg'high)) = '1');
+ end function Is_Negative;
+
+ -- compare functions
+ -- =, /=, >=, <=, <, >
+
+ function eq ( -- equal =
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN is
+ variable lfptype, rfptype : valid_fpstate;
+ variable is_equal, is_unordered : BOOLEAN;
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- equal
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ return false;
+ else
+ lfptype := classfp (l, check_error);
+ rfptype := classfp (r, check_error);
+ end if;
+ if (lfptype = neg_zero or lfptype = pos_zero) and
+ (rfptype = neg_zero or rfptype = pos_zero) then
+ is_equal := true;
+ else
+ lresize := resize (arg => to_x01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rresize := resize (arg => to_x01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ is_equal := (to_slv(lresize) = to_slv(rresize));
+ end if;
+ if (check_error) then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return is_equal and not is_unordered;
+ end function eq;
+
+ function lt ( -- less than <
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable expl, expr : UNSIGNED (exponent_width-1 downto 0);
+ variable fractl, fractr : UNSIGNED (fraction_width-1 downto 0);
+ variable is_less_than, is_unordered : BOOLEAN;
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ is_less_than := false;
+ else
+ lresize := resize (arg => to_x01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rresize := resize (arg => to_x01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ if to_x01(l(l'high)) = to_x01(r(r'high)) then -- sign bits
+ expl := UNSIGNED(lresize(exponent_width-1 downto 0));
+ expr := UNSIGNED(rresize(exponent_width-1 downto 0));
+ if expl = expr then
+ fractl := UNSIGNED (to_slv(lresize(-1 downto -fraction_width)));
+ fractr := UNSIGNED (to_slv(rresize(-1 downto -fraction_width)));
+ if to_x01(l(l'high)) = '0' then -- positive number
+ is_less_than := (fractl < fractr);
+ else
+ is_less_than := (fractl > fractr); -- negative
+ end if;
+ else
+ if to_x01(l(l'high)) = '0' then -- positive number
+ is_less_than := (expl < expr);
+ else
+ is_less_than := (expl > expr); -- negative
+ end if;
+ end if;
+ else
+ lfptype := classfp (l, check_error);
+ rfptype := classfp (r, check_error);
+ if (lfptype = neg_zero and rfptype = pos_zero) then
+ is_less_than := false; -- -0 < 0 returns false.
+ else
+ is_less_than := (to_x01(l(l'high)) > to_x01(r(r'high)));
+ end if;
+ end if;
+ end if;
+ if check_error then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return is_less_than and not is_unordered;
+ end function lt;
+
+ function gt ( -- greater than >
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable expl, expr : UNSIGNED (exponent_width-1 downto 0);
+ variable fractl, fractr : UNSIGNED (fraction_width-1 downto 0);
+ variable is_greater_than : BOOLEAN;
+ variable is_unordered : BOOLEAN;
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- greater_than
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ is_greater_than := false;
+ else
+ lresize := resize (arg => to_x01(l),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ rresize := resize (arg => to_x01(r),
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => denormalize,
+ denormalize => denormalize);
+ if to_x01(l(l'high)) = to_x01(r(r'high)) then -- sign bits
+ expl := UNSIGNED(lresize(exponent_width-1 downto 0));
+ expr := UNSIGNED(rresize(exponent_width-1 downto 0));
+ if expl = expr then
+ fractl := UNSIGNED (to_slv(lresize(-1 downto -fraction_width)));
+ fractr := UNSIGNED (to_slv(rresize(-1 downto -fraction_width)));
+ if to_x01(l(l'high)) = '0' then -- positive number
+ is_greater_than := fractl > fractr;
+ else
+ is_greater_than := fractl < fractr; -- negative
+ end if;
+ else
+ if to_x01(l(l'high)) = '0' then -- positive number
+ is_greater_than := expl > expr;
+ else
+ is_greater_than := expl < expr; -- negative
+ end if;
+ end if;
+ else
+ lfptype := classfp (l, check_error);
+ rfptype := classfp (r, check_error);
+ if (lfptype = pos_zero and rfptype = neg_zero) then
+ is_greater_than := false; -- 0 > -0 returns false.
+ else
+ is_greater_than := to_x01(l(l'high)) < to_x01(r(r'high));
+ end if;
+ end if;
+ end if;
+ if check_error then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return is_greater_than and not is_unordered;
+ end function gt;
+
+ -- purpose: /= function
+ function ne ( -- not equal /=
+ l, r : UNRESOLVED_float;
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN is
+ variable is_equal, is_unordered : BOOLEAN;
+ begin
+ is_equal := eq (l => l,
+ r => r,
+ check_error => false,
+ denormalize => denormalize);
+ if check_error then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return not (is_equal and not is_unordered);
+ end function ne;
+
+ function le ( -- less than or equal to <=
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN is
+ variable is_greater_than, is_unordered : BOOLEAN;
+ begin
+ is_greater_than := gt (l => l,
+ r => r,
+ check_error => false,
+ denormalize => denormalize);
+ if check_error then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return not is_greater_than and not is_unordered;
+ end function le;
+
+ function ge ( -- greater than or equal to >=
+ l, r : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize : BOOLEAN := float_denormalize)
+ return BOOLEAN is
+ variable is_less_than, is_unordered : BOOLEAN;
+ begin
+ is_less_than := lt (l => l,
+ r => r,
+ check_error => false,
+ denormalize => denormalize);
+ if check_error then
+ is_unordered := Unordered (x => l,
+ y => r);
+ else
+ is_unordered := false;
+ end if;
+ return not is_less_than and not is_unordered;
+ end function ge;
+
+ function \?=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable is_equal, is_unordered : STD_ULOGIC;
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- ?=
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ return 'X';
+ else
+ lfptype := classfp (l, float_check_error);
+ rfptype := classfp (r, float_check_error);
+ end if;
+ if (lfptype = neg_zero or lfptype = pos_zero) and
+ (rfptype = neg_zero or rfptype = pos_zero) then
+ is_equal := '1';
+ else
+ lresize := resize (arg => l,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => float_denormalize,
+ denormalize => float_denormalize);
+ rresize := resize (arg => r,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => float_denormalize,
+ denormalize => float_denormalize);
+ is_equal := \?=\ (to_sulv(lresize), to_sulv(rresize));
+ end if;
+ if (float_check_error) then
+ if (lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan) then
+ is_unordered := '1';
+ else
+ is_unordered := '0';
+ end if;
+ else
+ is_unordered := '0';
+ end if;
+ return is_equal and not is_unordered;
+ end function \?=\;
+
+ function \?/=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lfptype, rfptype : valid_fpstate;
+ variable is_equal, is_unordered : STD_ULOGIC;
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- ?/=
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ return 'X';
+ else
+ lfptype := classfp (l, float_check_error);
+ rfptype := classfp (r, float_check_error);
+ end if;
+ if (lfptype = neg_zero or lfptype = pos_zero) and
+ (rfptype = neg_zero or rfptype = pos_zero) then
+ is_equal := '1';
+ else
+ lresize := resize (arg => l,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => float_denormalize,
+ denormalize => float_denormalize);
+ rresize := resize (arg => r,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ denormalize_in => float_denormalize,
+ denormalize => float_denormalize);
+ is_equal := \?=\ (to_sulv(lresize), to_sulv(rresize));
+ end if;
+ if (float_check_error) then
+ if (lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan) then
+ is_unordered := '1';
+ else
+ is_unordered := '0';
+ end if;
+ else
+ is_unordered := '0';
+ end if;
+ return not (is_equal and not is_unordered);
+ end function \?/=\;
+
+ function \?>\ (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(l'low, r'low);
+ variable founddash : BOOLEAN := false;
+ begin
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ return 'X';
+ else
+ for i in L'range loop
+ if L(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ for i in R'range loop
+ if R(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ if founddash then
+ report float_pkg'instance_name
+ & " ""?>"": '-' found in compare string"
+ severity error;
+ return 'X';
+ elsif is_x(l) or is_x(r) then
+ return 'X';
+ elsif l > r then
+ return '1';
+ else
+ return '0';
+ end if;
+ end if;
+ end function \?>\;
+
+ function \?>=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(l'low, r'low);
+ variable founddash : BOOLEAN := false;
+ begin
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ return 'X';
+ else
+ for i in L'range loop
+ if L(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ for i in R'range loop
+ if R(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ if founddash then
+ report float_pkg'instance_name
+ & " ""?>="": '-' found in compare string"
+ severity error;
+ return 'X';
+ elsif is_x(l) or is_x(r) then
+ return 'X';
+ elsif l >= r then
+ return '1';
+ else
+ return '0';
+ end if;
+ end if;
+ end function \?>=\;
+
+ function \?<\ (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(l'low, r'low);
+ variable founddash : BOOLEAN := false;
+ begin
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ return 'X';
+ else
+ for i in L'range loop
+ if L(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ for i in R'range loop
+ if R(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ if founddash then
+ report float_pkg'instance_name
+ & " ""?<"": '-' found in compare string"
+ severity error;
+ return 'X';
+ elsif is_x(l) or is_x(r) then
+ return 'X';
+ elsif l < r then
+ return '1';
+ else
+ return '0';
+ end if;
+ end if;
+ end function \?<\;
+
+ function \?<=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is
+ constant fraction_width : NATURAL := -mine(l'low, r'low);
+ variable founddash : BOOLEAN := false;
+ begin
+ if (fraction_width = 0 or l'length < 7 or r'length < 7) then
+ return 'X';
+ else
+ for i in L'range loop
+ if L(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ for i in R'range loop
+ if R(i) = '-' then
+ founddash := true;
+ end if;
+ end loop;
+ if founddash then
+ report float_pkg'instance_name
+ & " ""?<="": '-' found in compare string"
+ severity error;
+ return 'X';
+ elsif is_x(l) or is_x(r) then
+ return 'X';
+ elsif l <= r then
+ return '1';
+ else
+ return '0';
+ end if;
+ end if;
+ end function \?<=\;
+
+ function std_match (L, R : UNRESOLVED_float) return BOOLEAN is
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ return std_match(to_sulv(L), to_sulv(R));
+ else
+ report float_pkg'instance_name
+ & "STD_MATCH: L'RANGE /= R'RANGE, returning FALSE"
+ severity warning;
+ return false;
+ end if;
+ end function std_match;
+
+ function find_rightmost (arg : UNRESOLVED_float; y : STD_ULOGIC) return INTEGER is
+ begin
+ for_loop : for i in arg'reverse_range loop
+ if \?=\ (arg(i), y) = '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_float; 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;
+
+ -- These override the defaults for the compare operators.
+ function "=" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return eq(l, r);
+ end function "=";
+
+ function "/=" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return ne(l, r);
+ end function "/=";
+
+ function ">=" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return ge(l, r);
+ end function ">=";
+
+ function "<=" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return le(l, r);
+ end function "<=";
+
+ function ">" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return gt(l, r);
+ end function ">";
+
+ function "<" (l, r : UNRESOLVED_float) return BOOLEAN is
+ begin
+ return lt(l, r);
+ end function "<";
+
+ -- purpose: maximum of two numbers (overrides default)
+ function maximum (
+ L, R : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin
+ if ((L'length < 1) or (R'length < 1)) then return NAFP;
+ end if;
+ lresize := resize (l, exponent_width, fraction_width);
+ rresize := resize (r, exponent_width, fraction_width);
+ if lresize > rresize then return lresize;
+ else return rresize;
+ end if;
+ end function maximum;
+
+ function minimum (
+ L, R : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent
+ variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin
+ if ((L'length < 1) or (R'length < 1)) then return NAFP;
+ end if;
+ lresize := resize (l, exponent_width, fraction_width);
+ rresize := resize (r, exponent_width, fraction_width);
+ if lresize > rresize then return rresize;
+ else return lresize;
+ end if;
+ end function minimum;
+
+ -----------------------------------------------------------------------------
+ -- conversion functions
+ -----------------------------------------------------------------------------
+
+ -- Converts a floating point number of one format into another format
+ function resize (
+ arg : UNRESOLVED_float; -- Floating point input
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ constant in_fraction_width : NATURAL := -arg'low; -- length of FP output fraction
+ constant in_exponent_width : NATURAL := arg'high; -- length of FP output exponent
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ -- result value
+ variable fptype : valid_fpstate;
+ variable expon_in : SIGNED (in_exponent_width-1 downto 0);
+ variable fract_in : UNSIGNED (in_fraction_width downto 0);
+ variable round : BOOLEAN;
+ variable expon_out : SIGNED (exponent_width-1 downto 0); -- output fract
+ variable fract_out : UNSIGNED (fraction_width downto 0); -- output fract
+ variable passguard : NATURAL;
+ begin
+ fptype := classfp(arg, check_error);
+ if ((fptype = pos_denormal or fptype = neg_denormal) and denormalize_in
+ and (in_exponent_width < exponent_width
+ or in_fraction_width < fraction_width))
+ or in_exponent_width > exponent_width
+ or in_fraction_width > fraction_width then
+ -- size reduction
+ classcase : case fptype is
+ when isx =>
+ result := (others => 'X');
+ when nan | quiet_nan =>
+ result := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_inf =>
+ result := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when neg_inf =>
+ result := neg_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when pos_zero | neg_zero =>
+ result := zerofp (fraction_width => fraction_width, -- hate -0
+ exponent_width => exponent_width);
+ when others =>
+ break_number (
+ arg => arg,
+ fptyp => fptype,
+ denormalize => denormalize_in,
+ fract => fract_in,
+ expon => expon_in);
+ if fraction_width > in_fraction_width and denormalize_in then
+ -- You only get here if you have a denormal input
+ fract_out := (others => '0'); -- pad with zeros
+ fract_out (fraction_width downto
+ fraction_width - in_fraction_width) := fract_in;
+ result := normalize (
+ fract => fract_out,
+ expon => expon_in,
+ sign => arg(arg'high),
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => 0);
+ else
+ result := normalize (
+ fract => fract_in,
+ expon => expon_in,
+ sign => arg(arg'high),
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => in_fraction_width - fraction_width);
+ end if;
+ end case classcase;
+ else -- size increase or the same size
+ if exponent_width > in_exponent_width then
+ expon_in := SIGNED(arg (in_exponent_width-1 downto 0));
+ if fptype = pos_zero or fptype = neg_zero then
+ result (exponent_width-1 downto 0) := (others => '0');
+ elsif expon_in = -1 then -- inf or nan (shorts out check_error)
+ result (exponent_width-1 downto 0) := (others => '1');
+ else
+ -- invert top BIT
+ expon_in(expon_in'high) := not expon_in(expon_in'high);
+ expon_out := resize (expon_in, expon_out'length); -- signed expand
+ -- Flip it back.
+ expon_out(expon_out'high) := not expon_out(expon_out'high);
+ result (exponent_width-1 downto 0) := UNRESOLVED_float(expon_out);
+ end if;
+ result (exponent_width) := arg (in_exponent_width); -- sign
+ else -- exponent_width = in_exponent_width
+ result (exponent_width downto 0) := arg (in_exponent_width downto 0);
+ end if;
+ if fraction_width > in_fraction_width then
+ result (-1 downto -fraction_width) := (others => '0'); -- zeros
+ result (-1 downto -in_fraction_width) :=
+ arg (-1 downto -in_fraction_width);
+ else -- fraction_width = in_fraciton_width
+ result (-1 downto -fraction_width) :=
+ arg (-1 downto -in_fraction_width);
+ end if;
+ end if;
+ return result;
+ end function resize;
+
+ function resize (
+ arg : UNRESOLVED_float; -- floating point input
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := resize (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize_in => denormalize_in,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function resize;
+
+ function to_float32 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float32 is
+ begin
+ return resize (arg => arg,
+ exponent_width => float32'high,
+ fraction_width => -float32'low,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize_in => denormalize_in,
+ denormalize => denormalize);
+ end function to_float32;
+
+ function to_float64 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float64 is
+ begin
+ return resize (arg => arg,
+ exponent_width => float64'high,
+ fraction_width => -float64'low,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize_in => denormalize_in,
+ denormalize => denormalize);
+ end function to_float64;
+
+ function to_float128 (
+ arg : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error;
+ constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float128 is
+ begin
+ return resize (arg => arg,
+ exponent_width => float128'high,
+ fraction_width => -float128'low,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize_in => denormalize_in,
+ denormalize => denormalize);
+ end function to_float128;
+
+ -- to_float (Real)
+ -- typically not Synthesizable unless the input is a constant.
+ function to_float (
+ arg : REAL;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable arg_real : REAL; -- Real version of argument
+ variable validfp : boundary_type; -- Check for valid results
+ variable exp : INTEGER; -- Integer version of exponent
+ variable expon : UNSIGNED (exponent_width - 1 downto 0);
+ -- Unsigned version of exp.
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable fract : UNSIGNED (fraction_width-1 downto 0);
+ variable frac : REAL; -- Real version of fraction
+ constant roundfrac : REAL := 2.0 ** (-2 - fract'high); -- used for rounding
+ variable round : BOOLEAN; -- to round or not to round
+ begin
+ result := (others => '0');
+ arg_real := arg;
+ if arg_real < 0.0 then
+ result (exponent_width) := '1';
+ arg_real := - arg_real; -- Make it positive.
+ else
+ result (exponent_width) := '0';
+ end if;
+ test_boundary (arg => arg_real,
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ denormalize => denormalize,
+ btype => validfp,
+ log2i => exp);
+ if validfp = zero then
+ return result; -- Result initialized to "0".
+ elsif validfp = infinity then
+ result (exponent_width - 1 downto 0) := (others => '1'); -- Exponent all "1"
+ -- return infinity.
+ return result;
+ else
+ if validfp = denormal then -- Exponent will default to "0".
+ expon := (others => '0');
+ frac := arg_real * (2.0 ** (to_integer(expon_base)-1));
+ else -- Number less than 1. "normal" number
+ expon := UNSIGNED (to_signed (exp-1, exponent_width));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ frac := (arg_real / 2.0 ** exp) - 1.0; -- Number less than 1.
+ end if;
+ for i in 0 to fract'high loop
+ if frac >= 2.0 ** (-1 - i) then
+ fract (fract'high - i) := '1';
+ frac := frac - 2.0 ** (-1 - i);
+ else
+ fract (fract'high - i) := '0';
+ end if;
+ end loop;
+ round := false;
+ case round_style is
+ when round_nearest =>
+ if frac > roundfrac or ((frac = roundfrac) and fract(0) = '1') then
+ round := true;
+ end if;
+ when round_inf =>
+ if frac /= 0.0 and result(exponent_width) = '0' then
+ round := true;
+ end if;
+ when round_neginf =>
+ if frac /= 0.0 and result(exponent_width) = '1' then
+ round := true;
+ end if;
+ when others =>
+ null; -- don't round
+ end case;
+ if (round) then
+ if and_reduce (fract) = '1' then -- fraction is all "1"
+ expon := expon + 1;
+ fract := (others => '0');
+ else
+ fract := fract + 1;
+ end if;
+ end if;
+ result (exponent_width-1 downto 0) := UNRESOLVED_float(expon);
+ result (-1 downto -fraction_width) := UNRESOLVED_float(fract);
+ return result;
+ end if;
+ end function to_float;
+
+ -- to_float (Integer)
+ function to_float (
+ arg : INTEGER;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable arg_int : NATURAL; -- Natural version of argument
+ variable expon : SIGNED (exponent_width-1 downto 0);
+ variable exptmp : SIGNED (exponent_width-1 downto 0);
+ -- Unsigned version of exp.
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable fract : UNSIGNED (fraction_width-1 downto 0) := (others => '0');
+ variable fracttmp : UNSIGNED (fraction_width-1 downto 0);
+ variable round : BOOLEAN;
+ variable shift : NATURAL;
+ variable shiftr : NATURAL;
+ variable roundfrac : NATURAL; -- used in rounding
+ begin
+ if arg < 0 then
+ result (exponent_width) := '1';
+ arg_int := -arg; -- Make it positive.
+ else
+ result (exponent_width) := '0';
+ arg_int := arg;
+ end if;
+ if arg_int = 0 then
+ result := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ -- If the number is larger than we can represent in this number system
+ -- we need to return infinity.
+ shift := log2(arg_int);
+ if shift > to_integer(expon_base) then
+ -- worry about infinity
+ if result (exponent_width) = '0' then
+ result := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ -- return negative infinity.
+ result := neg_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ end if;
+ else -- Normal number (can't be denormal)
+ -- Compute Exponent
+ expon := to_signed (shift-1, expon'length); -- positive fraction.
+ -- Compute Fraction
+ arg_int := arg_int - 2**shift; -- Subtract off the 1.0
+ shiftr := shift;
+ for I in fract'high downto maximum (fract'high - shift + 1, 0) loop
+ shiftr := shiftr - 1;
+ if (arg_int >= 2**shiftr) then
+ arg_int := arg_int - 2**shiftr;
+ fract(I) := '1';
+ else
+ fract(I) := '0';
+ end if;
+ end loop;
+ -- Rounding routine
+ round := false;
+ if arg_int > 0 then
+ roundfrac := 2**(shiftr-1);
+ case round_style is
+ when round_nearest =>
+ if arg_int > roundfrac or
+ ((arg_int = roundfrac) and fract(0) = '1') then
+ round := true;
+ end if;
+ when round_inf =>
+ if arg_int /= 0 and result (exponent_width) = '0' then
+ round := true;
+ end if;
+ when round_neginf =>
+ if arg_int /= 0 and result (exponent_width) = '1' then
+ round := true;
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+ if round then
+ fp_round(fract_in => fract,
+ expon_in => expon,
+ fract_out => fracttmp,
+ expon_out => exptmp);
+ fract := fracttmp;
+ expon := exptmp;
+ end if;
+ -- Put the number together and return
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ result (exponent_width-1 downto 0) := UNRESOLVED_float(expon);
+ result (-1 downto -fraction_width) := UNRESOLVED_float(fract);
+ end if;
+ end if;
+ return result;
+ end function to_float;
+
+ -- to_float (unsigned)
+ function to_float (
+ arg : UNSIGNED;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ constant ARG_LEFT : INTEGER := ARG'length-1;
+ alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG;
+ variable sarg : SIGNED (ARG_LEFT+1 downto 0); -- signed version of arg
+ begin
+ if arg'length < 1 then
+ return NAFP;
+ end if;
+ sarg (XARG'range) := SIGNED (XARG);
+ sarg (sarg'high) := '0';
+ result := to_float (arg => sarg,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ round_style => round_style);
+ return result;
+ end function to_float;
+
+ -- to_float (signed)
+ function to_float (
+ arg : SIGNED;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ constant ARG_LEFT : INTEGER := ARG'length-1;
+ alias XARG : SIGNED(ARG_LEFT downto 0) is ARG;
+ variable arg_int : UNSIGNED(xarg'range); -- Real version of argument
+ variable argb2 : UNSIGNED(xarg'high/2 downto 0); -- log2 of input
+ variable rexp : SIGNED (exponent_width - 1 downto 0);
+ variable exp : SIGNED (exponent_width - 1 downto 0);
+ -- signed version of exp.
+ variable expon : UNSIGNED (exponent_width - 1 downto 0);
+ -- Unsigned version of exp.
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable round : BOOLEAN;
+ variable fract : UNSIGNED (fraction_width-1 downto 0);
+ variable rfract : UNSIGNED (fraction_width-1 downto 0);
+ variable sign : STD_ULOGIC; -- sign bit
+ begin
+ if arg'length < 1 then
+ return NAFP;
+ end if;
+ if Is_X (xarg) then
+ result := (others => 'X');
+ elsif (xarg = 0) then
+ result := zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else -- Normal number (can't be denormal)
+ sign := to_X01(xarg (xarg'high));
+ arg_int := UNSIGNED(abs (to_01(xarg)));
+ -- Compute Exponent
+ argb2 := to_unsigned(find_leftmost(arg_int, '1'), argb2'length); -- Log2
+ if argb2 > UNSIGNED(expon_base) then
+ result := pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ result (exponent_width) := sign;
+ else
+ exp := SIGNED(resize(argb2, exp'length));
+ arg_int := shift_left (arg_int, arg_int'high-to_integer(exp));
+ if (arg_int'high > fraction_width) then
+ fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width));
+ round := check_round (
+ fract_in => fract (0),
+ sign => sign,
+ remainder => arg_int((arg_int'high-fraction_width-1)
+ downto 0),
+ round_style => round_style);
+ if round then
+ fp_round(fract_in => fract,
+ expon_in => exp,
+ fract_out => rfract,
+ expon_out => rexp);
+ else
+ rfract := fract;
+ rexp := exp;
+ end if;
+ else
+ rexp := exp;
+ rfract := (others => '0');
+ rfract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) :=
+ arg_int (arg_int'high-1 downto 0);
+ end if;
+ result (exponent_width) := sign;
+ expon := UNSIGNED (rexp-1);
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ result (exponent_width-1 downto 0) := UNRESOLVED_float(expon);
+ result (-1 downto -fraction_width) := UNRESOLVED_float(rfract);
+ end if;
+ end if;
+ return result;
+ end function to_float;
+
+ -- std_logic_vector to float
+ function to_float (
+ arg : STD_ULOGIC_VECTOR;
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction
+ return UNRESOLVED_float is
+ variable fpvar : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin
+ if arg'length < 1 then
+ return NAFP;
+ end if;
+ fpvar := UNRESOLVED_float(arg);
+ return fpvar;
+ end function to_float;
+
+ -- purpose: converts a ufixed to a floating point
+ function to_float (
+ arg : UNRESOLVED_ufixed; -- unsigned fixed point input
+ constant exponent_width : NATURAL := float_exponent_width; -- width of exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- width of fraction
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions
+ return UNRESOLVED_float is
+ variable sarg : sfixed (arg'high+1 downto arg'low); -- Signed version of arg
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ begin -- function to_float
+ if (arg'length < 1) then
+ return NAFP;
+ end if;
+ sarg (arg'range) := sfixed (arg);
+ sarg (sarg'high) := '0';
+ result := to_float (arg => sarg,
+ exponent_width => exponent_width,
+ fraction_width => fraction_width,
+ round_style => round_style,
+ denormalize => denormalize);
+ return result;
+ end function to_float;
+
+ function to_float (
+ arg : UNRESOLVED_sfixed; -- signed fixed point
+ constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent
+ constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- rounding option
+ return UNRESOLVED_float is
+ constant integer_width : INTEGER := arg'high;
+ constant in_fraction_width : INTEGER := arg'low;
+ variable xresult : sfixed (integer_width downto in_fraction_width);
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable arg_int : UNSIGNED(integer_width - in_fraction_width
+ downto 0); -- unsigned version of argument
+ variable argx : SIGNED (integer_width - in_fraction_width downto 0);
+ variable exp, exptmp : SIGNED (exponent_width + 1 downto 0);
+ variable expon : UNSIGNED (exponent_width - 1 downto 0);
+ -- Unsigned version of exp.
+ constant expon_base : SIGNED (exponent_width-1 downto 0) :=
+ gen_expon_base(exponent_width); -- exponent offset
+ variable fract, fracttmp : UNSIGNED (fraction_width-1 downto 0) :=
+ (others => '0');
+ variable round : BOOLEAN := false;
+ begin
+ if (arg'length < 1) then
+ return NAFP;
+ end if;
+ xresult := to_01(arg, 'X');
+ argx := SIGNED(to_slv(xresult));
+ if (Is_X (arg)) then
+ result := (others => 'X');
+ elsif (argx = 0) then
+ result := (others => '0');
+ else
+ result := (others => '0'); -- zero out the result
+ if argx(argx'left) = '1' then -- toss the sign bit
+ result (exponent_width) := '1'; -- Negative number
+ arg_int := UNSIGNED(to_x01(not STD_LOGIC_VECTOR (argx))) + 1; -- Make it positive with two's complement
+ else
+ result (exponent_width) := '0';
+ arg_int := UNSIGNED(to_x01(STD_LOGIC_VECTOR (argx))); -- new line: direct conversion to unsigned
+ end if;
+ -- Compute Exponent
+ exp := to_signed(find_leftmost(arg_int, '1'), exp'length); -- Log2
+ if exp + in_fraction_width > expon_base then -- return infinity
+ result (-1 downto -fraction_width) := (others => '0');
+ result (exponent_width -1 downto 0) := (others => '1');
+ return result;
+ elsif (denormalize and
+ (exp + in_fraction_width <= -resize(expon_base, exp'length))) then
+ exp := -resize(expon_base, exp'length);
+ -- shift by a constant
+ arg_int := shift_left (arg_int,
+ (arg_int'high + to_integer(expon_base)
+ + in_fraction_width - 1));
+ if (arg_int'high > fraction_width) then
+ fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width));
+ round := check_round (
+ fract_in => arg_int(arg_int'high-fraction_width),
+ sign => result(result'high),
+ remainder => arg_int((arg_int'high-fraction_width-1)
+ downto 0),
+ round_style => round_style);
+ if (round) then
+ fp_round (fract_in => arg_int (arg_int'high-1 downto
+ (arg_int'high-fraction_width)),
+ expon_in => exp,
+ fract_out => fract,
+ expon_out => exptmp);
+ exp := exptmp;
+ end if;
+ else
+ fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) :=
+ arg_int (arg_int'high-1 downto 0);
+ end if;
+ else
+ arg_int := shift_left (arg_int, arg_int'high-to_integer(exp));
+ exp := exp + in_fraction_width;
+ if (arg_int'high > fraction_width) then
+ fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width));
+ round := check_round (
+ fract_in => fract(0),
+ sign => result(result'high),
+ remainder => arg_int((arg_int'high-fraction_width-1)
+ downto 0),
+ round_style => round_style);
+ if (round) then
+ fp_round (fract_in => fract,
+ expon_in => exp,
+ fract_out => fracttmp,
+ expon_out => exptmp);
+ fract := fracttmp;
+ exp := exptmp;
+ end if;
+ else
+ fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) :=
+ arg_int (arg_int'high-1 downto 0);
+ end if;
+ end if;
+ expon := UNSIGNED (resize(exp-1, exponent_width));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ result (exponent_width-1 downto 0) := UNRESOLVED_float(expon);
+ result (-1 downto -fraction_width) := UNRESOLVED_float(fract);
+ end if;
+ return result;
+ end function to_float;
+
+ -- size_res functions
+ -- Integer to float
+ function to_float (
+ arg : INTEGER;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style);
+ return result;
+ end if;
+ end function to_float;
+
+ -- real to float
+ function to_float (
+ arg : REAL;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function to_float;
+
+ -- unsigned to float
+ function to_float (
+ arg : UNSIGNED;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding option
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style);
+ return result;
+ end if;
+ end function to_float;
+
+ -- signed to float
+ function to_float (
+ arg : SIGNED;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style) -- rounding
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style);
+ return result;
+ end if;
+ end function to_float;
+
+ -- std_ulogic_vector to float
+ function to_float (
+ arg : STD_ULOGIC_VECTOR;
+ size_res : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ return result;
+ end if;
+ end function to_float;
+
+ -- unsigned fixed point to float
+ function to_float (
+ arg : UNRESOLVED_ufixed; -- unsigned fixed point input
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function to_float;
+
+ -- signed fixed point to float
+ function to_float (
+ arg : UNRESOLVED_sfixed;
+ size_res : UNRESOLVED_float;
+ constant round_style : com_round_type := float_round_style; -- rounding
+ constant denormalize : BOOLEAN := float_denormalize) -- rounding option
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_float (arg => arg,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low,
+ round_style => round_style,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function to_float;
+
+ -- to_integer (float)
+ function to_integer (
+ arg : UNRESOLVED_float; -- floating point input
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return INTEGER is
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable frac : UNSIGNED (-arg'low downto 0); -- Fraction
+ variable fract : UNSIGNED (1-arg'low downto 0); -- Fraction
+ variable expon : SIGNED (arg'high-1 downto 0);
+ variable isign : STD_ULOGIC; -- internal version of sign
+ variable round : STD_ULOGIC; -- is rounding needed?
+ variable result : INTEGER;
+ variable base : INTEGER; -- Integer exponent
+ begin
+ validfp := classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | nan | quiet_nan | pos_zero | neg_zero | pos_denormal | neg_denormal =>
+ result := 0; -- return 0
+ when pos_inf =>
+ result := INTEGER'high;
+ when neg_inf =>
+ result := INTEGER'low;
+ when others =>
+ break_number (
+ arg => arg,
+ fptyp => validfp,
+ denormalize => false,
+ fract => frac,
+ expon => expon);
+ fract (fract'high) := '0'; -- Add extra bit for 0.6 case
+ fract (fract'high-1 downto 0) := frac;
+ isign := to_x01 (arg (arg'high));
+ base := to_integer (expon) + 1;
+ if base < -1 then
+ result := 0;
+ elsif base >= frac'high then
+ result := to_integer (fract) * 2**(base - frac'high);
+ else -- We need to round
+ if base = -1 then -- trap for 0.6 case.
+ result := 0;
+ else
+ result := to_integer (fract (frac'high downto frac'high-base));
+ end if;
+ -- rounding routine
+ case round_style is
+ when round_nearest =>
+ if frac'high - base > 1 then
+ round := fract (frac'high - base - 1) and
+ (fract (frac'high - base)
+ or (or_reduce (fract (frac'high - base - 2 downto 0))));
+ else
+ round := fract (frac'high - base - 1) and
+ fract (frac'high - base);
+ end if;
+ when round_inf =>
+ round := fract(frac'high - base - 1) and not isign;
+ when round_neginf =>
+ round := fract(frac'high - base - 1) and isign;
+ when others =>
+ round := '0';
+ end case;
+ if round = '1' then
+ result := result + 1;
+ end if;
+ end if;
+ if isign = '1' then
+ result := - result;
+ end if;
+ end case classcase;
+ return result;
+ end function to_integer;
+
+ -- to_unsigned (float)
+ function to_unsigned (
+ arg : UNRESOLVED_float; -- floating point input
+ constant size : NATURAL; -- length of output
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNSIGNED is
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable frac : UNSIGNED (size-1 downto 0); -- Fraction
+ variable sign : STD_ULOGIC; -- not used
+ begin
+ validfp := classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | nan | quiet_nan =>
+ frac := (others => 'X');
+ when pos_zero | neg_inf | neg_zero | neg_normal | pos_denormal | neg_denormal =>
+ frac := (others => '0'); -- return 0
+ when pos_inf =>
+ frac := (others => '1');
+ when others =>
+ float_to_unsigned (
+ arg => arg,
+ frac => frac,
+ sign => sign,
+ denormalize => false,
+ bias => 0,
+ round_style => round_style);
+ end case classcase;
+ return (frac);
+ end function to_unsigned;
+
+ -- to_signed (float)
+ function to_signed (
+ arg : UNRESOLVED_float; -- floating point input
+ constant size : NATURAL; -- length of output
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return SIGNED is
+ variable sign : STD_ULOGIC; -- true if negative
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable frac : UNSIGNED (size-1 downto 0); -- Fraction
+ variable result : SIGNED (size-1 downto 0);
+ begin
+ validfp := classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | nan | quiet_nan =>
+ result := (others => 'X');
+ when pos_zero | neg_zero | pos_denormal | neg_denormal =>
+ result := (others => '0'); -- return 0
+ when pos_inf =>
+ result := (others => '1');
+ result (result'high) := '0';
+ when neg_inf =>
+ result := (others => '0');
+ result (result'high) := '1';
+ when others =>
+ float_to_unsigned (
+ arg => arg,
+ sign => sign,
+ frac => frac,
+ denormalize => false,
+ bias => 0,
+ round_style => round_style);
+ result (size-1) := '0';
+ result (size-2 downto 0) := SIGNED(frac (size-2 downto 0));
+ if sign = '1' then
+ -- Because the most negative signed number is 1 less than the most
+ -- positive signed number, we need this code.
+ if frac(frac'high) = '1' then -- return most negative number
+ result := (others => '0');
+ result (result'high) := '1';
+ else
+ result := -result;
+ end if;
+ else
+ if frac(frac'high) = '1' then -- return most positive number
+ result := (others => '1');
+ result (result'high) := '0';
+ end if;
+ end if;
+ end case classcase;
+ return result;
+ end function to_signed;
+
+ -- purpose: Converts a float to ufixed
+ function to_ufixed (
+ arg : UNRESOLVED_float; -- fp input
+ constant left_index : INTEGER; -- integer part
+ constant right_index : INTEGER; -- fraction part
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_ufixed is
+ constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction
+ constant exponent_width : INTEGER := arg'high; -- length of FP output exponent
+ constant size : INTEGER := left_index - right_index + 4; -- unsigned size
+ variable expon_base : INTEGER; -- exponent offset
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable exp : INTEGER; -- Exponent
+ variable expon : UNSIGNED (exponent_width-1 downto 0); -- Vectorized exponent
+ -- Base to divide fraction by
+ variable frac : UNSIGNED (size-1 downto 0) := (others => '0'); -- Fraction
+ variable frac_shift : UNSIGNED (size-1 downto 0); -- Fraction shifted
+ variable shift : INTEGER;
+ variable result_big : UNRESOLVED_ufixed (left_index downto right_index-3);
+ variable result : UNRESOLVED_ufixed (left_index downto right_index); -- result
+ begin -- function to_ufixed
+ validfp := classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | nan | quiet_nan =>
+ frac := (others => 'X');
+ when pos_zero | neg_inf | neg_zero | neg_normal | neg_denormal =>
+ frac := (others => '0'); -- return 0
+ when pos_inf =>
+ frac := (others => '1'); -- always saturate
+ when others =>
+ expon_base := 2**(exponent_width-1) -1; -- exponent offset
+ -- Figure out the fraction
+ if (validfp = pos_denormal) and denormalize then
+ exp := -expon_base +1;
+ frac (frac'high) := '0'; -- Remove the "1.0".
+ else
+ -- exponent /= '0', normal floating point
+ expon := UNSIGNED(arg (exponent_width-1 downto 0));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ exp := to_integer (SIGNED(expon)) +1;
+ frac (frac'high) := '1'; -- Add the "1.0".
+ end if;
+ shift := (frac'high - 3 + right_index) - exp;
+ if fraction_width > frac'high then -- Can only use size-2 bits
+ frac (frac'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto
+ -frac'high)));
+ else -- can use all bits
+ frac (frac'high-1 downto frac'high-fraction_width) :=
+ UNSIGNED (to_slv (arg(-1 downto -fraction_width)));
+ end if;
+ frac_shift := frac srl shift;
+ if shift < 0 then -- Overflow
+ frac := (others => '1');
+ else
+ frac := frac_shift;
+ end if;
+ end case classcase;
+ result_big := to_ufixed (
+ arg => STD_ULOGIC_VECTOR(frac),
+ left_index => left_index,
+ right_index => (right_index-3));
+ result := resize (arg => result_big,
+ left_index => left_index,
+ right_index => right_index,
+ round_style => round_style,
+ overflow_style => overflow_style);
+ return result;
+ end function to_ufixed;
+
+ -- purpose: Converts a float to sfixed
+ function to_sfixed (
+ arg : UNRESOLVED_float; -- fp input
+ constant left_index : INTEGER; -- integer part
+ constant right_index : INTEGER; -- fraction part
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_sfixed is
+ constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction
+ constant exponent_width : INTEGER := arg'high; -- length of FP output exponent
+ constant size : INTEGER := left_index - right_index + 4; -- unsigned size
+ variable expon_base : INTEGER; -- exponent offset
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable exp : INTEGER; -- Exponent
+ variable sign : BOOLEAN; -- true if negative
+ variable expon : UNSIGNED (exponent_width-1 downto 0); -- Vectorized exponent
+ -- Base to divide fraction by
+ variable frac : UNSIGNED (size-2 downto 0) := (others => '0'); -- Fraction
+ variable frac_shift : UNSIGNED (size-2 downto 0); -- Fraction shifted
+ variable shift : INTEGER;
+ variable rsigned : SIGNED (size-1 downto 0); -- signed version of result
+ variable result_big : UNRESOLVED_sfixed (left_index downto right_index-3);
+ variable result : UNRESOLVED_sfixed (left_index downto right_index)
+ := (others => '0'); -- result
+ begin -- function to_sfixed
+ validfp := classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | nan | quiet_nan =>
+ result := (others => 'X');
+ when pos_zero | neg_zero =>
+ result := (others => '0'); -- return 0
+ when neg_inf =>
+ result (left_index) := '1'; -- return smallest negative number
+ when pos_inf =>
+ result := (others => '1'); -- return largest number
+ result (left_index) := '0';
+ when others =>
+ expon_base := 2**(exponent_width-1) -1; -- exponent offset
+ if arg(exponent_width) = '0' then
+ sign := false;
+ else
+ sign := true;
+ end if;
+ -- Figure out the fraction
+ if (validfp = pos_denormal or validfp = neg_denormal)
+ and denormalize then
+ exp := -expon_base +1;
+ frac (frac'high) := '0'; -- Add the "1.0".
+ else
+ -- exponent /= '0', normal floating point
+ expon := UNSIGNED(arg (exponent_width-1 downto 0));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ exp := to_integer (SIGNED(expon)) +1;
+ frac (frac'high) := '1'; -- Add the "1.0".
+ end if;
+ shift := (frac'high - 3 + right_index) - exp;
+ if fraction_width > frac'high then -- Can only use size-2 bits
+ frac (frac'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto
+ -frac'high)));
+ else -- can use all bits
+ frac (frac'high-1 downto frac'high-fraction_width) :=
+ UNSIGNED (to_slv (arg(-1 downto -fraction_width)));
+ end if;
+ frac_shift := frac srl shift;
+ if shift < 0 then -- Overflow
+ frac := (others => '1');
+ else
+ frac := frac_shift;
+ end if;
+ if not sign then
+ rsigned := SIGNED("0" & frac);
+ else
+ rsigned := -(SIGNED("0" & frac));
+ end if;
+ result_big := to_sfixed (
+ arg => STD_LOGIC_VECTOR(rsigned),
+ left_index => left_index,
+ right_index => (right_index-3));
+ result := resize (arg => result_big,
+ left_index => left_index,
+ right_index => right_index,
+ round_style => round_style,
+ overflow_style => overflow_style);
+ end case classcase;
+ return result;
+ end function to_sfixed;
+
+ -- size_res versions
+ -- float to unsigned
+ function to_unsigned (
+ arg : UNRESOLVED_float; -- floating point input
+ size_res : UNSIGNED;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return UNSIGNED is
+ variable result : UNSIGNED (size_res'range);
+ begin
+ if (SIZE_RES'length = 0) then
+ return result;
+ else
+ result := to_unsigned (
+ arg => arg,
+ size => size_res'length,
+ round_style => round_style,
+ check_error => check_error);
+ return result;
+ end if;
+ end function to_unsigned;
+
+ -- float to signed
+ function to_signed (
+ arg : UNRESOLVED_float; -- floating point input
+ size_res : SIGNED;
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error) -- check for errors
+ return SIGNED is
+ variable result : SIGNED (size_res'range);
+ begin
+ if (SIZE_RES'length = 0) then
+ return result;
+ else
+ result := to_signed (
+ arg => arg,
+ size => size_res'length,
+ round_style => round_style,
+ check_error => check_error);
+ return result;
+ end if;
+ end function to_signed;
+
+ -- purpose: Converts a float to unsigned fixed point
+ function to_ufixed (
+ arg : UNRESOLVED_float; -- fp input
+ size_res : UNRESOLVED_ufixed;
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_ufixed is
+ variable result : UNRESOLVED_ufixed (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_ufixed (
+ arg => arg,
+ left_index => size_res'high,
+ right_index => size_res'low,
+ overflow_style => overflow_style,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function to_ufixed;
+
+ -- float to signed fixed point
+ function to_sfixed (
+ arg : UNRESOLVED_float; -- fp input
+ size_res : UNRESOLVED_sfixed;
+ constant overflow_style : com_fixed_overflow_style_type := fixed_overflow_style; -- saturate
+ constant round_style : com_fixed_round_style_type := fixed_round_style; -- rounding
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_sfixed is
+ variable result : UNRESOLVED_sfixed (size_res'left downto size_res'right);
+ begin
+ if (result'length < 1) then
+ return result;
+ else
+ result := to_sfixed (
+ arg => arg,
+ left_index => size_res'high,
+ right_index => size_res'low,
+ overflow_style => overflow_style,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize => denormalize);
+ return result;
+ end if;
+ end function to_sfixed;
+
+ -- to_real (float)
+ -- typically not Synthesizable unless the input is a constant.
+ function to_real (
+ arg : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return REAL is
+ constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction
+ constant exponent_width : INTEGER := arg'high; -- length of FP output exponent
+ variable sign : REAL; -- Sign, + or - 1
+ variable exp : INTEGER; -- Exponent
+ variable expon_base : INTEGER; -- exponent offset
+ variable frac : REAL := 0.0; -- Fraction
+ variable validfp : valid_fpstate; -- Valid FP state
+ variable expon : UNSIGNED (exponent_width - 1 downto 0)
+ := (others => '1'); -- Vectorized exponent
+ begin
+ validfp := classfp (arg, check_error);
+ classcase : case validfp is
+ when isx | pos_zero | neg_zero | nan | quiet_nan =>
+ return 0.0;
+ when neg_inf =>
+ return REAL'low; -- Negative infinity.
+ when pos_inf =>
+ return REAL'high; -- Positive infinity
+ when others =>
+ expon_base := 2**(exponent_width-1) -1;
+ if to_X01(arg(exponent_width)) = '0' then
+ sign := 1.0;
+ else
+ sign := -1.0;
+ end if;
+ -- Figure out the fraction
+ for i in 0 to fraction_width-1 loop
+ if to_X01(arg (-1 - i)) = '1' then
+ frac := frac + (2.0 **(-1 - i));
+ end if;
+ end loop; -- i
+ if validfp = pos_normal or validfp = neg_normal or not denormalize then
+ -- exponent /= '0', normal floating point
+ expon := UNSIGNED(arg (exponent_width-1 downto 0));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ exp := to_integer (SIGNED(expon)) +1;
+ sign := sign * (2.0 ** exp) * (1.0 + frac);
+ else -- exponent = '0', IEEE extended floating point
+ exp := 1 - expon_base;
+ sign := sign * (2.0 ** exp) * frac;
+ end if;
+ return sign;
+ end case classcase;
+ end function to_real;
+
+ -- For Verilog compatability
+ function realtobits (arg : REAL) return STD_ULOGIC_VECTOR is
+ variable result : float64; -- 64 bit floating point
+ begin
+ result := to_float (arg => arg,
+ exponent_width => float64'high,
+ fraction_width => -float64'low);
+ return to_sulv (result);
+ end function realtobits;
+
+ function bitstoreal (arg : STD_ULOGIC_VECTOR) return REAL is
+ variable arg64 : float64; -- arg converted to float
+ begin
+ arg64 := to_float (arg => arg,
+ exponent_width => float64'high,
+ fraction_width => -float64'low);
+ return to_real (arg64);
+ end function bitstoreal;
+
+ -- purpose: Removes meta-logical values from FP string
+ function to_01 (
+ arg : UNRESOLVED_float; -- floating point input
+ XMAP : STD_LOGIC := '0')
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (arg'range);
+ begin -- function to_01
+ if (arg'length < 1) then
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & "TO_01: null detected, returning NULL"
+ severity warning;
+ return NAFP;
+ end if;
+ result := UNRESOLVED_float (STD_LOGIC_VECTOR(to_01(UNSIGNED(to_slv(arg)), XMAP)));
+ return result;
+ end function to_01;
+
+ function Is_X
+ (arg : UNRESOLVED_float)
+ return BOOLEAN is
+ begin
+ return Is_X (to_slv(arg));
+ end function Is_X;
+
+ function to_X01 (arg : UNRESOLVED_float) return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (arg'range);
+ begin
+ if (arg'length < 1) then
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & "TO_X01: null detected, returning NULL"
+ severity warning;
+ return NAFP;
+ else
+ result := UNRESOLVED_float (to_X01(to_slv(arg)));
+ return result;
+ end if;
+ end function to_X01;
+
+ function to_X01Z (arg : UNRESOLVED_float) return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (arg'range);
+ begin
+ if (arg'length < 1) then
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & "TO_X01Z: null detected, returning NULL"
+ severity warning;
+ return NAFP;
+ else
+ result := UNRESOLVED_float (to_X01Z(to_slv(arg)));
+ return result;
+ end if;
+ end function to_X01Z;
+
+ function to_UX01 (arg : UNRESOLVED_float) return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (arg'range);
+ begin
+ if (arg'length < 1) then
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & "TO_UX01: null detected, returning NULL"
+ severity warning;
+ return NAFP;
+ else
+ result := UNRESOLVED_float (to_UX01(to_slv(arg)));
+ return result;
+ end if;
+ end function to_UX01;
+
+ -- These allows the base math functions to use the default values
+ -- of their parameters. Thus they do full IEEE floating point.
+ function "+" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return add (l, r);
+ end function "+";
+
+ function "-" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return subtract (l, r);
+ end function "-";
+
+ function "*" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return multiply (l, r);
+ end function "*";
+
+ function "/" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return divide (l, r);
+ end function "/";
+
+ function "rem" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return remainder (l, r);
+ end function "rem";
+
+ function "mod" (l, r : UNRESOLVED_float) return UNRESOLVED_float is
+ begin
+ return modulo (l, r);
+ end function "mod";
+
+ -- overloaded versions
+ function "+" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return add (l, r_float);
+ end function "+";
+
+ function "+" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return add (l_float, r);
+ end function "+";
+
+ function "+" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return add (l, r_float);
+ end function "+";
+
+ function "+" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return add (l_float, r);
+ end function "+";
+
+ function "-" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return subtract (l, r_float);
+ end function "-";
+
+ function "-" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return subtract (l_float, r);
+ end function "-";
+
+ function "-" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return subtract (l, r_float);
+ end function "-";
+
+ function "-" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return subtract (l_float, r);
+ end function "-";
+
+ function "*" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return multiply (l, r_float);
+ end function "*";
+
+ function "*" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return multiply (l_float, r);
+ end function "*";
+
+ function "*" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return multiply (l, r_float);
+ end function "*";
+
+ function "*" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return multiply (l_float, r);
+ end function "*";
+
+ function "/" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return divide (l, r_float);
+ end function "/";
+
+ function "/" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return divide (l_float, r);
+ end function "/";
+
+ function "/" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return divide (l, r_float);
+ end function "/";
+
+ function "/" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return divide (l_float, r);
+ end function "/";
+
+ function "rem" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return remainder (l, r_float);
+ end function "rem";
+
+ function "rem" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return remainder (l_float, r);
+ end function "rem";
+
+ function "rem" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return remainder (l, r_float);
+ end function "rem";
+
+ function "rem" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return remainder (l_float, r);
+ end function "rem";
+
+ function "mod" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return modulo (l, r_float);
+ end function "mod";
+
+ function "mod" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return modulo (l_float, r);
+ end function "mod";
+
+ function "mod" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return modulo (l, r_float);
+ end function "mod";
+
+ function "mod" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return modulo (l_float, r);
+ end function "mod";
+
+ function "=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return eq (l, r_float);
+ end function "=";
+
+ function "/=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return ne (l, r_float);
+ end function "/=";
+
+ function ">=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return ge (l, r_float);
+ end function ">=";
+
+ function "<=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return le (l, r_float);
+ end function "<=";
+
+ function ">" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return gt (l, r_float);
+ end function ">";
+
+ function "<" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return lt (l, r_float);
+ end function "<";
+
+ function "=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return eq (l_float, r);
+ end function "=";
+
+ function "/=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return ne (l_float, r);
+ end function "/=";
+
+ function ">=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return ge (l_float, r);
+ end function ">=";
+
+ function "<=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return le (l_float, r);
+ end function "<=";
+
+ function ">" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return gt (l_float, r);
+ end function ">";
+
+ function "<" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return lt (l_float, r);
+ end function "<";
+
+ function "=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return eq (l, r_float);
+ end function "=";
+
+ function "/=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return ne (l, r_float);
+ end function "/=";
+
+ function ">=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return ge (l, r_float);
+ end function ">=";
+
+ function "<=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return le (l, r_float);
+ end function "<=";
+
+ function ">" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return gt (l, r_float);
+ end function ">";
+
+ function "<" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return lt (l, r_float);
+ end function "<";
+
+ function "=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return eq (l_float, r);
+ end function "=";
+
+ function "/=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return ne (l_float, r);
+ end function "/=";
+
+ function ">=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return ge (l_float, r);
+ end function ">=";
+
+ function "<=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return le (l_float, r);
+ end function "<=";
+
+ function ">" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return gt (l_float, r);
+ end function ">";
+
+ function "<" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float(l, r'high, -r'low);
+ return lt (l_float, r);
+ end function "<";
+
+ -- ?= overloads
+ function \?=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?=\ (l, r_float);
+ end function \?=\;
+
+ function \?/=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?/=\ (l, r_float);
+ end function \?/=\;
+
+ function \?>\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?>\ (l, r_float);
+ end function \?>\;
+
+ function \?>=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?>=\ (l, r_float);
+ end function \?>=\;
+
+ function \?<\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?<\ (l, r_float);
+ end function \?<\;
+
+ function \?<=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?<=\ (l, r_float);
+ end function \?<=\;
+
+ -- real and float
+ function \?=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?=\ (l_float, r);
+ end function \?=\;
+
+ function \?/=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?/=\ (l_float, r);
+ end function \?/=\;
+
+ function \?>\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?>\ (l_float, r);
+ end function \?>\;
+
+ function \?>=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?>=\ (l_float, r);
+ end function \?>=\;
+
+ function \?<\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?<\ (l_float, r);
+ end function \?<\;
+
+ function \?<=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?<=\ (l_float, r);
+ end function \?<=\;
+
+ -- ?= overloads
+ function \?=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?=\ (l, r_float);
+ end function \?=\;
+
+ function \?/=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?/=\ (l, r_float);
+ end function \?/=\;
+
+ function \?>\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?>\ (l, r_float);
+ end function \?>\;
+
+ function \?>=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?>=\ (l, r_float);
+ end function \?>=\;
+
+ function \?<\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?<\ (l, r_float);
+ end function \?<\;
+
+ function \?<=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return \?<=\ (l, r_float);
+ end function \?<=\;
+
+ -- integer and float
+ function \?=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?=\ (l_float, r);
+ end function \?=\;
+
+ function \?/=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?/=\ (l_float, r);
+ end function \?/=\;
+
+ function \?>\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?>\ (l_float, r);
+ end function \?>\;
+
+ function \?>=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?>=\ (l_float, r);
+ end function \?>=\;
+
+ function \?<\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?<\ (l_float, r);
+ end function \?<\;
+
+ function \?<=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return \?<=\ (l_float, r);
+ end function \?<=\;
+
+ -- minimum and maximum overloads
+ function minimum (l : UNRESOLVED_float; r : REAL)
+ return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return minimum (l, r_float);
+ end function minimum;
+
+ function maximum (l : UNRESOLVED_float; r : REAL)
+ return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return maximum (l, r_float);
+ end function maximum;
+
+ function minimum (l : REAL; r : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return minimum (l_float, r);
+ end function minimum;
+
+ function maximum (l : REAL; r : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return maximum (l_float, r);
+ end function maximum;
+
+ function minimum (l : UNRESOLVED_float; r : INTEGER)
+ return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return minimum (l, r_float);
+ end function minimum;
+
+ function maximum (l : UNRESOLVED_float; r : INTEGER)
+ return UNRESOLVED_float is
+ variable r_float : UNRESOLVED_float (l'range);
+ begin
+ r_float := to_float (r, l'high, -l'low);
+ return maximum (l, r_float);
+ end function maximum;
+
+ function minimum (l : INTEGER; r : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return minimum (l_float, r);
+ end function minimum;
+
+ function maximum (l : INTEGER; r : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ variable l_float : UNRESOLVED_float (r'range);
+ begin
+ l_float := to_float (l, r'high, -r'low);
+ return maximum (l_float, r);
+ end function maximum;
+
+ ----------------------------------------------------------------------------
+ -- logical functions
+ ----------------------------------------------------------------------------
+ function "not" (L : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ RESULT := not to_sulv(L);
+ return to_float (RESULT, L'high, -L'low);
+ end function "not";
+
+ function "and" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) and to_sulv(R);
+ else
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & """and"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "and";
+
+ function "or" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) or to_sulv(R);
+ else
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & """or"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "or";
+
+ function "nand" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) nand to_sulv(R);
+ else
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & """nand"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "nand";
+
+ function "nor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) nor to_sulv(R);
+ else
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & """nor"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "nor";
+
+ function "xor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) xor to_sulv(R);
+ else
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & """xor"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "xor";
+
+ function "xnor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is
+ variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto
+ begin
+ if (L'high = R'high and L'low = R'low) then
+ RESULT := to_sulv(L) xnor to_sulv(R);
+ else
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & """xnor"": Range error L'RANGE /= R'RANGE"
+ severity warning;
+ RESULT := (others => 'X');
+ end if;
+ return to_float (RESULT, L'high, -L'low);
+ end function "xnor";
+
+ -- Vector and std_ulogic functions, same as functions in numeric_std
+ function "and" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ for i in result'range loop
+ result(i) := L and R(i);
+ end loop;
+ return result;
+ end function "and";
+
+ function "and" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ for i in result'range loop
+ result(i) := L(i) and R;
+ end loop;
+ return result;
+ end function "and";
+
+ function "or" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ for i in result'range loop
+ result(i) := L or R(i);
+ end loop;
+ return result;
+ end function "or";
+
+ function "or" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ for i in result'range loop
+ result(i) := L(i) or R;
+ end loop;
+ return result;
+ end function "or";
+
+ function "nand" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ for i in result'range loop
+ result(i) := L nand R(i);
+ end loop;
+ return result;
+ end function "nand";
+
+ function "nand" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ for i in result'range loop
+ result(i) := L(i) nand R;
+ end loop;
+ return result;
+ end function "nand";
+
+ function "nor" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ for i in result'range loop
+ result(i) := L nor R(i);
+ end loop;
+ return result;
+ end function "nor";
+
+ function "nor" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ for i in result'range loop
+ result(i) := L(i) nor R;
+ end loop;
+ return result;
+ end function "nor";
+
+ function "xor" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ for i in result'range loop
+ result(i) := L xor R(i);
+ end loop;
+ return result;
+ end function "xor";
+
+ function "xor" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ for i in result'range loop
+ result(i) := L(i) xor R;
+ end loop;
+ return result;
+ end function "xor";
+
+ function "xnor" (L : STD_ULOGIC; R : UNRESOLVED_float)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (R'range);
+ begin
+ for i in result'range loop
+ result(i) := L xnor R(i);
+ end loop;
+ return result;
+ end function "xnor";
+
+ function "xnor" (L : UNRESOLVED_float; R : STD_ULOGIC)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (L'range);
+ begin
+ for i in result'range loop
+ result(i) := L(i) xnor R;
+ end loop;
+ return result;
+ end function "xnor";
+
+ -- Reduction operator_reduces, same as numeric_std functions
+
+ function and_reduce (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return and_reduce (to_sulv(l));
+ end function and_reduce;
+
+ function nand_reduce (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return nand_reduce (to_sulv(l));
+ end function nand_reduce;
+
+ function or_reduce (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return or_reduce (to_sulv(l));
+ end function or_reduce;
+
+ function nor_reduce (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return nor_reduce (to_sulv(l));
+ end function nor_reduce;
+
+ function xor_reduce (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return xor_reduce (to_sulv(l));
+ end function xor_reduce;
+
+ function xnor_reduce (l : UNRESOLVED_float) return STD_ULOGIC is
+ begin
+ return xnor_reduce (to_sulv(l));
+ end function xnor_reduce;
+
+ -----------------------------------------------------------------------------
+ -- Recommended Functions from the IEEE 754 Appendix
+ -----------------------------------------------------------------------------
+ -- returns x with the sign of y.
+ function Copysign (
+ x, y : UNRESOLVED_float) -- floating point input
+ return UNRESOLVED_float is
+ begin
+ return y(y'high) & x (x'high-1 downto x'low);
+ end function Copysign;
+
+ -- Returns y * 2**n for integral values of N without computing 2**n
+ function Scalb (
+ y : UNRESOLVED_float; -- floating point input
+ N : INTEGER; -- exponent to add
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := -mine(y'low, y'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := y'high; -- length of FP output exponent
+ variable arg, result : UNRESOLVED_float (exponent_width downto -fraction_width); -- internal argument
+ variable expon : SIGNED (exponent_width-1 downto 0); -- Vectorized exp
+ variable exp : SIGNED (exponent_width downto 0);
+ variable ufract : UNSIGNED (fraction_width downto 0);
+ constant expon_base : SIGNED (exponent_width-1 downto 0)
+ := gen_expon_base(exponent_width); -- exponent offset
+ variable fptype : valid_fpstate;
+ begin
+ -- This can be done by simply adding N to the exponent.
+ arg := to_01 (y, 'X');
+ fptype := classfp(arg, check_error);
+ classcase : case fptype is
+ when isx =>
+ result := (others => 'X');
+ when nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ result := qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ when others =>
+ break_number (
+ arg => arg,
+ fptyp => fptype,
+ denormalize => denormalize,
+ fract => ufract,
+ expon => expon);
+ exp := resize (expon, exp'length) + N;
+ result := normalize (
+ fract => ufract,
+ expon => exp,
+ sign => to_x01 (arg (arg'high)),
+ fraction_width => fraction_width,
+ exponent_width => exponent_width,
+ round_style => round_style,
+ denormalize => denormalize,
+ nguard => 0);
+ end case classcase;
+ return result;
+ end function Scalb;
+
+ -- Returns y * 2**n for integral values of N without computing 2**n
+ function Scalb (
+ y : UNRESOLVED_float; -- floating point input
+ N : SIGNED; -- exponent to add
+ constant round_style : com_round_type := float_round_style; -- rounding option
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP
+ return UNRESOLVED_float is
+ variable n_int : INTEGER;
+ begin
+ n_int := to_integer(N);
+ return Scalb (y => y,
+ N => n_int,
+ round_style => round_style,
+ check_error => check_error,
+ denormalize => denormalize);
+ end function Scalb;
+
+ -- returns the unbiased exponent of x
+ function Logb (
+ x : UNRESOLVED_float) -- floating point input
+ return INTEGER is
+ constant fraction_width : NATURAL := -mine (x'low, x'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := x'high; -- length of FP output exponent
+ variable result : INTEGER; -- result
+ variable arg : UNRESOLVED_float (exponent_width downto -fraction_width); -- internal argument
+ variable expon : SIGNED (exponent_width - 1 downto 0);
+ variable fract : UNSIGNED (fraction_width downto 0);
+ constant expon_base : INTEGER := 2**(exponent_width-1) -1; -- exponent
+ -- offset +1
+ variable fptype : valid_fpstate;
+ begin
+ -- Just return the exponent.
+ arg := to_01 (x, 'X');
+ fptype := classfp(arg);
+ classcase : case fptype is
+ when isx | nan | quiet_nan =>
+ -- Return quiet NAN, IEEE754-1985-7.1,1
+ result := 0;
+ when pos_denormal | neg_denormal =>
+ fract (fraction_width) := '0';
+ fract (fraction_width-1 downto 0) :=
+ UNSIGNED (to_slv(arg(-1 downto -fraction_width)));
+ result := find_leftmost (fract, '1') -- Find the first "1"
+ - fraction_width; -- subtract the length we want
+ result := -expon_base + 1 + result;
+ when others =>
+ expon := SIGNED(arg (exponent_width - 1 downto 0));
+ expon(exponent_width-1) := not expon(exponent_width-1);
+ expon := expon + 1;
+ result := to_integer (expon);
+ end case classcase;
+ return result;
+ end function Logb;
+
+ -- returns the unbiased exponent of x
+ function Logb (
+ x : UNRESOLVED_float) -- floating point input
+ return SIGNED is
+ constant exponent_width : NATURAL := x'high; -- length of FP output exponent
+ variable result : SIGNED (exponent_width - 1 downto 0); -- result
+ begin
+ -- Just return the exponent.
+ result := to_signed (Logb (x), exponent_width);
+ return result;
+ end function Logb;
+
+ -- returns the next representable neighbor of x in the direction toward y
+ function Nextafter (
+ x, y : UNRESOLVED_float; -- floating point input
+ constant check_error : BOOLEAN := float_check_error; -- check for errors
+ constant denormalize : BOOLEAN := float_denormalize)
+ return UNRESOLVED_float is
+ constant fraction_width : NATURAL := -mine(x'low, x'low); -- length of FP output fraction
+ constant exponent_width : NATURAL := x'high; -- length of FP output exponent
+ function "=" (
+ l, r : UNRESOLVED_float) -- inputs
+ return BOOLEAN is
+ begin -- function "="
+ return eq (l => l,
+ r => r,
+ check_error => false);
+ end function "=";
+ function ">" (
+ l, r : UNRESOLVED_float) -- inputs
+ return BOOLEAN is
+ begin -- function ">"
+ return gt (l => l,
+ r => r,
+ check_error => false);
+ end function ">";
+ variable fract : UNSIGNED (fraction_width-1 downto 0);
+ variable expon : UNSIGNED (exponent_width-1 downto 0);
+ variable sign : STD_ULOGIC;
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable validfpx, validfpy : valid_fpstate; -- Valid FP state
+ begin -- fp_Nextafter
+ -- If Y > X, add one to the fraction, otherwise subtract.
+ validfpx := classfp (x, check_error);
+ validfpy := classfp (y, check_error);
+ if validfpx = isx or validfpy = isx then
+ result := (others => 'X');
+ return result;
+ elsif (validfpx = nan or validfpy = nan) then
+ return nanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif (validfpx = quiet_nan or validfpy = quiet_nan) then
+ return qnanfp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ elsif x = y then -- Return X
+ return x;
+ else
+ fract := UNSIGNED (to_slv (x (-1 downto -fraction_width))); -- Fraction
+ expon := UNSIGNED (x (exponent_width - 1 downto 0)); -- exponent
+ sign := x(exponent_width); -- sign bit
+ if (y > x) then
+ -- Increase the number given
+ if validfpx = neg_inf then
+ -- return most negative number
+ expon := (others => '1');
+ expon (0) := '0';
+ fract := (others => '1');
+ elsif validfpx = pos_zero or validfpx = neg_zero then
+ -- return smallest denormal number
+ sign := '0';
+ expon := (others => '0');
+ fract := (others => '0');
+ fract(0) := '1';
+ elsif validfpx = pos_normal then
+ if and_reduce (fract) = '1' then -- fraction is all "1".
+ if and_reduce (expon (exponent_width-1 downto 1)) = '1'
+ and expon (0) = '0' then
+ -- Exponent is one away from infinity.
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & "FP_NEXTAFTER: NextAfter overflow"
+ severity warning;
+ return pos_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ expon := expon + 1;
+ fract := (others => '0');
+ end if;
+ else
+ fract := fract + 1;
+ end if;
+ elsif validfpx = pos_denormal then
+ if and_reduce (fract) = '1' then -- fraction is all "1".
+ -- return smallest possible normal number
+ expon := (others => '0');
+ expon(0) := '1';
+ fract := (others => '0');
+ else
+ fract := fract + 1;
+ end if;
+ elsif validfpx = neg_normal then
+ if or_reduce (fract) = '0' then -- fraction is all "0".
+ if or_reduce (expon (exponent_width-1 downto 1)) = '0' and
+ expon (0) = '1' then -- Smallest exponent
+ -- return the largest negative denormal number
+ expon := (others => '0');
+ fract := (others => '1');
+ else
+ expon := expon - 1;
+ fract := (others => '1');
+ end if;
+ else
+ fract := fract - 1;
+ end if;
+ elsif validfpx = neg_denormal then
+ if or_reduce (fract(fract'high downto 1)) = '0'
+ and fract (0) = '1' then -- Smallest possible fraction
+ return zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ fract := fract - 1;
+ end if;
+ end if;
+ else
+ -- Decrease the number
+ if validfpx = pos_inf then
+ -- return most positive number
+ expon := (others => '1');
+ expon (0) := '0';
+ fract := (others => '1');
+ elsif validfpx = pos_zero
+ or classfp (x) = neg_zero then
+ -- return smallest negative denormal number
+ sign := '1';
+ expon := (others => '0');
+ fract := (others => '0');
+ fract(0) := '1';
+ elsif validfpx = neg_normal then
+ if and_reduce (fract) = '1' then -- fraction is all "1".
+ if and_reduce (expon (exponent_width-1 downto 1)) = '1'
+ and expon (0) = '0' then
+ -- Exponent is one away from infinity.
+ assert NO_WARNING
+ report float_pkg'instance_name
+ & "FP_NEXTAFTER: NextAfter overflow"
+ severity warning;
+ return neg_inffp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ expon := expon + 1; -- Fraction overflow
+ fract := (others => '0');
+ end if;
+ else
+ fract := fract + 1;
+ end if;
+ elsif validfpx = neg_denormal then
+ if and_reduce (fract) = '1' then -- fraction is all "1".
+ -- return smallest possible normal number
+ expon := (others => '0');
+ expon(0) := '1';
+ fract := (others => '0');
+ else
+ fract := fract + 1;
+ end if;
+ elsif validfpx = pos_normal then
+ if or_reduce (fract) = '0' then -- fraction is all "0".
+ if or_reduce (expon (exponent_width-1 downto 1)) = '0' and
+ expon (0) = '1' then -- Smallest exponent
+ -- return the largest positive denormal number
+ expon := (others => '0');
+ fract := (others => '1');
+ else
+ expon := expon - 1;
+ fract := (others => '1');
+ end if;
+ else
+ fract := fract - 1;
+ end if;
+ elsif validfpx = pos_denormal then
+ if or_reduce (fract(fract'high downto 1)) = '0'
+ and fract (0) = '1' then -- Smallest possible fraction
+ return zerofp (fraction_width => fraction_width,
+ exponent_width => exponent_width);
+ else
+ fract := fract - 1;
+ end if;
+ end if;
+ end if;
+ result (-1 downto -fraction_width) := UNRESOLVED_float(fract);
+ result (exponent_width -1 downto 0) := UNRESOLVED_float(expon);
+ result (exponent_width) := sign;
+ return result;
+ end if;
+ end function Nextafter;
+
+ -- Returns True if X is unordered with Y.
+ function Unordered (
+ x, y : UNRESOLVED_float) -- floating point input
+ return BOOLEAN is
+ variable lfptype, rfptype : valid_fpstate;
+ begin
+ lfptype := classfp (x);
+ rfptype := classfp (y);
+ if (lfptype = nan or lfptype = quiet_nan or
+ rfptype = nan or rfptype = quiet_nan or
+ lfptype = isx or rfptype = isx) then
+ return true;
+ else
+ return false;
+ end if;
+ end function Unordered;
+
+ function Finite (
+ x : UNRESOLVED_float)
+ return BOOLEAN is
+ variable fp_state : valid_fpstate; -- fp state
+ begin
+ fp_state := Classfp (x);
+ if (fp_state = pos_inf) or (fp_state = neg_inf) then
+ return true;
+ else
+ return false;
+ end if;
+ end function Finite;
+
+ function Isnan (
+ x : UNRESOLVED_float)
+ return BOOLEAN is
+ variable fp_state : valid_fpstate; -- fp state
+ begin
+ fp_state := Classfp (x);
+ if (fp_state = nan) or (fp_state = quiet_nan) then
+ return true;
+ else
+ return false;
+ end if;
+ end function Isnan;
+
+ -- Function to return constants.
+ function zerofp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float is
+ constant result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ return result;
+ end function zerofp;
+
+ function nanfp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ result (exponent_width-1 downto 0) := (others => '1');
+ -- Exponent all "1"
+ result (-1) := '1'; -- MSB of Fraction "1"
+ -- Note: From W. Khan "IEEE Standard 754 for Binary Floating Point"
+ -- The difference between a signaling NAN and a quiet NAN is that
+ -- the MSB of the Fraction is a "1" in a Signaling NAN, and is a
+ -- "0" in a quiet NAN.
+ return result;
+ end function nanfp;
+
+ function qnanfp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ result (exponent_width-1 downto 0) := (others => '1');
+ -- Exponent all "1"
+ result (-fraction_width) := '1'; -- LSB of Fraction "1"
+ -- (Could have been any bit)
+ return result;
+ end function qnanfp;
+
+ function pos_inffp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ result (exponent_width-1 downto 0) := (others => '1'); -- Exponent all "1"
+ return result;
+ end function pos_inffp;
+
+ function neg_inffp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ result (exponent_width downto 0) := (others => '1'); -- top bits all "1"
+ return result;
+ end function neg_inffp;
+
+ function neg_zerofp (
+ constant exponent_width : NATURAL := float_exponent_width; -- exponent
+ constant fraction_width : NATURAL := float_fraction_width) -- fraction
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width) :=
+ (others => '0'); -- zero
+ begin
+ result (exponent_width) := '1';
+ return result;
+ end function neg_zerofp;
+
+ -- size_res versions
+ function zerofp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return zerofp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function zerofp;
+
+ function nanfp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return nanfp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function nanfp;
+
+ function qnanfp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return qnanfp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function qnanfp;
+
+ function pos_inffp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return pos_inffp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function pos_inffp;
+
+ function neg_inffp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return neg_inffp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function neg_inffp;
+
+ function neg_zerofp (
+ size_res : UNRESOLVED_float) -- variable is only use for sizing
+ return UNRESOLVED_float is
+ begin
+ return neg_zerofp (
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function neg_zerofp;
+
+-- rtl_synthesis off
+-- pragma synthesis_off
+
+ --%%% these functions are copied from std_logic_1164 (VHDL-200X edition)
+ -- Textio functions
+ -- purpose: writes float into a line (NOTE changed basetype)
+ type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', error);
+ type char_indexed_by_MVL9 is array (STD_ULOGIC) of CHARACTER;
+ type MVL9_indexed_by_char is array (CHARACTER) of STD_ULOGIC;
+ type MVL9plus_indexed_by_char is array (CHARACTER) of MVL9plus;
+
+ constant NBSP : CHARACTER := CHARACTER'val(160); -- space character
+ constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-";
+ constant char_to_MVL9 : MVL9_indexed_by_char :=
+ ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
+ 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U');
+ constant char_to_MVL9plus : MVL9plus_indexed_by_char :=
+ ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
+ 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => error);
+ constant NUS : STRING(2 to 1) := (others => ' ');
+
+ -- purpose: Skips white space
+ procedure skip_whitespace (
+ L : inout LINE) is
+ variable readOk : BOOLEAN;
+ variable c : CHARACTER;
+ begin
+ while L /= null and L.all'length /= 0 loop
+ if (L.all(1) = ' ' or L.all(1) = NBSP or L.all(1) = HT) then
+ read (l, c, readOk);
+ else
+ exit;
+ end if;
+ end loop;
+ end procedure skip_whitespace;
+
+-- %%% Replicated textio functions
+ function to_ostring (value : STD_LOGIC_VECTOR) return STRING is
+ constant ne : INTEGER := (value'length+2)/3;
+ variable pad : STD_LOGIC_VECTOR(0 to (ne*3 - value'length) - 1);
+ variable ivalue : STD_LOGIC_VECTOR(0 to ne*3 - 1);
+ variable result : STRING(1 to ne);
+ variable tri : STD_LOGIC_VECTOR(0 to 2);
+ begin
+ if value'length < 1 then
+ return NUS;
+ else
+ if value (value'left) = 'Z' then
+ pad := (others => 'Z');
+ else
+ pad := (others => '0');
+ end if;
+ ivalue := pad & value;
+ for i in 0 to ne-1 loop
+ tri := To_X01Z(ivalue(3*i to 3*i+2));
+ case tri is
+ when o"0" => result(i+1) := '0';
+ when o"1" => result(i+1) := '1';
+ when o"2" => result(i+1) := '2';
+ when o"3" => result(i+1) := '3';
+ when o"4" => result(i+1) := '4';
+ when o"5" => result(i+1) := '5';
+ when o"6" => result(i+1) := '6';
+ when o"7" => result(i+1) := '7';
+ when "ZZZ" => result(i+1) := 'Z';
+ when others => result(i+1) := 'X';
+ end case;
+ end loop;
+ return result;
+ end if;
+ end function to_ostring;
+ -------------------------------------------------------------------
+ function to_hstring (value : STD_LOGIC_VECTOR) return STRING is
+ constant ne : INTEGER := (value'length+3)/4;
+ variable pad : STD_LOGIC_VECTOR(0 to (ne*4 - value'length) - 1);
+ variable ivalue : STD_LOGIC_VECTOR(0 to ne*4 - 1);
+ variable result : STRING(1 to ne);
+ variable quad : STD_LOGIC_VECTOR(0 to 3);
+ begin
+ if value'length < 1 then
+ return NUS;
+ else
+ if value (value'left) = 'Z' then
+ pad := (others => 'Z');
+ else
+ pad := (others => '0');
+ end if;
+ ivalue := pad & value;
+ for i in 0 to ne-1 loop
+ quad := To_X01Z(ivalue(4*i to 4*i+3));
+ case quad is
+ when x"0" => result(i+1) := '0';
+ when x"1" => result(i+1) := '1';
+ when x"2" => result(i+1) := '2';
+ when x"3" => result(i+1) := '3';
+ when x"4" => result(i+1) := '4';
+ when x"5" => result(i+1) := '5';
+ when x"6" => result(i+1) := '6';
+ when x"7" => result(i+1) := '7';
+ when x"8" => result(i+1) := '8';
+ when x"9" => result(i+1) := '9';
+ when x"A" => result(i+1) := 'A';
+ when x"B" => result(i+1) := 'B';
+ when x"C" => result(i+1) := 'C';
+ when x"D" => result(i+1) := 'D';
+ when x"E" => result(i+1) := 'E';
+ when x"F" => result(i+1) := 'F';
+ when "ZZZZ" => result(i+1) := 'Z';
+ when others => result(i+1) := 'X';
+ end case;
+ end loop;
+ return result;
+ end if;
+ end function to_hstring;
+ procedure Char2TriBits (C : CHARACTER;
+ RESULT : out STD_LOGIC_VECTOR(2 downto 0);
+ GOOD : out BOOLEAN;
+ ISSUE_ERROR : in BOOLEAN) is
+ begin
+ case c is
+ when '0' => result := o"0"; good := true;
+ when '1' => result := o"1"; good := true;
+ when '2' => result := o"2"; good := true;
+ when '3' => result := o"3"; good := true;
+ when '4' => result := o"4"; good := true;
+ when '5' => result := o"5"; good := true;
+ when '6' => result := o"6"; good := true;
+ when '7' => result := o"7"; good := true;
+ when 'Z' => result := "ZZZ"; good := true;
+ when 'X' => result := "XXX"; good := true;
+ when others =>
+ assert not ISSUE_ERROR
+ report float_pkg'instance_name
+ & "OREAD Error: Read a '" & c &
+ "', expected an Octal character (0-7)."
+ severity error;
+ result := "UUU";
+ good := false;
+ end case;
+ end procedure Char2TriBits;
+
+ procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR;
+ GOOD : out BOOLEAN) is
+ variable ok : BOOLEAN;
+ variable c : CHARACTER;
+ constant ne : INTEGER := (VALUE'length+2)/3;
+ constant pad : INTEGER := ne*3 - VALUE'length;
+ variable sv : STD_LOGIC_VECTOR(0 to ne*3 - 1);
+ variable i : INTEGER;
+ variable lastu : BOOLEAN := false; -- last character was an "_"
+ begin
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ Skip_whitespace (L);
+ if VALUE'length > 0 then
+ read (l, c, ok);
+ i := 0;
+ while i < ne loop
+ -- Bail out if there was a bad read
+ if not ok then
+ good := false;
+ return;
+ elsif c = '_' then
+ if i = 0 then
+ good := false; -- Begins with an "_"
+ return;
+ elsif lastu then
+ good := false; -- "__" detected
+ return;
+ else
+ lastu := true;
+ end if;
+ else
+ Char2TriBits(c, sv(3*i to 3*i+2), ok, false);
+ if not ok then
+ good := false;
+ return;
+ end if;
+ i := i + 1;
+ lastu := false;
+ end if;
+ if i < ne then
+ read(L, c, ok);
+ end if;
+ end loop;
+ if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or"
+ good := false; -- vector was truncated.
+ else
+ good := true;
+ VALUE := sv (pad to sv'high);
+ end if;
+ else
+ good := true; -- read into a null array
+ end if;
+ end procedure OREAD;
+
+ -- Hex Read and Write procedures for STD_ULOGIC_VECTOR.
+ -- Modified from the original to be more forgiving.
+
+ procedure Char2QuadBits (C : CHARACTER;
+ RESULT : out STD_LOGIC_VECTOR(3 downto 0);
+ GOOD : out BOOLEAN;
+ ISSUE_ERROR : in BOOLEAN) is
+ begin
+ case c is
+ when '0' => result := x"0"; good := true;
+ when '1' => result := x"1"; good := true;
+ when '2' => result := x"2"; good := true;
+ when '3' => result := x"3"; good := true;
+ when '4' => result := x"4"; good := true;
+ when '5' => result := x"5"; good := true;
+ when '6' => result := x"6"; good := true;
+ when '7' => result := x"7"; good := true;
+ when '8' => result := x"8"; good := true;
+ when '9' => result := x"9"; good := true;
+ when 'A' | 'a' => result := x"A"; good := true;
+ when 'B' | 'b' => result := x"B"; good := true;
+ when 'C' | 'c' => result := x"C"; good := true;
+ when 'D' | 'd' => result := x"D"; good := true;
+ when 'E' | 'e' => result := x"E"; good := true;
+ when 'F' | 'f' => result := x"F"; good := true;
+ when 'Z' => result := "ZZZZ"; good := true;
+ when 'X' => result := "XXXX"; good := true;
+ when others =>
+ assert not ISSUE_ERROR
+ report float_pkg'instance_name
+ & "HREAD Error: Read a '" & c &
+ "', expected a Hex character (0-F)."
+ severity error;
+ result := "UUUU";
+ good := false;
+ end case;
+ end procedure Char2QuadBits;
+
+ procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR;
+ GOOD : out BOOLEAN) is
+ variable ok : BOOLEAN;
+ variable c : CHARACTER;
+ constant ne : INTEGER := (VALUE'length+3)/4;
+ constant pad : INTEGER := ne*4 - VALUE'length;
+ variable sv : STD_LOGIC_VECTOR(0 to ne*4 - 1);
+ variable i : INTEGER;
+ variable lastu : BOOLEAN := false; -- last character was an "_"
+ begin
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ Skip_whitespace (L);
+ if VALUE'length > 0 then
+ read (l, c, ok);
+ i := 0;
+ while i < ne loop
+ -- Bail out if there was a bad read
+ if not ok then
+ good := false;
+ return;
+ elsif c = '_' then
+ if i = 0 then
+ good := false; -- Begins with an "_"
+ return;
+ elsif lastu then
+ good := false; -- "__" detected
+ return;
+ else
+ lastu := true;
+ end if;
+ else
+ Char2QuadBits(c, sv(4*i to 4*i+3), ok, false);
+ if not ok then
+ good := false;
+ return;
+ end if;
+ i := i + 1;
+ lastu := false;
+ end if;
+ if i < ne then
+ read(L, c, ok);
+ end if;
+ end loop;
+ if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or"
+ good := false; -- vector was truncated.
+ else
+ good := true;
+ VALUE := sv (pad to sv'high);
+ end if;
+ else
+ good := true; -- Null input string, skips whitespace
+ end if;
+ end procedure HREAD;
+
+-- %%% END replicated textio functions
+
+ -- purpose: Checks the punctuation in a line
+ procedure check_punctuation (
+ arg : in STRING;
+ colon : out BOOLEAN; -- There was a colon in the line
+ dot : out BOOLEAN; -- There was a dot in the line
+ good : out BOOLEAN; -- True if enough characters found
+ chars : in INTEGER) is
+ -- Examples. Legal inputs are "0000000", "0000.000", "0:000:000"
+ alias xarg : STRING (1 to arg'length) is arg; -- make it downto range
+ variable icolon, idot : BOOLEAN; -- internal
+ variable j : INTEGER := 0; -- charters read
+ begin
+ good := false;
+ icolon := false;
+ idot := false;
+ for i in 1 to arg'length loop
+ if xarg(i) = ' ' or xarg(i) = NBSP or xarg(i) = HT or j = chars then
+ exit;
+ elsif xarg(i) = ':' then
+ icolon := true;
+ elsif xarg(i) = '.' then
+ idot := true;
+ elsif xarg (i) /= '_' then
+ j := j + 1;
+ end if;
+ end loop;
+ if j = chars then
+ good := true; -- There are enough charactes to read
+ end if;
+ colon := icolon;
+ if idot and icolon then
+ dot := false;
+ else
+ dot := idot;
+ end if;
+ end procedure check_punctuation;
+
+ -- purpose: Searches a line for a ":" and replaces it with a ".".
+ procedure fix_colon (
+ arg : inout STRING;
+ chars : in integer) is
+ alias xarg : STRING (1 to arg'length) is arg; -- make it downto range
+ variable j : INTEGER := 0; -- charters read
+ begin
+ for i in 1 to arg'length loop
+ if xarg(i) = ' ' or xarg(i) = NBSP or xarg(i) = HT or j > chars then
+ exit;
+ elsif xarg(i) = ':' then
+ xarg (i) := '.';
+ elsif xarg (i) /= '_' then
+ j := j + 1;
+ end if;
+ end loop;
+ end procedure fix_colon;
+
+ procedure WRITE (
+ L : inout LINE; -- input line
+ VALUE : in UNRESOLVED_float; -- floating point input
+ JUSTIFIED : in SIDE := right;
+ FIELD : in WIDTH := 0) is
+ variable s : STRING(1 to value'high - value'low +3);
+ variable sindx : INTEGER;
+ begin -- function write
+ s(1) := MVL9_to_char(STD_ULOGIC(VALUE(VALUE'high)));
+ s(2) := ':';
+ sindx := 3;
+ for i in VALUE'high-1 downto 0 loop
+ s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i)));
+ sindx := sindx + 1;
+ end loop;
+ s(sindx) := ':';
+ sindx := sindx + 1;
+ for i in -1 downto VALUE'low loop
+ s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i)));
+ sindx := sindx + 1;
+ end loop;
+ WRITE (L, s, JUSTIFIED, FIELD);
+ end procedure WRITE;
+
+ procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float) is
+ -- Possible data: 0:0000:0000000
+ -- 000000000000
+ variable c : CHARACTER;
+ variable mv : UNRESOLVED_float (VALUE'range);
+ variable readOk : BOOLEAN;
+ variable lastu : BOOLEAN := false; -- last character was an "_"
+ variable i : INTEGER; -- index variable
+ begin -- READ
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ Skip_whitespace (L);
+ READ (l, c, readOk);
+ if VALUE'length > 0 then
+ i := value'high;
+ readloop : loop
+ if readOk = false then -- Bail out if there was a bad read
+ report float_pkg'instance_name
+ & "READ(float): "
+ & "Error end of file encountered."
+ severity error;
+ return;
+ elsif c = ' ' or c = CR or c = HT then -- reading done.
+ if (i /= value'low) then
+ report float_pkg'instance_name
+ & "READ(float): "
+ & "Warning: Value truncated."
+ severity warning;
+ return;
+ end if;
+ elsif c = '_' then
+ if i = value'high then -- Begins with an "_"
+ report float_pkg'instance_name
+ & "READ(float): "
+ & "String begins with an ""_""" severity error;
+ return;
+ elsif lastu then -- "__" detected
+ report float_pkg'instance_name
+ & "READ(float): "
+ & "Two underscores detected in input string ""__"""
+ severity error;
+ return;
+ else
+ lastu := true;
+ end if;
+ elsif c = ':' or c = '.' then -- separator, ignore
+ if not (i = -1 or i = value'high-1) then
+ report float_pkg'instance_name
+ & "READ(float): "
+ & "Warning: Separator point does not match number format: '"
+ & c & "' encountered at location " & INTEGER'image(i) & "."
+ severity warning;
+ end if;
+ lastu := false;
+ elsif (char_to_MVL9plus(c) = error) then
+ report float_pkg'instance_name
+ & "READ(float): "
+ & "Error: Character '" & c & "' read, expected STD_ULOGIC literal."
+ severity error;
+ return;
+ else
+ mv (i) := char_to_MVL9(c);
+ i := i - 1;
+ if i < value'low then
+ VALUE := mv;
+ return;
+ end if;
+ lastu := false;
+ end if;
+ READ (l, c, readOk);
+ end loop readloop;
+ end if;
+ end procedure READ;
+
+ procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is
+ -- Possible data: 0:0000:0000000
+ -- 000000000000
+ variable c : CHARACTER;
+ variable mv : UNRESOLVED_float (VALUE'range);
+ variable lastu : BOOLEAN := false; -- last character was an "_"
+ variable i : INTEGER; -- index variable
+ variable readOk : BOOLEAN;
+ begin -- READ
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ Skip_whitespace (L);
+ READ (l, c, readOk);
+ if VALUE'length > 0 then
+ i := value'high;
+ good := false;
+ readloop : loop
+ if readOk = false then -- Bail out if there was a bad read
+ return;
+ elsif c = ' ' or c = CR or c = HT then -- reading done
+ return;
+ elsif c = '_' then
+ if i = 0 then -- Begins with an "_"
+ return;
+ elsif lastu then -- "__" detected
+ return;
+ else
+ lastu := true;
+ end if;
+ elsif c = ':' or c = '.' then -- separator, ignore
+ -- good := (i = -1 or i = value'high-1);
+ lastu := false;
+ elsif (char_to_MVL9plus(c) = error) then
+ return;
+ else
+ mv (i) := char_to_MVL9(c);
+ i := i - 1;
+ if i < value'low then
+ good := true;
+ VALUE := mv;
+ return;
+ end if;
+ lastu := false;
+ end if;
+ READ (l, c, readOk);
+ end loop readloop;
+ else
+ good := true; -- read into a null array
+ end if;
+ end procedure READ;
+
+ procedure OWRITE (
+ L : inout LINE; -- access type (pointer)
+ VALUE : in UNRESOLVED_float; -- value to write
+ JUSTIFIED : in SIDE := right; -- which side to justify text
+ FIELD : in WIDTH := 0) is -- width of field
+ begin
+ WRITE (L => L,
+ VALUE => to_ostring(VALUE),
+ JUSTIFIED => JUSTIFIED,
+ FIELD => FIELD);
+ end procedure OWRITE;
+
+ procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float) is
+ constant ne : INTEGER := ((value'length+2)/3) * 3; -- pad
+ variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv
+ variable slvu : ufixed (VALUE'range); -- Unsigned fixed point
+ variable c : CHARACTER;
+ variable ok : BOOLEAN;
+ variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits
+ variable colon, dot : BOOLEAN;
+ begin
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ Skip_whitespace (L);
+ if VALUE'length > 0 then
+ check_punctuation (arg => L.all,
+ colon => colon,
+ dot => dot,
+ good => ok,
+ chars => ne/3);
+ if not ok then
+ report float_pkg'instance_name & "OREAD: "
+ & "short string encounted: " & L.all
+ & " needs to have " & integer'image (ne/3)
+ & " valid octal characters."
+ severity error;
+ return;
+ elsif dot then
+ OREAD (L, slvu, ok); -- read it like a UFIXED number
+ if not ok then
+ report float_pkg'instance_name & "OREAD: "
+ & "error encounted reading STRING " & L.all
+ severity error;
+ return;
+ else
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ elsif colon then
+ OREAD (L, nybble, ok); -- read the sign bit
+ if not ok then
+ report float_pkg'instance_name & "OREAD: "
+ & "End of string encountered"
+ severity error;
+ return;
+ elsif nybble (2 downto 1) /= "00" then
+ report float_pkg'instance_name & "OREAD: "
+ & "Illegal sign bit STRING encounted "
+ severity error;
+ return;
+ end if;
+ read (l, c, ok); -- read the colon
+ fix_colon (L.all, ne/3); -- replaces the colon with a ".".
+ OREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number
+ if not ok then
+ report float_pkg'instance_name & "OREAD: "
+ & "error encounted reading STRING " & L.all
+ severity error;
+ return;
+ else
+ slvu (slvu'high) := nybble (0);
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ else
+ OREAD (L, slv, ok);
+ if not ok then
+ report float_pkg'instance_name & "OREAD: "
+ & "Error encounted during read"
+ severity error;
+ return;
+ end if;
+ if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then
+ report float_pkg'instance_name & "OREAD: "
+ & "Vector truncated."
+ severity error;
+ return;
+ end if;
+ VALUE := to_float (slv(VALUE'high-VALUE'low downto 0),
+ VALUE'high, -VALUE'low);
+ end if;
+ end if;
+ end procedure OREAD;
+
+ procedure OREAD(L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is
+ constant ne : INTEGER := ((value'length+2)/3) * 3; -- pad
+ variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv
+ variable slvu : ufixed (VALUE'range); -- Unsigned fixed point
+ variable c : CHARACTER;
+ variable ok : BOOLEAN;
+ variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits
+ variable colon, dot : BOOLEAN;
+ begin
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ GOOD := false;
+ Skip_whitespace (L);
+ if VALUE'length > 0 then
+ check_punctuation (arg => L.all,
+ colon => colon,
+ dot => dot,
+ good => ok,
+ chars => ne/3);
+ if not ok then
+ return;
+ elsif dot then
+ OREAD (L, slvu, ok); -- read it like a UFIXED number
+ if not ok then
+ return;
+ else
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ elsif colon then
+ OREAD (L, nybble, ok); -- read the sign bit
+ if not ok then
+ return;
+ elsif nybble (2 downto 1) /= "00" then
+ return;
+ end if;
+ read (l, c, ok); -- read the colon
+ fix_colon (L.all, ne/3); -- replaces the colon with a ".".
+ OREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number
+ if not ok then
+ return;
+ else
+ slvu (slvu'high) := nybble (0);
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ else
+ OREAD (L, slv, ok);
+ if not ok then
+ return;
+ end if;
+ if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then
+ return;
+ end if;
+ VALUE := to_float (slv(VALUE'high-VALUE'low downto 0),
+ VALUE'high, -VALUE'low);
+ end if;
+ GOOD := true;
+ end if;
+ end procedure OREAD;
+
+ procedure HWRITE (
+ L : inout LINE; -- access type (pointer)
+ VALUE : in UNRESOLVED_float; -- value to write
+ JUSTIFIED : in SIDE := right; -- which side to justify text
+ FIELD : in WIDTH := 0) is -- width of field
+ begin
+ WRITE (L => L,
+ VALUE => to_hstring(VALUE),
+ JUSTIFIED => JUSTIFIED,
+ FIELD => FIELD);
+ end procedure HWRITE;
+
+ procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float) is
+ constant ne : INTEGER := ((value'length+3)/4) * 4; -- pad
+ variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv
+ variable slvu : ufixed (VALUE'range); -- Unsigned fixed point
+ variable c : CHARACTER;
+ variable ok : BOOLEAN;
+ variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits
+ variable colon, dot : BOOLEAN;
+ begin
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ Skip_whitespace (L);
+ if VALUE'length > 0 then
+ check_punctuation (arg => L.all,
+ colon => colon,
+ dot => dot,
+ good => ok,
+ chars => ne/4);
+ if not ok then
+ report float_pkg'instance_name & "HREAD: "
+ & "short string encounted: " & L.all
+ & " needs to have " & integer'image (ne/4)
+ & " valid hex characters."
+ severity error;
+ return;
+ elsif dot then
+ HREAD (L, slvu, ok); -- read it like a UFIXED number
+ if not ok then
+ report float_pkg'instance_name & "HREAD: "
+ & "error encounted reading STRING " & L.all
+ severity error;
+ return;
+ else
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ elsif colon then
+ HREAD (L, nybble, ok); -- read the sign bit
+ if not ok then
+ report float_pkg'instance_name & "HREAD: "
+ & "End of string encountered"
+ severity error;
+ return;
+ elsif nybble (3 downto 1) /= "000" then
+ report float_pkg'instance_name & "HREAD: "
+ & "Illegal sign bit STRING encounted "
+ severity error;
+ return;
+ end if;
+ read (l, c, ok); -- read the colon
+ fix_colon (L.all, ne/4); -- replaces the colon with a ".".
+ HREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number
+ if not ok then
+ report float_pkg'instance_name & "HREAD: "
+ & "error encounted reading STRING " & L.all
+ severity error;
+ return;
+ else
+ slvu (slvu'high) := nybble (0);
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ else
+ HREAD (L, slv, ok);
+ if not ok then
+ report float_pkg'instance_name & "HREAD: "
+ & "Error encounted during read"
+ severity error;
+ return;
+ end if;
+ if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then
+ report float_pkg'instance_name & "HREAD: "
+ & "Vector truncated."
+ severity error;
+ return;
+ end if;
+ VALUE := to_float (slv(VALUE'high-VALUE'low downto 0),
+ VALUE'high, -VALUE'low);
+ end if;
+ end if;
+ end procedure HREAD;
+
+ procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is
+ constant ne : INTEGER := ((value'length+3)/4) * 4; -- pad
+ variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv
+ variable slvu : ufixed (VALUE'range); -- Unsigned fixed point
+ variable c : CHARACTER;
+ variable ok : BOOLEAN;
+ variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits
+ variable colon, dot : BOOLEAN;
+ begin
+ VALUE := (VALUE'range => 'U'); -- initialize to a "U"
+ GOOD := false;
+ Skip_whitespace (L);
+ if VALUE'length > 0 then
+ check_punctuation (arg => L.all,
+ colon => colon,
+ dot => dot,
+ good => ok,
+ chars => ne/4);
+ if not ok then
+ return;
+ elsif dot then
+ HREAD (L, slvu, ok); -- read it like a UFIXED number
+ if not ok then
+ return;
+ else
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ elsif colon then
+ HREAD (L, nybble, ok); -- read the sign bit
+ if not ok then
+ return;
+ elsif nybble (3 downto 1) /= "000" then
+ return;
+ end if;
+ read (l, c, ok); -- read the colon
+ fix_colon (L.all, ne/4); -- replaces the colon with a ".".
+ HREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number
+ if not ok then
+ return;
+ else
+ slvu (slvu'high) := nybble (0);
+ VALUE := UNRESOLVED_float (slvu);
+ end if;
+ else
+ HREAD (L, slv, ok);
+ if not ok then
+ return;
+ end if;
+ if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then
+ return;
+ end if;
+ VALUE := to_float (slv(VALUE'high-VALUE'low downto 0),
+ VALUE'high, -VALUE'low);
+ end if;
+ GOOD := true;
+ end if;
+ end procedure HREAD;
+
+ function to_string (value : UNRESOLVED_float) return STRING is
+ variable s : STRING(1 to value'high - value'low +3);
+ variable sindx : INTEGER;
+ begin -- function write
+ s(1) := MVL9_to_char(STD_ULOGIC(VALUE(VALUE'high)));
+ s(2) := ':';
+ sindx := 3;
+ for i in VALUE'high-1 downto 0 loop
+ s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i)));
+ sindx := sindx + 1;
+ end loop;
+ s(sindx) := ':';
+ sindx := sindx + 1;
+ for i in -1 downto VALUE'low loop
+ s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i)));
+ sindx := sindx + 1;
+ end loop;
+ return s;
+ end function to_string;
+
+ function to_hstring (value : UNRESOLVED_float) return STRING is
+ variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0);
+ begin
+ floop : for i in slv'range loop
+ slv(i) := to_X01Z (value(i + value'low));
+ end loop floop;
+ return to_hstring (slv);
+ end function to_hstring;
+
+ function to_ostring (value : UNRESOLVED_float) return STRING is
+ variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0);
+ begin
+ floop : for i in slv'range loop
+ slv(i) := to_X01Z (value(i + value'low));
+ end loop floop;
+ return to_ostring (slv);
+ end function to_ostring;
+
+ function from_string (
+ bstring : STRING; -- binary string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable L : LINE;
+ variable good : BOOLEAN;
+ begin
+ L := new STRING'(bstring);
+ READ (L, result, good);
+ deallocate (L);
+ assert (good)
+ report float_pkg'instance_name
+ & "from_string: Bad string " & bstring
+ severity error;
+ return result;
+ end function from_string;
+
+ function from_ostring (
+ ostring : STRING; -- Octal string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable L : LINE;
+ variable good : BOOLEAN;
+ begin
+ L := new STRING'(ostring);
+ OREAD (L, result, good);
+ deallocate (L);
+ assert (good)
+ report float_pkg'instance_name
+ & "from_ostring: Bad string " & ostring
+ severity error;
+ return result;
+ end function from_ostring;
+
+ function from_hstring (
+ hstring : STRING; -- hex string
+ constant exponent_width : NATURAL := float_exponent_width;
+ constant fraction_width : NATURAL := float_fraction_width)
+ return UNRESOLVED_float is
+ variable result : UNRESOLVED_float (exponent_width downto -fraction_width);
+ variable L : LINE;
+ variable good : BOOLEAN;
+ begin
+ L := new STRING'(hstring);
+ HREAD (L, result, good);
+ deallocate (L);
+ assert (good)
+ report float_pkg'instance_name
+ & "from_hstring: Bad string " & hstring
+ severity error;
+ return result;
+ end function from_hstring;
+
+ function from_string (
+ bstring : STRING; -- binary string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float is
+ begin
+ return from_string (bstring => bstring,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function from_string;
+
+ function from_ostring (
+ ostring : STRING; -- Octal string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float is
+ begin
+ return from_ostring (ostring => ostring,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function from_ostring;
+
+ function from_hstring (
+ hstring : STRING; -- hex string
+ size_res : UNRESOLVED_float) -- used for sizing only
+ return UNRESOLVED_float is
+ begin
+ return from_hstring (hstring => hstring,
+ exponent_width => size_res'high,
+ fraction_width => -size_res'low);
+ end function from_hstring;
+-- rtl_synthesis on
+-- pragma synthesis_on
+
+
+
+
+end package body float_pkg;
diff --git a/common_pkg/float_pkg_c_2008redirect.vhdl b/common_pkg/float_pkg_c_2008redirect.vhdl
new file mode 100755
index 00000000..9540de08
--- /dev/null
+++ b/common_pkg/float_pkg_c_2008redirect.vhdl
@@ -0,0 +1,58 @@
+-- -----------------------------------------------------------------
+--
+-- Copyright 2019 IEEE P1076 WG Authors
+--
+-- See the LICENSE file distributed with this work for copyright and
+-- licensing information and the AUTHORS file.
+--
+-- This file to you under the Apache License, Version 2.0 (the "License").
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+-- implied. See the License for the specific language governing
+-- permissions and limitations under the License.
+--
+-- Title : Floating-point package (Instantiated package declaration)
+-- :
+-- Library : This package shall be compiled into a library
+-- : symbolically named IEEE.
+-- :
+-- Developers: Accellera VHDL-TC and IEEE P1076 Working Group
+-- :
+-- Purpose : This packages defines basic binary floating point
+-- : arithmetic functions
+-- :
+-- 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) $
+-- --------------------------------------------------------------------
+
+library ieee;
+library common_pkg_lib;
+use common_pkg_lib.common_fixed_float_types.all;
+use common_pkg_lib.fixed_pkg.all;
+
+package float_pkg is new common_pkg_lib.float_generic_pkg
+ generic map (
+ float_exponent_width => 8, -- float32'high
+ float_fraction_width => 23, -- -float32'low
+ float_round_style => common_pkg_lib.common_fixed_float_types.round_nearest, -- round nearest algorithm
+ float_denormalize => true, -- Use IEEE extended floating
+ float_check_error => true, -- Turn on NAN and overflow processing
+ float_guard_bits => 3, -- number of guard bits
+ no_warning => false, -- show warnings
+ fixed_pkg => common_pkg_lib.fixed_pkg
+ );
diff --git a/common_pkg/tb_common_pkg.vhd b/common_pkg/tb_common_pkg.vhd
index 502e30f9..c0664705 100644
--- a/common_pkg/tb_common_pkg.vhd
+++ b/common_pkg/tb_common_pkg.vhd
@@ -304,6 +304,21 @@ PACKAGE tb_common_pkg IS
PROCEDURE proc_common_read_mem_file(file_name : IN STRING;
SIGNAL return_array : OUT t_integer_arr);
+ PROCEDURE csv_parse_line_to_array(line_in : IN STRING;
+ delimiter : IN CHARACTER;
+ value_array : OUT t_nat_integer_arr;
+ nof_values : OUT INTEGER);
+ PROCEDURE csv_read_file_to_array(file_status : INOUT FILE_OPEN_STATUS;
+ FILE in_file : TEXT;
+ value_matrix : OUT t_nat_integer_matrix;
+ max_lines : IN INTEGER;
+ delimiter : IN CHARACTER);
+
+ PROCEDURE csv_open_and_read_file(file_name : IN STRING;
+ value_matrix : OUT t_nat_integer_matrix;
+ max_lines : IN INTEGER;
+ delimiter : IN CHARACTER);
+
-- Complex multiply function with conjugate option for input b
FUNCTION func_complex_multiply(in_ar, in_ai, in_br, in_bi : STD_LOGIC_VECTOR; conjugate_b : BOOLEAN; str : STRING; g_out_dat_w : NATURAL) RETURN STD_LOGIC_VECTOR;
@@ -1262,6 +1277,97 @@ PACKAGE BODY tb_common_pkg IS
proc_common_close_file(v_file_status, v_in_file);
END proc_common_read_mem_file;
+ ------------------------------------------------------------------------------
+ -- PROCEDURE: Parses a line of text into an integer array using a specified delimiter.
+ ------------------------------------------------------------------------------
+ PROCEDURE csv_parse_line_to_array(line_in : IN STRING;
+ delimiter : IN CHARACTER;
+ value_array : OUT t_nat_integer_arr;
+ nof_values : OUT INTEGER) IS
+ VARIABLE v_idx : INTEGER := 1;
+ VARIABLE v_len : INTEGER := line_in'LENGTH;
+ VARIABLE v_start : INTEGER := 1;
+ VARIABLE v_cnt_vals : INTEGER := 0;
+ VARIABLE v_substr : STRING(1 TO 100);
+ VARIABLE v_int : INTEGER;
+ VARIABLE v_good : BOOLEAN;
+ VARIABLE v_subline : LINE;
+ BEGIN
+ WHILE v_start <= v_len LOOP
+ -- Find the next delimiter position
+ v_idx := v_start;
+ WHILE v_idx <= v_len AND line_in(v_idx) /= delimiter LOOP
+ v_idx := v_idx + 1;
+ END LOOP;
+ -- Extract substring
+ IF v_idx > v_start THEN
+ v_substr := line_in(v_start TO v_idx - 1);
+ ELSE
+ v_substr := line_in(v_start TO v_len);
+ END IF;
+ -- Convert substring to integer
+ WRITE(v_subline, v_substr);
+ READ(v_subline, v_int, v_good);
+ IF v_good = FALSE THEN
+ REPORT "COMMON : Read from line unsuccessful " SEVERITY FAILURE;
+ END IF;
+ value_array(v_cnt_vals) := v_int;
+ v_cnt_vals := v_cnt_vals + 1;
+ -- Move to the next part of the line
+ v_start := v_idx + 1;
+ END LOOP;
+ nof_values := v_cnt_vals;
+ END csv_parse_line_to_array;
+
+ ------------------------------------------------------------------------------
+ -- PROCEDURE: Reads a file line by line and populates an array of integer arrays.
+ ------------------------------------------------------------------------------
+ PROCEDURE csv_read_file_to_array(file_status : INOUT FILE_OPEN_STATUS;
+ FILE in_file : TEXT;
+ value_matrix : OUT t_nat_integer_matrix;
+ max_lines : IN INTEGER;
+ delimiter : IN CHARACTER) IS
+ VARIABLE v_line : LINE;
+ VARIABLE v_array : t_nat_integer_arr(0 TO 100); -- Adjust size as needed
+ VARIABLE v_nof_values : INTEGER;
+ VARIABLE v_line_idx : INTEGER := 0;
+ BEGIN
+ IF file_status /= OPEN_OK THEN
+ REPORT "COMMON : File is not opened " SEVERITY FAILURE;
+ ELSE
+ WHILE NOT ENDFILE(in_file) AND v_line_idx < max_lines LOOP
+ READLINE(in_file, v_line);
+ csv_parse_line_to_array(v_line.all, delimiter, v_array, v_nof_values);
+ FOR i IN 0 TO v_nof_values - 1 LOOP
+ value_matrix(v_line_idx, i) := v_array(i);
+ END LOOP;
+ v_line_idx := v_line_idx + 1;
+ END LOOP;
+ END IF;
+ END csv_read_file_to_array;
+
+ ------------------------------------------------------------------------------
+ -- PROCEDURE: Opens a file and calls read_file_to_array to process it.
+ ------------------------------------------------------------------------------
+ PROCEDURE csv_open_and_read_file(file_name : IN STRING;
+ value_matrix : OUT t_nat_integer_matrix;
+ max_lines : IN INTEGER;
+ delimiter : IN CHARACTER) IS
+ FILE in_file : TEXT;
+ VARIABLE file_status : FILE_OPEN_STATUS;
+ BEGIN
+ -- Open the file
+ proc_common_open_file(file_status, in_file, file_name, READ_MODE);
+ IF file_status /= OPEN_OK THEN
+ REPORT "COMMON : Unable to open file " & file_name SEVERITY FAILURE;
+ ELSE
+ -- Call read_file_to_array to process the file
+ csv_read_file_to_array(file_status, in_file, value_matrix, max_lines, delimiter);
+ -- Close the file
+ FILE_CLOSE(in_file);
+ END IF;
+ END csv_open_and_read_file;
+
------------------------------------------------------------------------------
-- FUNCTION: Complex multiply with conjugate option for input b
------------------------------------------------------------------------------
diff --git a/common_slv_arr_pkg/common_slv_arr_pkg.vhd b/common_slv_arr_pkg/common_slv_arr_pkg.vhd
new file mode 100644
index 00000000..3c7fef91
--- /dev/null
+++ b/common_slv_arr_pkg/common_slv_arr_pkg.vhd
@@ -0,0 +1,65 @@
+-- Abstraction of sl_mat as an SLV array.
+-- Inspired by https://stackoverflow.com/a/28514135
+-- @author: Ross Donnachie
+-- @company: Mydon Solutions
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.all;
+
+package common_slv_arr_pkg is
+ type t_slv_arr is array(natural range <>, natural range <>) of std_logic;
+
+ procedure slv_arr_set(signal slv_arr : out t_slv_arr; constant idx : natural; signal slv : in std_logic_vector);
+ procedure slv_arr_set_variable(signal slv_arr : out t_slv_arr; constant idx : natural; variable slv : in std_logic_vector);
+ procedure slv_arr_set(signal slv_arr : out t_slv_arr; constant out_idx : natural; signal slv_arr_in : in t_slv_arr; constant in_idx : natural);
+
+ procedure slv_arr_get(signal slv : out std_logic_vector; signal slv_arr : in t_slv_arr; constant idx : natural);
+ procedure slv_arr_get_variable(variable slv : out std_logic_vector; signal slv_arr : in t_slv_arr; constant idx : natural);
+ function slv_arr_index(signal slv_arr : in t_slv_arr; constant idx : natural) return std_logic_vector;
+end package;
+
+package body common_slv_arr_pkg is
+ procedure slv_arr_set(signal slv_arr : out t_slv_arr; constant idx : natural; signal slv : in std_logic_vector) is
+ begin
+ for i in slv'range loop
+ slv_arr(idx, i) <= slv(i);
+ end loop;
+ end procedure;
+
+ procedure slv_arr_set_variable(signal slv_arr : out t_slv_arr; constant idx : natural; variable slv : in std_logic_vector) is
+ begin
+ for i in slv'range loop
+ slv_arr(idx, i) <= slv(i);
+ end loop;
+ end procedure;
+
+ procedure slv_arr_set(signal slv_arr : out t_slv_arr; constant out_idx : natural; signal slv_arr_in : in t_slv_arr; constant in_idx : natural) is
+ begin
+ for i in slv_arr_in'range(2) loop
+ slv_arr(out_idx, i) <= slv_arr_in(in_idx, i);
+ end loop;
+ end procedure;
+
+ procedure slv_arr_get(signal slv : out std_logic_vector; signal slv_arr : in t_slv_arr; constant idx : natural) is
+ begin
+ for i in slv'range loop
+ slv(i) <= slv_arr(idx, i);
+ end loop;
+ end procedure;
+
+ procedure slv_arr_get_variable(variable slv : out std_logic_vector; signal slv_arr : in t_slv_arr; constant idx : natural) is
+ begin
+ for i in slv'range loop
+ slv(i) := slv_arr(idx, i);
+ end loop;
+ end procedure;
+
+ function slv_arr_index(signal slv_arr : in t_slv_arr; constant idx : natural) return std_logic_vector is
+ variable result: STD_LOGIC_VECTOR(slv_arr'RANGE(2));
+ begin
+ for i in slv_arr'range(2) loop
+ result(i) := slv_arr(idx, i);
+ end loop;
+ return result;
+ end function;
+end package body;
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000..3ee5d723
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1 @@
+Only the `sphinx` python module is required to `make` the documentation. On windows the following is executed: `./make.bat html`.
\ No newline at end of file
diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle
deleted file mode 100644
index 004b3449..00000000
Binary files a/docs/build/doctrees/environment.pickle and /dev/null differ
diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree
deleted file mode 100644
index c2d0b5a6..00000000
Binary files a/docs/build/doctrees/index.doctree and /dev/null differ
diff --git a/docs/build/doctrees/r2sdf_fft.doctree b/docs/build/doctrees/r2sdf_fft.doctree
deleted file mode 100644
index b1aab3d8..00000000
Binary files a/docs/build/doctrees/r2sdf_fft.doctree and /dev/null differ
diff --git a/docs/build/doctrees/wideband_fft.doctree b/docs/build/doctrees/wideband_fft.doctree
deleted file mode 100644
index 0a86e18e..00000000
Binary files a/docs/build/doctrees/wideband_fft.doctree and /dev/null differ
diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo
deleted file mode 100644
index 50f0fa3e..00000000
--- a/docs/build/html/.buildinfo
+++ /dev/null
@@ -1,4 +0,0 @@
-# Sphinx build info version 1
-# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
-config: faa97ef624a4da3622056b75c245694b
-tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/docs/build/html/_images/dif_butterfly.png b/docs/build/html/_images/dif_butterfly.png
deleted file mode 100644
index cbade224..00000000
Binary files a/docs/build/html/_images/dif_butterfly.png and /dev/null differ
diff --git a/docs/build/html/_images/dif_butterfly_quant.png b/docs/build/html/_images/dif_butterfly_quant.png
deleted file mode 100644
index 3af255b6..00000000
Binary files a/docs/build/html/_images/dif_butterfly_quant.png and /dev/null differ
diff --git a/docs/build/html/_images/fft_r2_par.png b/docs/build/html/_images/fft_r2_par.png
deleted file mode 100644
index 6fb3f544..00000000
Binary files a/docs/build/html/_images/fft_r2_par.png and /dev/null differ
diff --git a/docs/build/html/_images/fft_r2_pipe.png b/docs/build/html/_images/fft_r2_pipe.png
deleted file mode 100644
index 249e9169..00000000
Binary files a/docs/build/html/_images/fft_r2_pipe.png and /dev/null differ
diff --git a/docs/build/html/_images/fft_r2_wide.png b/docs/build/html/_images/fft_r2_wide.png
deleted file mode 100644
index 933573d2..00000000
Binary files a/docs/build/html/_images/fft_r2_wide.png and /dev/null differ
diff --git a/docs/build/html/_images/wideband_fft_slim_base.png b/docs/build/html/_images/wideband_fft_slim_base.png
deleted file mode 100644
index 436cfad7..00000000
Binary files a/docs/build/html/_images/wideband_fft_slim_base.png and /dev/null differ
diff --git a/docs/build/html/_images/wideband_fft_slim_expanded.png b/docs/build/html/_images/wideband_fft_slim_expanded.png
deleted file mode 100644
index ac29a2d6..00000000
Binary files a/docs/build/html/_images/wideband_fft_slim_expanded.png and /dev/null differ
diff --git a/docs/build/html/_images/widebandunit_overview.png b/docs/build/html/_images/widebandunit_overview.png
deleted file mode 100644
index 3eb19f16..00000000
Binary files a/docs/build/html/_images/widebandunit_overview.png and /dev/null differ
diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt
deleted file mode 100644
index 6fb95490..00000000
--- a/docs/build/html/_sources/index.rst.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-CASPER's DSP Development Documentation
-======================================
-
-Contained herein is the documentation for the HDL IP cores maintained by the CASPER community.
-These may be pulled into mlib_devel toolflow by pointing the HDL_DSP_DEVEL_PATH environment variable to the cloned casper_dspdevel repository.
-
-IP Cores:
----------
-.. toctree::
- :maxdepth: 4
-
- wideband_fft
- r2sdf_fft
-
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
diff --git a/docs/build/html/_sources/r2sdf_fft.rst.txt b/docs/build/html/_sources/r2sdf_fft.rst.txt
deleted file mode 100644
index 97ff8622..00000000
--- a/docs/build/html/_sources/r2sdf_fft.rst.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-.. _r2sdf_fft:
-
-R2SDF FFT
-=========
\ No newline at end of file
diff --git a/docs/build/html/_sources/wideband_fft.rst.txt b/docs/build/html/_sources/wideband_fft.rst.txt
deleted file mode 100644
index 30651518..00000000
--- a/docs/build/html/_sources/wideband_fft.rst.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-Wideband FFT
-=============
-
-Purpose:
---------
-This FFT was originally sourced from ASTRON via OpenCores. It performs an N-Point Wideband FFT on data that is partly applied in serial and partly applied in
-parallel. This FFT specifically suits applications where the sample clock is higher than the DSP processing clock. For each output stream a subband statistic
-unit is included which can be read via the memory mapped interface.
-
-Module Overview:
-----------------
-An overview of the fft_wide unit is shown in Figure 1. The fft_wide unit calculates a N-point FFT and has P
-number of input streams. Data of each input is offered to a M-point pipelined FFT, where M=N/P. The output
-of all pipelined FFTs is then connected to a P-point parallel FFT that performs the final stage of the wideband
-FFT. Each output of the parallel FFT is connected to a subband statistics unit that calculates the power in
-each subband. The MM interface is used to read out the subband statistics.
-The rTwoSDF pipelined FFT (see :ref:`r2sdf_fft`) design is used as building block for the development of the wideband extension.
-
-.. figure:: ./_images/widebandunit_overview.png
- :width: 650px
- :align: center
- :figclass: align-center
-
-Figure 1: FFT Wideband Unit Overview
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-
-
-Firmware Interface:
--------------------
-
-Clock Domains
-~~~~~~~~~~~~~
-There are two clock domains used in the fft_wide unit: the mm_clk and the dp_clk domain. Figure 2 shows
-an overview of the clock domains in the fft_wide unit. The only unit that is connected to both clock domains is
-the memory of the subband statistics module. This memory is a dual ported ram that holds the results of the
-subband statistics. Table 1 lists both clocks and their characteristics.
-
-+--------+----------------+------------------------+
-| Name | Frequency (MHz)| Description |
-+========+================+========================+
-| DP_CLK | 200 MHz | Clock for datapath |
-+--------+----------------+------------------------+
-| MM_CLK | 125 MHz | Clock for mm interface |
-+--------+----------------+------------------------+
-
-Parameters
-~~~~~~~~~~
-+----------------+---------+-------+----------------------------------------------------------------+
-| Generic | Type | Value | Description |
-+================+=========+=======+================================================================+
-| use_reorder | Boolean | true | When set to ‘true’, the output bins of the FFT are reordered |
-| | | | in such a way that the first bin represents the lowest |
-| | | | frequency and the highest bin represents the highest frequency.|
-+----------------+---------+-------+----------------------------------------------------------------+
-| use_fft_shift | Boolean | true | False for [0, pos, neg] bin frequencies order, true for |
-| | | | [neg, 0, pos] bin frequencies order in case of complex input |
-+----------------+---------+-------+----------------------------------------------------------------+
-| use_separate | Boolean | true | When set to ‘true’ a separate algorithm will be enabled in |
-| | | | order to retrieve two separate spectra from the output of the |
-| | | | complex FFT in case both the real and imaginary input of the |
-| | | | complex FFT are fed with two independent real signals. |
-+----------------+---------+-------+----------------------------------------------------------------+
-| nof_chan | Natural | 0 | Defines the number of channels (=time-multiplexed input |
-| | | | signals). The number of channels is :math:`2^{nof\_channels}`. |
-| | | | Multiple channels is only supported by the pipelined FFT. |
-+----------------+---------+-------+----------------------------------------------------------------+
-| wb_factor=P | Natural | 4 | The number that defines the wideband factor. It defines the |
-| | | | number of parallel pipelined FFTs. |
-+----------------+---------+-------+----------------------------------------------------------------+
-| twiddle_offset | Natural | 0 | The twiddle offset is used for the pipelined sections in the |
-| | | | wideband configuration. |
-+----------------+---------+-------+----------------------------------------------------------------+
-| nof_points = N | Natural | 1024 | The number of points of the FFT. |
-+----------------+---------+-------+----------------------------------------------------------------+
-| in_dat_w | Natural | 8 | Width in bits of the input data. This value specifies the |
-| | | | width of both the real and the imaginary part. |
-+----------------+---------+-------+----------------------------------------------------------------+
-| out_dat_w | Natural | 14 | The bitwidth of the real and imaginary part of the output of |
-| | | | the FFT. The relation with the in_dat_w is as follows: |
-| | | | :math:`out\_dat\_w=in\_dat\_w+(\log2(nof\_N))/{2+1}`. |
-+----------------+---------+-------+----------------------------------------------------------------+
-| stage_dat_w | Natural | 18 | The bitwidth of the data that is used between the stages |
-| | | | (=DSP multiplier-width). |
-+----------------+---------+-------+----------------------------------------------------------------+
-| guard_w | Natural | 2 | Number of bits that function as guard bits. The guard bits are |
-| | | | required to avoid overflow in the first two stages of the FFT. |
-+----------------+---------+-------+----------------------------------------------------------------+
-| guard_enable | Boolean | true | When set to ‘true’ the input is guarded during the input resize|
-| | | | function, when set to ‘false’ the input is not guarded, but the|
-| | | | scaling is not skipped on the last stages of the FFT (based on |
-| | | | the value of guard_w). |
-+----------------+---------+-------+----------------------------------------------------------------+
diff --git a/docs/build/html/_static/basic.css b/docs/build/html/_static/basic.css
deleted file mode 100644
index 4984b305..00000000
--- a/docs/build/html/_static/basic.css
+++ /dev/null
@@ -1,856 +0,0 @@
-/*
- * basic.css
- * ~~~~~~~~~
- *
- * Sphinx stylesheet -- basic theme.
- *
- * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
- * :license: BSD, see LICENSE for details.
- *
- */
-
-/* -- main layout ----------------------------------------------------------- */
-
-div.clearer {
- clear: both;
-}
-
-div.section::after {
- display: block;
- content: '';
- clear: left;
-}
-
-/* -- relbar ---------------------------------------------------------------- */
-
-div.related {
- width: 100%;
- font-size: 90%;
-}
-
-div.related h3 {
- display: none;
-}
-
-div.related ul {
- margin: 0;
- padding: 0 0 0 10px;
- list-style: none;
-}
-
-div.related li {
- display: inline;
-}
-
-div.related li.right {
- float: right;
- margin-right: 5px;
-}
-
-/* -- sidebar --------------------------------------------------------------- */
-
-div.sphinxsidebarwrapper {
- padding: 10px 5px 0 10px;
-}
-
-div.sphinxsidebar {
- float: left;
- width: 230px;
- margin-left: -100%;
- font-size: 90%;
- word-wrap: break-word;
- overflow-wrap : break-word;
-}
-
-div.sphinxsidebar ul {
- list-style: none;
-}
-
-div.sphinxsidebar ul ul,
-div.sphinxsidebar ul.want-points {
- margin-left: 20px;
- list-style: square;
-}
-
-div.sphinxsidebar ul ul {
- margin-top: 0;
- margin-bottom: 0;
-}
-
-div.sphinxsidebar form {
- margin-top: 10px;
-}
-
-div.sphinxsidebar input {
- border: 1px solid #98dbcc;
- font-family: sans-serif;
- font-size: 1em;
-}
-
-div.sphinxsidebar #searchbox form.search {
- overflow: hidden;
-}
-
-div.sphinxsidebar #searchbox input[type="text"] {
- float: left;
- width: 80%;
- padding: 0.25em;
- box-sizing: border-box;
-}
-
-div.sphinxsidebar #searchbox input[type="submit"] {
- float: left;
- width: 20%;
- border-left: none;
- padding: 0.25em;
- box-sizing: border-box;
-}
-
-
-img {
- border: 0;
- max-width: 100%;
-}
-
-/* -- search page ----------------------------------------------------------- */
-
-ul.search {
- margin: 10px 0 0 20px;
- padding: 0;
-}
-
-ul.search li {
- padding: 5px 0 5px 20px;
- background-image: url(file.png);
- background-repeat: no-repeat;
- background-position: 0 7px;
-}
-
-ul.search li a {
- font-weight: bold;
-}
-
-ul.search li div.context {
- color: #888;
- margin: 2px 0 0 30px;
- text-align: left;
-}
-
-ul.keywordmatches li.goodmatch a {
- font-weight: bold;
-}
-
-/* -- index page ------------------------------------------------------------ */
-
-table.contentstable {
- width: 90%;
- margin-left: auto;
- margin-right: auto;
-}
-
-table.contentstable p.biglink {
- line-height: 150%;
-}
-
-a.biglink {
- font-size: 1.3em;
-}
-
-span.linkdescr {
- font-style: italic;
- padding-top: 5px;
- font-size: 90%;
-}
-
-/* -- general index --------------------------------------------------------- */
-
-table.indextable {
- width: 100%;
-}
-
-table.indextable td {
- text-align: left;
- vertical-align: top;
-}
-
-table.indextable ul {
- margin-top: 0;
- margin-bottom: 0;
- list-style-type: none;
-}
-
-table.indextable > tbody > tr > td > ul {
- padding-left: 0em;
-}
-
-table.indextable tr.pcap {
- height: 10px;
-}
-
-table.indextable tr.cap {
- margin-top: 10px;
- background-color: #f2f2f2;
-}
-
-img.toggler {
- margin-right: 3px;
- margin-top: 3px;
- cursor: pointer;
-}
-
-div.modindex-jumpbox {
- border-top: 1px solid #ddd;
- border-bottom: 1px solid #ddd;
- margin: 1em 0 1em 0;
- padding: 0.4em;
-}
-
-div.genindex-jumpbox {
- border-top: 1px solid #ddd;
- border-bottom: 1px solid #ddd;
- margin: 1em 0 1em 0;
- padding: 0.4em;
-}
-
-/* -- domain module index --------------------------------------------------- */
-
-table.modindextable td {
- padding: 2px;
- border-collapse: collapse;
-}
-
-/* -- general body styles --------------------------------------------------- */
-
-div.body {
- min-width: 0;
- max-width: none;
-}
-
-div.body p, div.body dd, div.body li, div.body blockquote {
- -moz-hyphens: auto;
- -ms-hyphens: auto;
- -webkit-hyphens: auto;
- hyphens: auto;
-}
-
-a.headerlink {
- visibility: hidden;
-}
-
-a.brackets:before,
-span.brackets > a:before{
- content: "[";
-}
-
-a.brackets:after,
-span.brackets > a:after {
- content: "]";
-}
-
-h1:hover > a.headerlink,
-h2:hover > a.headerlink,
-h3:hover > a.headerlink,
-h4:hover > a.headerlink,
-h5:hover > a.headerlink,
-h6:hover > a.headerlink,
-dt:hover > a.headerlink,
-caption:hover > a.headerlink,
-p.caption:hover > a.headerlink,
-div.code-block-caption:hover > a.headerlink {
- visibility: visible;
-}
-
-div.body p.caption {
- text-align: inherit;
-}
-
-div.body td {
- text-align: left;
-}
-
-.first {
- margin-top: 0 !important;
-}
-
-p.rubric {
- margin-top: 30px;
- font-weight: bold;
-}
-
-img.align-left, .figure.align-left, object.align-left {
- clear: left;
- float: left;
- margin-right: 1em;
-}
-
-img.align-right, .figure.align-right, object.align-right {
- clear: right;
- float: right;
- margin-left: 1em;
-}
-
-img.align-center, .figure.align-center, object.align-center {
- display: block;
- margin-left: auto;
- margin-right: auto;
-}
-
-img.align-default, .figure.align-default {
- display: block;
- margin-left: auto;
- margin-right: auto;
-}
-
-.align-left {
- text-align: left;
-}
-
-.align-center {
- text-align: center;
-}
-
-.align-default {
- text-align: center;
-}
-
-.align-right {
- text-align: right;
-}
-
-/* -- sidebars -------------------------------------------------------------- */
-
-div.sidebar {
- margin: 0 0 0.5em 1em;
- border: 1px solid #ddb;
- padding: 7px;
- background-color: #ffe;
- width: 40%;
- float: right;
- clear: right;
- overflow-x: auto;
-}
-
-p.sidebar-title {
- font-weight: bold;
-}
-
-div.admonition, div.topic, blockquote {
- clear: left;
-}
-
-/* -- topics ---------------------------------------------------------------- */
-
-div.topic {
- border: 1px solid #ccc;
- padding: 7px;
- margin: 10px 0 10px 0;
-}
-
-p.topic-title {
- font-size: 1.1em;
- font-weight: bold;
- margin-top: 10px;
-}
-
-/* -- admonitions ----------------------------------------------------------- */
-
-div.admonition {
- margin-top: 10px;
- margin-bottom: 10px;
- padding: 7px;
-}
-
-div.admonition dt {
- font-weight: bold;
-}
-
-p.admonition-title {
- margin: 0px 10px 5px 0px;
- font-weight: bold;
-}
-
-div.body p.centered {
- text-align: center;
- margin-top: 25px;
-}
-
-/* -- content of sidebars/topics/admonitions -------------------------------- */
-
-div.sidebar > :last-child,
-div.topic > :last-child,
-div.admonition > :last-child {
- margin-bottom: 0;
-}
-
-div.sidebar::after,
-div.topic::after,
-div.admonition::after,
-blockquote::after {
- display: block;
- content: '';
- clear: both;
-}
-
-/* -- tables ---------------------------------------------------------------- */
-
-table.docutils {
- margin-top: 10px;
- margin-bottom: 10px;
- border: 0;
- border-collapse: collapse;
-}
-
-table.align-center {
- margin-left: auto;
- margin-right: auto;
-}
-
-table.align-default {
- margin-left: auto;
- margin-right: auto;
-}
-
-table caption span.caption-number {
- font-style: italic;
-}
-
-table caption span.caption-text {
-}
-
-table.docutils td, table.docutils th {
- padding: 1px 8px 1px 5px;
- border-top: 0;
- border-left: 0;
- border-right: 0;
- border-bottom: 1px solid #aaa;
-}
-
-table.footnote td, table.footnote th {
- border: 0 !important;
-}
-
-th {
- text-align: left;
- padding-right: 5px;
-}
-
-table.citation {
- border-left: solid 1px gray;
- margin-left: 1px;
-}
-
-table.citation td {
- border-bottom: none;
-}
-
-th > :first-child,
-td > :first-child {
- margin-top: 0px;
-}
-
-th > :last-child,
-td > :last-child {
- margin-bottom: 0px;
-}
-
-/* -- figures --------------------------------------------------------------- */
-
-div.figure {
- margin: 0.5em;
- padding: 0.5em;
-}
-
-div.figure p.caption {
- padding: 0.3em;
-}
-
-div.figure p.caption span.caption-number {
- font-style: italic;
-}
-
-div.figure p.caption span.caption-text {
-}
-
-/* -- field list styles ----------------------------------------------------- */
-
-table.field-list td, table.field-list th {
- border: 0 !important;
-}
-
-.field-list ul {
- margin: 0;
- padding-left: 1em;
-}
-
-.field-list p {
- margin: 0;
-}
-
-.field-name {
- -moz-hyphens: manual;
- -ms-hyphens: manual;
- -webkit-hyphens: manual;
- hyphens: manual;
-}
-
-/* -- hlist styles ---------------------------------------------------------- */
-
-table.hlist {
- margin: 1em 0;
-}
-
-table.hlist td {
- vertical-align: top;
-}
-
-
-/* -- other body styles ----------------------------------------------------- */
-
-ol.arabic {
- list-style: decimal;
-}
-
-ol.loweralpha {
- list-style: lower-alpha;
-}
-
-ol.upperalpha {
- list-style: upper-alpha;
-}
-
-ol.lowerroman {
- list-style: lower-roman;
-}
-
-ol.upperroman {
- list-style: upper-roman;
-}
-
-:not(li) > ol > li:first-child > :first-child,
-:not(li) > ul > li:first-child > :first-child {
- margin-top: 0px;
-}
-
-:not(li) > ol > li:last-child > :last-child,
-:not(li) > ul > li:last-child > :last-child {
- margin-bottom: 0px;
-}
-
-ol.simple ol p,
-ol.simple ul p,
-ul.simple ol p,
-ul.simple ul p {
- margin-top: 0;
-}
-
-ol.simple > li:not(:first-child) > p,
-ul.simple > li:not(:first-child) > p {
- margin-top: 0;
-}
-
-ol.simple p,
-ul.simple p {
- margin-bottom: 0;
-}
-
-dl.footnote > dt,
-dl.citation > dt {
- float: left;
- margin-right: 0.5em;
-}
-
-dl.footnote > dd,
-dl.citation > dd {
- margin-bottom: 0em;
-}
-
-dl.footnote > dd:after,
-dl.citation > dd:after {
- content: "";
- clear: both;
-}
-
-dl.field-list {
- display: grid;
- grid-template-columns: fit-content(30%) auto;
-}
-
-dl.field-list > dt {
- font-weight: bold;
- word-break: break-word;
- padding-left: 0.5em;
- padding-right: 5px;
-}
-
-dl.field-list > dt:after {
- content: ":";
-}
-
-dl.field-list > dd {
- padding-left: 0.5em;
- margin-top: 0em;
- margin-left: 0em;
- margin-bottom: 0em;
-}
-
-dl {
- margin-bottom: 15px;
-}
-
-dd > :first-child {
- margin-top: 0px;
-}
-
-dd ul, dd table {
- margin-bottom: 10px;
-}
-
-dd {
- margin-top: 3px;
- margin-bottom: 10px;
- margin-left: 30px;
-}
-
-dl > dd:last-child,
-dl > dd:last-child > :last-child {
- margin-bottom: 0;
-}
-
-dt:target, span.highlighted {
- background-color: #fbe54e;
-}
-
-rect.highlighted {
- fill: #fbe54e;
-}
-
-dl.glossary dt {
- font-weight: bold;
- font-size: 1.1em;
-}
-
-.optional {
- font-size: 1.3em;
-}
-
-.sig-paren {
- font-size: larger;
-}
-
-.versionmodified {
- font-style: italic;
-}
-
-.system-message {
- background-color: #fda;
- padding: 5px;
- border: 3px solid red;
-}
-
-.footnote:target {
- background-color: #ffa;
-}
-
-.line-block {
- display: block;
- margin-top: 1em;
- margin-bottom: 1em;
-}
-
-.line-block .line-block {
- margin-top: 0;
- margin-bottom: 0;
- margin-left: 1.5em;
-}
-
-.guilabel, .menuselection {
- font-family: sans-serif;
-}
-
-.accelerator {
- text-decoration: underline;
-}
-
-.classifier {
- font-style: oblique;
-}
-
-.classifier:before {
- font-style: normal;
- margin: 0.5em;
- content: ":";
-}
-
-abbr, acronym {
- border-bottom: dotted 1px;
- cursor: help;
-}
-
-/* -- code displays --------------------------------------------------------- */
-
-pre {
- overflow: auto;
- overflow-y: hidden; /* fixes display issues on Chrome browsers */
-}
-
-pre, div[class*="highlight-"] {
- clear: both;
-}
-
-span.pre {
- -moz-hyphens: none;
- -ms-hyphens: none;
- -webkit-hyphens: none;
- hyphens: none;
-}
-
-div[class*="highlight-"] {
- margin: 1em 0;
-}
-
-td.linenos pre {
- border: 0;
- background-color: transparent;
- color: #aaa;
-}
-
-table.highlighttable {
- display: block;
-}
-
-table.highlighttable tbody {
- display: block;
-}
-
-table.highlighttable tr {
- display: flex;
-}
-
-table.highlighttable td {
- margin: 0;
- padding: 0;
-}
-
-table.highlighttable td.linenos {
- padding-right: 0.5em;
-}
-
-table.highlighttable td.code {
- flex: 1;
- overflow: hidden;
-}
-
-.highlight .hll {
- display: block;
-}
-
-div.highlight pre,
-table.highlighttable pre {
- margin: 0;
-}
-
-div.code-block-caption + div {
- margin-top: 0;
-}
-
-div.code-block-caption {
- margin-top: 1em;
- padding: 2px 5px;
- font-size: small;
-}
-
-div.code-block-caption code {
- background-color: transparent;
-}
-
-table.highlighttable td.linenos,
-span.linenos,
-div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */
- user-select: none;
-}
-
-div.code-block-caption span.caption-number {
- padding: 0.1em 0.3em;
- font-style: italic;
-}
-
-div.code-block-caption span.caption-text {
-}
-
-div.literal-block-wrapper {
- margin: 1em 0;
-}
-
-code.descname {
- background-color: transparent;
- font-weight: bold;
- font-size: 1.2em;
-}
-
-code.descclassname {
- background-color: transparent;
-}
-
-code.xref, a code {
- background-color: transparent;
- font-weight: bold;
-}
-
-h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
- background-color: transparent;
-}
-
-.viewcode-link {
- float: right;
-}
-
-.viewcode-back {
- float: right;
- font-family: sans-serif;
-}
-
-div.viewcode-block:target {
- margin: -1px -10px;
- padding: 0 10px;
-}
-
-/* -- math display ---------------------------------------------------------- */
-
-img.math {
- vertical-align: middle;
-}
-
-div.body div.math p {
- text-align: center;
-}
-
-span.eqno {
- float: right;
-}
-
-span.eqno a.headerlink {
- position: absolute;
- z-index: 1;
-}
-
-div.math:hover a.headerlink {
- visibility: visible;
-}
-
-/* -- printout stylesheet --------------------------------------------------- */
-
-@media print {
- div.document,
- div.documentwrapper,
- div.bodywrapper {
- margin: 0 !important;
- width: 100%;
- }
-
- div.sphinxsidebar,
- div.related,
- div.footer,
- #top-link {
- display: none;
- }
-}
\ No newline at end of file
diff --git a/docs/build/html/_static/doctools.js b/docs/build/html/_static/doctools.js
deleted file mode 100644
index 7d88f807..00000000
--- a/docs/build/html/_static/doctools.js
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * doctools.js
- * ~~~~~~~~~~~
- *
- * Sphinx JavaScript utilities for all documentation.
- *
- * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
- * :license: BSD, see LICENSE for details.
- *
- */
-
-/**
- * select a different prefix for underscore
- */
-$u = _.noConflict();
-
-/**
- * make the code below compatible with browsers without
- * an installed firebug like debugger
-if (!window.console || !console.firebug) {
- var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
- "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
- "profile", "profileEnd"];
- window.console = {};
- for (var i = 0; i < names.length; ++i)
- window.console[names[i]] = function() {};
-}
- */
-
-/**
- * small helper function to urldecode strings
- */
-jQuery.urldecode = function(x) {
- return decodeURIComponent(x).replace(/\+/g, ' ');
-};
-
-/**
- * small helper function to urlencode strings
- */
-jQuery.urlencode = encodeURIComponent;
-
-/**
- * This function returns the parsed url parameters of the
- * current request. Multiple values per key are supported,
- * it will always return arrays of strings for the value parts.
- */
-jQuery.getQueryParameters = function(s) {
- if (typeof s === 'undefined')
- s = document.location.search;
- var parts = s.substr(s.indexOf('?') + 1).split('&');
- var result = {};
- for (var i = 0; i < parts.length; i++) {
- var tmp = parts[i].split('=', 2);
- var key = jQuery.urldecode(tmp[0]);
- var value = jQuery.urldecode(tmp[1]);
- if (key in result)
- result[key].push(value);
- else
- result[key] = [value];
- }
- return result;
-};
-
-/**
- * highlight a given string on a jquery object by wrapping it in
- * span elements with the given class name.
- */
-jQuery.fn.highlightText = function(text, className) {
- function highlight(node, addItems) {
- if (node.nodeType === 3) {
- var val = node.nodeValue;
- var pos = val.toLowerCase().indexOf(text);
- if (pos >= 0 &&
- !jQuery(node.parentNode).hasClass(className) &&
- !jQuery(node.parentNode).hasClass("nohighlight")) {
- var span;
- var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
- if (isInSVG) {
- span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
- } else {
- span = document.createElement("span");
- span.className = className;
- }
- span.appendChild(document.createTextNode(val.substr(pos, text.length)));
- node.parentNode.insertBefore(span, node.parentNode.insertBefore(
- document.createTextNode(val.substr(pos + text.length)),
- node.nextSibling));
- node.nodeValue = val.substr(0, pos);
- if (isInSVG) {
- var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
- var bbox = node.parentElement.getBBox();
- rect.x.baseVal.value = bbox.x;
- rect.y.baseVal.value = bbox.y;
- rect.width.baseVal.value = bbox.width;
- rect.height.baseVal.value = bbox.height;
- rect.setAttribute('class', className);
- addItems.push({
- "parent": node.parentNode,
- "target": rect});
- }
- }
- }
- else if (!jQuery(node).is("button, select, textarea")) {
- jQuery.each(node.childNodes, function() {
- highlight(this, addItems);
- });
- }
- }
- var addItems = [];
- var result = this.each(function() {
- highlight(this, addItems);
- });
- for (var i = 0; i < addItems.length; ++i) {
- jQuery(addItems[i].parent).before(addItems[i].target);
- }
- return result;
-};
-
-/*
- * backward compatibility for jQuery.browser
- * This will be supported until firefox bug is fixed.
- */
-if (!jQuery.browser) {
- jQuery.uaMatch = function(ua) {
- ua = ua.toLowerCase();
-
- var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
- /(webkit)[ \/]([\w.]+)/.exec(ua) ||
- /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
- /(msie) ([\w.]+)/.exec(ua) ||
- ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
- [];
-
- return {
- browser: match[ 1 ] || "",
- version: match[ 2 ] || "0"
- };
- };
- jQuery.browser = {};
- jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
-}
-
-/**
- * Small JavaScript module for the documentation.
- */
-var Documentation = {
-
- init : function() {
- this.fixFirefoxAnchorBug();
- this.highlightSearchWords();
- this.initIndexTable();
- if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
- this.initOnKeyListeners();
- }
- },
-
- /**
- * i18n support
- */
- TRANSLATIONS : {},
- PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
- LOCALE : 'unknown',
-
- // gettext and ngettext don't access this so that the functions
- // can safely bound to a different name (_ = Documentation.gettext)
- gettext : function(string) {
- var translated = Documentation.TRANSLATIONS[string];
- if (typeof translated === 'undefined')
- return string;
- return (typeof translated === 'string') ? translated : translated[0];
- },
-
- ngettext : function(singular, plural, n) {
- var translated = Documentation.TRANSLATIONS[singular];
- if (typeof translated === 'undefined')
- return (n == 1) ? singular : plural;
- return translated[Documentation.PLURALEXPR(n)];
- },
-
- addTranslations : function(catalog) {
- for (var key in catalog.messages)
- this.TRANSLATIONS[key] = catalog.messages[key];
- this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
- this.LOCALE = catalog.locale;
- },
-
- /**
- * add context elements like header anchor links
- */
- addContextElements : function() {
- $('div[id] > :header:first').each(function() {
- $('').
- attr('href', '#' + this.id).
- attr('title', _('Permalink to this headline')).
- appendTo(this);
- });
- $('dt[id]').each(function() {
- $('').
- attr('href', '#' + this.id).
- attr('title', _('Permalink to this definition')).
- appendTo(this);
- });
- },
-
- /**
- * workaround a firefox stupidity
- * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
- */
- fixFirefoxAnchorBug : function() {
- if (document.location.hash && $.browser.mozilla)
- window.setTimeout(function() {
- document.location.href += '';
- }, 10);
- },
-
- /**
- * highlight the search words provided in the url in the text
- */
- highlightSearchWords : function() {
- var params = $.getQueryParameters();
- var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
- if (terms.length) {
- var body = $('div.body');
- if (!body.length) {
- body = $('body');
- }
- window.setTimeout(function() {
- $.each(terms, function() {
- body.highlightText(this.toLowerCase(), 'highlighted');
- });
- }, 10);
- $('' + _('Hide Search Matches') + '
')
- .appendTo($('#searchbox'));
- }
- },
-
- /**
- * init the domain index toggle buttons
- */
- initIndexTable : function() {
- var togglers = $('img.toggler').click(function() {
- var src = $(this).attr('src');
- var idnum = $(this).attr('id').substr(7);
- $('tr.cg-' + idnum).toggle();
- if (src.substr(-9) === 'minus.png')
- $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
- else
- $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
- }).css('display', '');
- if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
- togglers.click();
- }
- },
-
- /**
- * helper function to hide the search marks again
- */
- hideSearchWords : function() {
- $('#searchbox .highlight-link').fadeOut(300);
- $('span.highlighted').removeClass('highlighted');
- },
-
- /**
- * make the url absolute
- */
- makeURL : function(relativeURL) {
- return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
- },
-
- /**
- * get the current relative url
- */
- getCurrentURL : function() {
- var path = document.location.pathname;
- var parts = path.split(/\//);
- $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
- if (this === '..')
- parts.pop();
- });
- var url = parts.join('/');
- return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
- },
-
- initOnKeyListeners: function() {
- $(document).keydown(function(event) {
- var activeElementType = document.activeElement.tagName;
- // don't navigate when in search box, textarea, dropdown or button
- if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT'
- && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey
- && !event.shiftKey) {
- switch (event.keyCode) {
- case 37: // left
- var prevHref = $('link[rel="prev"]').prop('href');
- if (prevHref) {
- window.location.href = prevHref;
- return false;
- }
- case 39: // right
- var nextHref = $('link[rel="next"]').prop('href');
- if (nextHref) {
- window.location.href = nextHref;
- return false;
- }
- }
- }
- });
- }
-};
-
-// quick alias for translations
-_ = Documentation.gettext;
-
-$(document).ready(function() {
- Documentation.init();
-});
diff --git a/docs/build/html/_static/documentation_options.js b/docs/build/html/_static/documentation_options.js
deleted file mode 100644
index 23fc755e..00000000
--- a/docs/build/html/_static/documentation_options.js
+++ /dev/null
@@ -1,12 +0,0 @@
-var DOCUMENTATION_OPTIONS = {
- URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
- VERSION: '0.0.1',
- LANGUAGE: 'None',
- COLLAPSE_INDEX: false,
- BUILDER: 'html',
- FILE_SUFFIX: '.html',
- LINK_SUFFIX: '.html',
- HAS_SOURCE: true,
- SOURCELINK_SUFFIX: '.txt',
- NAVIGATION_WITH_KEYS: false
-};
\ No newline at end of file
diff --git a/docs/build/html/_static/file.png b/docs/build/html/_static/file.png
deleted file mode 100644
index a858a410..00000000
Binary files a/docs/build/html/_static/file.png and /dev/null differ
diff --git a/docs/build/html/_static/jquery-3.5.1.js b/docs/build/html/_static/jquery-3.5.1.js
deleted file mode 100644
index 50937333..00000000
--- a/docs/build/html/_static/jquery-3.5.1.js
+++ /dev/null
@@ -1,10872 +0,0 @@
-/*!
- * jQuery JavaScript Library v3.5.1
- * https://jquery.com/
- *
- * Includes Sizzle.js
- * https://sizzlejs.com/
- *
- * Copyright JS Foundation and other contributors
- * Released under the MIT license
- * https://jquery.org/license
- *
- * Date: 2020-05-04T22:49Z
- */
-( function( global, factory ) {
-
- "use strict";
-
- if ( typeof module === "object" && typeof module.exports === "object" ) {
-
- // For CommonJS and CommonJS-like environments where a proper `window`
- // is present, execute the factory and get jQuery.
- // For environments that do not have a `window` with a `document`
- // (such as Node.js), expose a factory as module.exports.
- // This accentuates the need for the creation of a real `window`.
- // e.g. var jQuery = require("jquery")(window);
- // See ticket #14549 for more info.
- module.exports = global.document ?
- factory( global, true ) :
- function( w ) {
- if ( !w.document ) {
- throw new Error( "jQuery requires a window with a document" );
- }
- return factory( w );
- };
- } else {
- factory( global );
- }
-
-// Pass this if window is not defined yet
-} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
-
-// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
-// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
-// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
-// enough that all such attempts are guarded in a try block.
-"use strict";
-
-var arr = [];
-
-var getProto = Object.getPrototypeOf;
-
-var slice = arr.slice;
-
-var flat = arr.flat ? function( array ) {
- return arr.flat.call( array );
-} : function( array ) {
- return arr.concat.apply( [], array );
-};
-
-
-var push = arr.push;
-
-var indexOf = arr.indexOf;
-
-var class2type = {};
-
-var toString = class2type.toString;
-
-var hasOwn = class2type.hasOwnProperty;
-
-var fnToString = hasOwn.toString;
-
-var ObjectFunctionString = fnToString.call( Object );
-
-var support = {};
-
-var isFunction = function isFunction( obj ) {
-
- // Support: Chrome <=57, Firefox <=52
- // In some browsers, typeof returns "function" for HTML