-
Eric Kooistra authoredEric Kooistra authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
common_pkg.vhd 143.40 KiB
-------------------------------------------------------------------------------
--
-- Copyright (C) 2019
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
-- Author:
-- . Eric Kooistra
-- Purpose:
-- . Collection of commonly used base funtions
-- 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_dual : 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_48 : NATURAL := 48;
CONSTANT c_64 : NATURAL := 64;
CONSTANT c_128 : NATURAL := 128;
CONSTANT c_256 : NATURAL := 256;
CONSTANT c_natural_high : NATURAL := 2147483647; -- = 2**31 - 1 = NATURAL'HIGH;
-- 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
CONSTANT c_eps : REAL := 1.0e-20; -- add small epsilon value to avoid 1/0 and log(0), 1e-20 < 1/2**64
-- 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 (and Arria 10 for 2 multipliers per DSP block)
CONSTANT c_dsp_mult_18_w : NATURAL := 18; -- Width of the embedded multipliers in Stratix IV (and Arria 10 for 2 multipliers per DSP block)
CONSTANT c_dsp_mult_27_w : NATURAL := 27; -- Width of the embedded multipliers in Arria 10
-- 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_real_arr IS ARRAY (INTEGER RANGE <>) OF REAL; -- 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_nat_real_arr IS ARRAY (NATURAL RANGE <>) OF REAL; -- 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 the two possible boolean values that can be iterated over
CONSTANT c_nat_boolean_arr : t_nat_boolean_arr := (TRUE, FALSE); -- array the two possible boolean 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);
-- Multi-dimensional array types with fixed LS-dimension
-- . 2arr_2
-- . first '2' indicates two dimensions, so array I of array J, where I is
-- free in (NATURAL RANGE <>)
-- . second '_2' indicate that the last dimension J has fixed size 2 is
-- (1 DOWNTO 0)
TYPE t_natural_2arr_2 IS ARRAY (NATURAL RANGE <>) OF t_natural_arr(1 DOWNTO 0);
TYPE t_integer_2arr_2 IS ARRAY (NATURAL RANGE <>) OF t_integer_arr(1 DOWNTO 0);
TYPE t_real_2arr_2 IS ARRAY (NATURAL RANGE <>) OF t_real_arr(1 DOWNTO 0);
SUBTYPE t_complex_integer_arr_2 IS t_integer_2arr_2;
SUBTYPE t_complex_real_arr_2 IS t_real_2arr_2;
-- 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
-- use almost_equal(a/b, 1.0, max_ratio) to verify that a and b differ less than max_ratio/100 percent
-- use almost_zero(a/b, max_ratio) to verify that a is less than max_ratio/100 percent of b, so almost zero
FUNCTION almost_equal(a, b, delta : REAL) RETURN BOOLEAN; -- return TRUE when abs(a - b) < abs(delta), else return FALSE
FUNCTION almost_equal(a, b, delta : INTEGER) RETURN BOOLEAN;
FUNCTION almost_zero(a, delta : REAL) RETURN BOOLEAN; -- return TRUE when abs(a) < abs(delta), else return FALSE
FUNCTION almost_zero(a, delta : INTEGER) RETURN BOOLEAN;
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 gcd(a, b : NATURAL) RETURN NATURAL; -- greatest common divider
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_sl( n: IN BOOLEAN) RETURN STD_LOGIC; -- if TRUE then return '1' else '0'
FUNCTION to_bool(n: IN STD_LOGIC) RETURN BOOLEAN; -- if '1' or 'H' then return TRUE else FALSE
FUNCTION to_bool(n: IN INTEGER) RETURN BOOLEAN; -- if 0 then return FALSE else TRUE
FUNCTION not_int(n: IN INTEGER) RETURN INTEGER; -- if 0 then return 1 else 0
FUNCTION pack_complex(re, im : INTEGER; w : NATURAL) RETURN INTEGER; -- pack order: im & re
FUNCTION unpack_complex_re(data : INTEGER; w : NATURAL) RETURN INTEGER; -- pack order: im & re
FUNCTION unpack_complex_re(data : STD_LOGIC_VECTOR; w : NATURAL) RETURN INTEGER; -- pack order: im & re
FUNCTION unpack_complex_im(data : INTEGER; w : NATURAL) RETURN INTEGER; -- pack order: im & re
FUNCTION unpack_complex_im(data : STD_LOGIC_VECTOR; w : NATURAL) RETURN INTEGER; -- pack order: im & re
FUNCTION atan2(Y, X: REAL) RETURN REAL; -- = ARCTAN(Y, X) but returns 0 when Y = X = 0, without reporting Error: ARCTAN(0.0, 0.0) is undetermined
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 array_and(arr : t_nat_boolean_arr) RETURN BOOLEAN;
FUNCTION array_or( arr : t_nat_boolean_arr) RETURN BOOLEAN;
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 : REAL) RETURN REAL;
FUNCTION smallest(n, m, l : INTEGER) RETURN INTEGER;
FUNCTION smallest(n : t_natural_arr) RETURN NATURAL;
FUNCTION smallest(n : t_nat_natural_arr) RETURN NATURAL;
FUNCTION largest(n, m : INTEGER) RETURN INTEGER;
FUNCTION largest(n, m : REAL) RETURN REAL;
FUNCTION largest(n : t_natural_arr) RETURN NATURAL;
FUNCTION largest(n : t_nat_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 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 : BOOLEAN; nof : NATURAL) RETURN t_nat_boolean_arr; -- 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
-- . Note that using func_slv_concat() without the BOOLEAN use_* is equivalent to using the
-- slv concatenation operator & directly. However this overloaded func_slv_concat() is
-- still nice to have, because it shows the relation with the inverse func_slv_extract().
FUNCTION func_slv_concat( use_a, use_b, use_c, use_d, use_e, use_f, use_g, use_h : BOOLEAN; a, b, c, d, e, f, g, h : STD_LOGIC_VECTOR) RETURN 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( a, b, c, d, e, f, g, h : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
FUNCTION func_slv_concat( a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
FUNCTION func_slv_concat( a, b, c, d, e, f : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
FUNCTION func_slv_concat( a, b, c, d, e : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
FUNCTION func_slv_concat( a, b, c, d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
FUNCTION func_slv_concat( a, b, c : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
FUNCTION func_slv_concat( 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, use_h : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_w : NATURAL) RETURN NATURAL;
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, use_h : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_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, 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_extract( a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
FUNCTION func_slv_extract( 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( 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( 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( a_w, b_w, c_w, d_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
FUNCTION func_slv_extract( a_w, b_w, c_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
FUNCTION func_slv_extract( a_w, b_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR;
-- Number formats, see:
-- . https://support.astron.nl/confluence/display/L2M/L3+SDP+Decision%3A+Definition+of+fixed+point+numbers
-- . https://support.astron.nl/confluence/display/L2M/L4+SDPFW+Decision%3A+Number+representation%2C+resizing+and+rounding
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
FUNCTION TO_UINT(udec : REAL; w, resolution_w : INTEGER) RETURN NATURAL; -- REAL >= 0 to NATURAL fixed point number
FUNCTION TO_SINT(sdec : REAL; w, resolution_w : INTEGER) RETURN INTEGER; -- REAL to INTEGER fixed point number
FUNCTION TO_UVEC(udec : REAL; w, resolution_w : INTEGER) RETURN STD_LOGIC_VECTOR; -- REAL >= 0 to unsigned SLV fixed point number
FUNCTION TO_SVEC(sdec : REAL; w, resolution_w : INTEGER) RETURN STD_LOGIC_VECTOR; -- REAL to signed SLV fixed point number
FUNCTION TO_UREAL(uvec : STD_LOGIC_VECTOR) RETURN REAL; -- convert unsigned slv of any length to REAL, fixed point number with resolution = 1
FUNCTION TO_SREAL(svec : STD_LOGIC_VECTOR) RETURN REAL; -- convert signed slv of any length to REAL, fixed point number with resolution = 1
FUNCTION TO_UREAL(uvec : STD_LOGIC_VECTOR; resolution_w : INTEGER) RETURN REAL; -- convert unsigned fixed point slv of any length, and with resolution of 2**resolution_w, to REAL
FUNCTION TO_SREAL(svec : STD_LOGIC_VECTOR; resolution_w : INTEGER) RETURN REAL; -- convert signed fixed point slv of any length, and with resolution of 2**resolution_w, to REAL
-- RESIZE_NUM() original description:
-- 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.
--
-- RESIZE_NUM() updated description (27 oct 2021):
-- The RESIZE() from IEEE.NUMERIC_STD keeps the sign bit and the w-1 LSbits, this results in a signal that
-- keeps the sign, but wraps between - and 0 for negative input, and that wraps between + and 0 for
-- positive input.
-- The RESIZE_NUM() from in this common_pkg.vhd simply keeps the w LSbits, so it wraps between - and +.
-- Hence RESIZE_NUM() works the same for SIGNED as for UNSIGNED. For an adder that sums multiple inputs,
-- it can be better to wrap over the entire -, + range, like RESIZE_NUM() does, because if the final adder
-- sum again fits in w bits, then any wrapping effects for intermediate sums will cancel in the end sum.
-- If the number of bit w is sufficient to have no resize overflow, then RESIZE() = RESIZE_NUM(). In an
-- application overflow should be avoided anyway, so then using either RESIZE() or RESIZE_NUM() is fine.
-- When w keeps or increases the data width then the values do not change (of course). When w reduces the
-- data width then overflow can occur in an application, so then use:
-- * RESIZE() to preserve the sign,
-- * RESIZE_NUM() to wrap similar for SIGNED as for UNSIGNED,
-- * common_resize.vhd to clip the overflow (and use symmetrical -, + clipping to avoid introducing DC bias).
-- The resize functions and component are verified by tb_tb_resize.vhd.
-- Conclusion:
-- 1) Keep original RESIZE_NUM(), so resize by selecting the w LSbits for both SIGNED and UNSIGNED.
-- 2) For applications without overflow RESIZE() = RESIZE_NUM() = common_resize.
-- 3) For applications with overflow choose to use RESIZE_NUM(), because it wraps similar for SIGNED as
-- for UNSIGNED (because both keep the w LSbits), instead of behaving differently for SIGNED like
-- RESIZE() does (keeping the MSbit and the w-1 LSbits). The wrapping of RESIZE_NUM() preserves the
-- capability of recovering from intermediate overflow in a summator, which can be beneficial for e.g.
-- a beamformer.
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 NEGATE_SVEC(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- assume negated ranges fits within -+max
FUNCTION NEGATE_SVEC(vec : STD_LOGIC_VECTOR; w : INTEGER) RETURN STD_LOGIC_VECTOR; -- avoid overflow by forcing -min to +max. Use w <= vec'LENGTH
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 MULT_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 + r_vec'LENGTH
FUNCTION MULT_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 + r_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
-- Convert between polar and rectangular coordinates
FUNCTION COMPLEX_RADIUS(re, im : REAL) RETURN REAL;
FUNCTION COMPLEX_RADIUS(re, im : INTEGER) RETURN REAL;
FUNCTION COMPLEX_PHASE( re, im : REAL; radians : BOOLEAN) RETURN REAL; -- phase in radians or degrees
FUNCTION COMPLEX_PHASE( re, im : INTEGER; radians : BOOLEAN) RETURN REAL; -- phase in radians or degrees
FUNCTION COMPLEX_PHASE( re, im : REAL) RETURN REAL; -- phase in degrees
FUNCTION COMPLEX_PHASE( re, im : INTEGER) RETURN REAL; -- phase in degrees
FUNCTION COMPLEX_RE(ampl, phase : REAL; radians : BOOLEAN) RETURN REAL; -- phase in radians or degrees
FUNCTION COMPLEX_RE(ampl, phase : INTEGER; radians : BOOLEAN) RETURN REAL; -- phase in radians or degrees
FUNCTION COMPLEX_RE(ampl, phase : REAL) RETURN REAL; -- phase in degrees
FUNCTION COMPLEX_RE(ampl, phase : INTEGER) RETURN REAL; -- phase in degrees
FUNCTION COMPLEX_IM(ampl, phase : REAL; radians : BOOLEAN) RETURN REAL; -- phase in radians or degrees
FUNCTION COMPLEX_IM(ampl, phase : INTEGER; radians : BOOLEAN) RETURN REAL; -- phase in radians or degrees
FUNCTION COMPLEX_IM(ampl, phase : REAL) RETURN REAL; -- phase in degrees
FUNCTION COMPLEX_IM(ampl, phase : INTEGER) RETURN REAL; -- phase in degrees
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 ROTATE_UVEC(vec : STD_LOGIC_VECTOR; shift : INTEGER) RETURN STD_LOGIC_VECTOR; -- < 0 rotate left, > 0 rotate 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( vec : STD_LOGIC_VECTOR; n : NATURAL; clip, even : BOOLEAN) RETURN STD_LOGIC_VECTOR; -- idem but round half to even for signed
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_round( vec : STD_LOGIC_VECTOR; n : NATURAL; clip, even : BOOLEAN) RETURN STD_LOGIC_VECTOR; -- idem but round half to even for unsigned
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 almost_equal(a, b, delta : REAL) RETURN BOOLEAN IS
BEGIN
IF ABS(a - b) <= ABS(delta) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END;
FUNCTION almost_equal(a, b, delta : INTEGER) RETURN BOOLEAN IS
BEGIN
IF ABS(a - b) <= ABS(delta) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END;
FUNCTION almost_zero(a, delta : REAL) RETURN BOOLEAN IS
BEGIN
RETURN almost_equal(a, 0.0, delta);
END;
FUNCTION almost_zero(a, delta : INTEGER) RETURN BOOLEAN IS
BEGIN
RETURN almost_equal(a, 0, delta);
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 gcd(a, b : NATURAL) RETURN NATURAL IS -- greatest common divider
BEGIN
IF b = 0 THEN
RETURN a;
ELSE
RETURN gcd(b, a MOD b);
END IF;
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_sl(n: IN BOOLEAN) RETURN STD_LOGIC IS
BEGIN
IF n = TRUE THEN
RETURN '1';
ELSE
RETURN '0';
END IF;
END;
FUNCTION to_bool(n: IN STD_LOGIC) RETURN BOOLEAN IS
BEGIN
RETURN n = '1' OR n = 'H';
END;
FUNCTION to_bool(n: IN INTEGER) RETURN BOOLEAN IS
BEGIN
RETURN NOT (n = 0);
END;
FUNCTION not_int(n : INTEGER) RETURN INTEGER IS
BEGIN
RETURN sel_a_b(n = 0, 1, 0);
END;
FUNCTION pack_complex(re, im : INTEGER; w : NATURAL) RETURN INTEGER IS
CONSTANT c_complex_w : NATURAL := 2 * w;
VARIABLE v_complex_slv : STD_LOGIC_VECTOR(c_complex_w-1 DOWNTO 0) := TO_SVEC(im, w) & TO_SVEC(re, w);
BEGIN
ASSERT c_complex_w <= c_word_w REPORT "common_pkg: Complex value to large to pack into 32 bit integer" SEVERITY FAILURE;
IF c_complex_w < c_word_w THEN -- fits in 31 bit unsigned NATURAL
RETURN TO_UINT(v_complex_slv);
ELSE -- need to use 32 bit signed INTEGER
RETURN TO_SINT(v_complex_slv);
END IF;
END;
FUNCTION unpack_complex_re(data : STD_LOGIC_VECTOR; w : NATURAL) RETURN INTEGER IS
BEGIN
ASSERT w <= c_word_w REPORT "common_pkg: Complex value to large to unpack into 32 bit integer parts" SEVERITY FAILURE;
RETURN TO_SINT(data(w-1 DOWNTO 0)); -- Re in LS part
END;
FUNCTION unpack_complex_re(data : INTEGER; w : NATURAL) RETURN INTEGER IS
CONSTANT c_complex_w : NATURAL := 2 * w;
VARIABLE v_complex_slv : STD_LOGIC_VECTOR(c_complex_w-1 DOWNTO 0) := TO_SVEC(data, c_complex_w);
BEGIN
RETURN TO_SINT(v_complex_slv(w-1 DOWNTO 0)); -- Re in LS part
END;
FUNCTION unpack_complex_im(data : STD_LOGIC_VECTOR; w : NATURAL) RETURN INTEGER IS
BEGIN
ASSERT w <= c_word_w REPORT "common_pkg: Complex value to large to unpack into 32 bit integer parts" SEVERITY FAILURE;
RETURN TO_SINT(data(2*w-1 DOWNTO w)); -- Im in MS part
END;
FUNCTION unpack_complex_im(data : INTEGER; w : NATURAL) RETURN INTEGER IS
CONSTANT c_complex_w : NATURAL := 2 * w;
VARIABLE v_complex_slv : STD_LOGIC_VECTOR(c_complex_w-1 DOWNTO 0) := TO_SVEC(data, c_complex_w);
BEGIN
RETURN TO_SINT(v_complex_slv(c_complex_w-1 DOWNTO w)); -- Im in MS part
END;
FUNCTION atan2(Y, X: REAL) RETURN REAL IS
BEGIN
IF Y = 0.0 AND X = 0.0 THEN
RETURN 0.0;
ELSE
RETURN ARCTAN(Y, X);
END IF;
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 array_and(arr : t_nat_boolean_arr) RETURN BOOLEAN IS
VARIABLE v_slv : STD_LOGIC_VECTOR(arr'RANGE);
BEGIN
FOR I IN arr'RANGE LOOP v_slv(I) := sel_a_b(arr(I), '1', '0'); END LOOP; -- wire map boolean arr to slv
RETURN sel_a_b(vector_and(v_slv) = '1', TRUE, FALSE); -- use vector_tree to determine result
END;
FUNCTION array_or(arr : t_nat_boolean_arr) RETURN BOOLEAN IS
VARIABLE v_slv : STD_LOGIC_VECTOR(arr'RANGE);
BEGIN
FOR I IN arr'RANGE LOOP v_slv(I) := sel_a_b(arr(I), '1', '0'); END LOOP; -- wire map boolean arr to slv
RETURN sel_a_b(vector_or(v_slv) = '1', TRUE, FALSE); -- use vector_tree to determine result
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 : REAL) RETURN REAL 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 smallest(n : t_nat_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, m : REAL) RETURN REAL 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 largest(n : t_nat_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 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 : BOOLEAN; nof : NATURAL) RETURN t_nat_boolean_arr IS
VARIABLE v_arr : t_nat_boolean_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_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 8 slv into 1 slv
FUNCTION func_slv_concat(use_a, use_b, use_c, use_d, use_e, use_f, use_g, use_h : BOOLEAN; a, b, c, d, e, f, g, h : 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 + h'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;
IF use_h = TRUE THEN v_res(h'LENGTH-1 + v_len DOWNTO v_len) := h; v_len := v_len + h'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, use_g : BOOLEAN; a, b, c, d, e, f, g : 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, use_g, FALSE, a, b, c, d, e, f, g, "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, FALSE, a, b, c, d, e, f, "0", "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, FALSE, a, b, c, d, e, "0", "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, FALSE, a, b, c, d, "0", "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, FALSE, a, b, c, "0", "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, FALSE, a, b, "0", "0", "0", "0", "0", "0");
END func_slv_concat;
FUNCTION func_slv_concat(a, b, c, d, e, f, g, h : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN func_slv_concat(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, a, b, c, d, e, f, g, h);
END func_slv_concat;
FUNCTION func_slv_concat(a, b, c, d, e, f, g : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN func_slv_concat(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, a, b, c, d, e, f, g);
END func_slv_concat;
FUNCTION func_slv_concat(a, b, c, d, e, f : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN func_slv_concat(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, a, b, c, d, e, f);
END func_slv_concat;
FUNCTION func_slv_concat(a, b, c, d, e: STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN func_slv_concat(TRUE, TRUE, TRUE, TRUE, TRUE, a, b, c, d, e);
END func_slv_concat;
FUNCTION func_slv_concat(a, b, c, d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN func_slv_concat(TRUE, TRUE, TRUE, TRUE, a, b, c, d);
END func_slv_concat;
FUNCTION func_slv_concat(a, b, c : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN func_slv_concat(TRUE, TRUE, TRUE, a, b, c);
END func_slv_concat;
FUNCTION func_slv_concat(a, b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN func_slv_concat(TRUE, TRUE, a, b);
END func_slv_concat;
FUNCTION func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g, use_h : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_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;
IF use_h = TRUE THEN v_len := v_len + h_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, use_g : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w : NATURAL) RETURN NATURAL IS
BEGIN
RETURN func_slv_concat_w(use_a, use_b, use_c, use_d, use_e, use_f, use_g, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, g_w, 0);
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, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, 0, 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, FALSE, a_w, b_w, c_w, d_w, e_w, 0, 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, FALSE, a_w, b_w, c_w, d_w, 0, 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, FALSE, a_w, b_w, c_w, 0, 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, FALSE, a_w, b_w, 0, 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, use_h : BOOLEAN; a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_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 7 =>
IF use_h = TRUE THEN v_w := h_w; ELSE RETURN c_slv0(h_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;
IF use_g = TRUE THEN v_lo := v_lo + g_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, 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
BEGIN
RETURN func_slv_extract(use_a, use_b, use_c, use_d, use_e, use_f, use_g, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, g_w, 0, vec, sel);
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, FALSE, a_w, b_w, c_w, d_w, e_w, f_w, 0, 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, FALSE, a_w, b_w, c_w, d_w, e_w, 0, 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, FALSE, a_w, b_w, c_w, d_w, 0, 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, FALSE, a_w, b_w, c_w, 0, 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, FALSE, a_w, b_w, 0, 0, 0, 0, 0, 0, vec, sel);
END func_slv_extract;
FUNCTION func_slv_extract(a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN func_slv_extract(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, a_w, b_w, c_w, d_w, e_w, f_w, g_w, h_w, vec, sel);
END func_slv_extract;
FUNCTION func_slv_extract(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
BEGIN
RETURN func_slv_extract(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, a_w, b_w, c_w, d_w, e_w, f_w, g_w, vec, sel);
END func_slv_extract;
FUNCTION func_slv_extract(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(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, a_w, b_w, c_w, d_w, e_w, f_w, vec, sel);
END func_slv_extract;
FUNCTION func_slv_extract(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(TRUE, TRUE, TRUE, TRUE, TRUE, a_w, b_w, c_w, d_w, e_w, vec, sel);
END func_slv_extract;
FUNCTION func_slv_extract(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(TRUE, TRUE, TRUE, TRUE, a_w, b_w, c_w, d_w, vec, sel);
END func_slv_extract;
FUNCTION func_slv_extract(a_w, b_w, c_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN func_slv_extract(TRUE, TRUE, TRUE, a_w, b_w, c_w, vec, sel);
END func_slv_extract;
FUNCTION func_slv_extract(a_w, b_w : NATURAL; vec : STD_LOGIC_VECTOR; sel : NATURAL) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN func_slv_extract(TRUE, TRUE, a_w, b_w, 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 TO_UINT(udec : REAL; w, resolution_w : INTEGER) RETURN NATURAL IS
CONSTANT c_resolution : REAL := 1.0 / 2.0**REAL(resolution_w);
CONSTANT c_ureal : REAL := ROUND(udec / c_resolution); -- rounds away from zero
BEGIN
IF udec >= 0.0 THEN
RETURN TO_SINT(udec, w + 1, resolution_w); -- w + 1, because unsigned has no sign bit
ELSE
REPORT "Negative REAL clipped to INTEGER 0 : " & REAL'IMAGE(c_ureal) & " --> 0" SEVERITY WARNING;
RETURN 0;
END IF;
END;
FUNCTION TO_SINT(sdec : REAL; w, resolution_w : INTEGER) RETURN INTEGER IS
CONSTANT c_max : REAL := 2.0**REAL(w - 1) - 1.0;
CONSTANT c_min : REAL := -2.0**REAL(w - 1);
CONSTANT c_resolution : REAL := 1.0 / 2.0**REAL(resolution_w);
CONSTANT c_sreal : REAL := ROUND(sdec / c_resolution); -- rounds away from zero
CONSTANT c_sint : INTEGER := INTEGER(c_sreal);
BEGIN
IF c_sreal >= c_min THEN
IF c_sreal <= c_max THEN
RETURN c_sint;
ELSE
REPORT "REAL clipped to INTEGER max : " & REAL'IMAGE(c_sreal) & " --> " & INTEGER'IMAGE(INTEGER(c_max)) SEVERITY WARNING;
RETURN INTEGER(c_max); -- clip to max
END IF;
ELSE
REPORT "REAL clipped to INTEGER min : " & REAL'IMAGE(c_sreal) & " --> " & INTEGER'IMAGE(INTEGER(c_min)) SEVERITY WARNING;
RETURN INTEGER(c_min); -- clip to min
END IF;
END;
FUNCTION TO_UVEC(udec : REAL; w, resolution_w : INTEGER) RETURN STD_LOGIC_VECTOR IS
-- Determine range that fits w bits
CONSTANT c_uvec_max : STD_LOGIC_VECTOR(w-1 DOWNTO 0) := (OTHERS => '1');
CONSTANT c_max : REAL := 2.0**REAL(w) - 1.0;
CONSTANT c_resolution : REAL := 1.0 / 2.0**REAL(resolution_w);
VARIABLE v_ureal : REAL := ROUND(udec / c_resolution); -- rounds away from zero
-- Convert to uvec
VARIABLE v_floor : REAL := 0.0;
VARIABLE v_uvec : STD_LOGIC_VECTOR(w-1 DOWNTO 0) := (OTHERS => '0');
BEGIN
IF udec >= 0.0 THEN
IF v_ureal <= c_max THEN
-- Avoid using INTEGER, which is limited to 32 bit, by determining per
-- bit whether the REAL value contributes to it.
-- If the REAL, after fixed point scaling by c_resolution, fits in w
-- bits, then the remainer v_floor after w times dividing by 2.0 will
-- be 0.0, because 2**w * 0.5 = 2**(w-1). For example u(4,0) = 7.0
-- yields:
-- 7.0 / 2 = 3.5 --> [0] = '1'
-- floor(3.5) = 3.0 / 2 = 1.5 --> [1] = '1'
-- floor(1.5) = 1.0 / 2 = 0.5 --> [2] = '1'
-- floor(0.5) = 0.0 / 2 = 0.0 --> [3] = '0'
-- so u(4,0) = 7.0 yields remainder 0.0 and SLV[3:0] = "0111"
-- similar u(4,0) = 8.0 yields remainder 0.5 and SLV[3:0] = "1000"
-- and u(4,0) > 8.0 yields remainder >= 0.5
FOR I IN 0 TO w-1 LOOP
v_ureal := v_ureal / 2.0;
v_floor := floor(v_ureal);
IF v_ureal > v_floor THEN
v_uvec(I) := '1';
END IF;
v_ureal := v_floor;
END LOOP;
ASSERT v_floor = 0.0 REPORT "Unexpected TO_UVEC REAL remainder : " & REAL'IMAGE(v_floor) & " /= 0.0" SEVERITY FAILURE;
RETURN v_uvec;
ELSE
REPORT "Positive REAL clipped to UVEC max : " & REAL'IMAGE(v_ureal) & " --> " & REAL'IMAGE(c_max) SEVERITY WARNING;
RETURN c_uvec_max;
END IF;
ELSE
REPORT "Negative REAL clipped to UVEC 0 : " & REAL'IMAGE(v_ureal) & " --> 0" SEVERITY WARNING;
RETURN TO_UVEC(0, w);
END IF;
END;
FUNCTION TO_SVEC(sdec : REAL; w, resolution_w : INTEGER) RETURN STD_LOGIC_VECTOR IS
-- Determine range that fits w bits
CONSTANT c_svec_max : STD_LOGIC_VECTOR(w-1 DOWNTO 0) := '0' & (w-2 DOWNTO 0 => '1');
CONSTANT c_svec_min : STD_LOGIC_VECTOR(w-1 DOWNTO 0) := '1' & (w-2 DOWNTO 0 => '0');
CONSTANT c_max : REAL := 2.0**REAL(w - 1) - 1.0;
CONSTANT c_min : REAL := -2.0**REAL(w - 1);
CONSTANT c_resolution : REAL := 1.0 / 2.0**REAL(resolution_w);
CONSTANT c_sreal : REAL := ROUND(sdec / c_resolution); -- rounds away from zero
-- Convert to positive using TO_UVEC, so if sdec is negative, then
-- negate sdec to have positive c_udec.
CONSTANT c_pos : BOOLEAN := sdec >= 0.0;
CONSTANT c_udec : REAL := sel_a_b(c_pos, sdec, -sdec);
-- Determine SLV value for positive REAL, use w+1 to fit negate of most negative value
CONSTANT c_uvec : STD_LOGIC_VECTOR(w DOWNTO 0) := TO_UVEC(c_udec, w + 1, resolution_w);
-- Back to signed, so if sdec is negative, then negate c_uvec to have positive c_svec
CONSTANT c_svec : STD_LOGIC_VECTOR(w DOWNTO 0) := sel_a_b(c_pos, c_uvec, NEGATE_SVEC(c_uvec));
BEGIN
IF c_sreal >= c_min THEN
IF c_sreal <= c_max THEN
RETURN c_svec(w-1 DOWNTO 0);
ELSE
REPORT "REAL clipped to SVEC max : " & REAL'IMAGE(c_sreal) & " --> " & REAL'IMAGE(c_max) SEVERITY WARNING;
RETURN c_svec_max; -- clip to max
END IF;
ELSE
REPORT "REAL clipped to SVEC min : " & REAL'IMAGE(c_sreal) & " --> " & REAL'IMAGE(c_min) SEVERITY WARNING;
RETURN c_svec_min; -- clip to min
END IF;
END;
FUNCTION TO_UREAL(uvec : STD_LOGIC_VECTOR) RETURN REAL IS
CONSTANT c_len : NATURAL := uvec'LENGTH;
CONSTANT c_uvec : STD_LOGIC_VECTOR(c_len-1 DOWNTO 0) := uvec;
VARIABLE v_real : REAL := 0.0;
BEGIN
-- Avoid using INTEGER, which is limited to 32 bit, by determining per bit whether it contributes to the REAL value
FOR I IN 0 TO c_len-1 LOOP
IF c_uvec(I)='1' THEN
v_real := v_real + 2.0**REAL(I);
END IF;
END LOOP;
RETURN v_real;
END;
FUNCTION TO_SREAL(svec : STD_LOGIC_VECTOR) RETURN REAL IS
-- Increase vector length by +1 so the c_uvec can also fit abs() of most negative is -1 * -2**(c_len-1)
CONSTANT c_len : NATURAL := svec'LENGTH + 1;
CONSTANT c_svec : STD_LOGIC_VECTOR(c_len-1 DOWNTO 0) := RESIZE_SVEC(svec, c_len);
-- If c_svec is negative, then negate c_svec to have positive c_uvec.
CONSTANT c_pos : BOOLEAN := SIGNED(svec) >= 0;
CONSTANT c_uvec : STD_LOGIC_VECTOR(c_len-1 DOWNTO 0) := sel_a_b(c_pos, c_svec, NEGATE_SVEC(c_svec));
-- Determine REAL value for positive
CONSTANT c_real : REAL := TO_UREAL(c_uvec);
BEGIN
-- Update the sign
RETURN sel_a_b(c_pos, c_real, -c_real);
END;
-- Fixed point format
-- . https://support.astron.nl/confluence/display/L2M/L3+SDP+Decision%3A+Definition+of+fixed+point+numbers
FUNCTION TO_UREAL(uvec : STD_LOGIC_VECTOR; resolution_w : INTEGER) RETURN REAL IS
BEGIN
-- First convert as unsigned integer, then scale to real. See TO_SREAL()
-- for interpretation of resolution_w
RETURN TO_UREAL(uvec) / 2.0**REAL(resolution_w);
END;
FUNCTION TO_SREAL(svec : STD_LOGIC_VECTOR; resolution_w : INTEGER) RETURN REAL IS
BEGIN
-- First convert as unsigned integer, then scale to real
-- . The resolution_w is the number of bits that LSbit 0 in svec(HIGH-1 DOWNTO 0) is after
-- (when resolution_w > 0), or before (when resolution_w < 0) the fixed point.
-- . The real value is then scaled by scaling the integer value by 1.0 / 2**(resolution_w):
-- . resolution_w = 0 : scale by 2**0 = 1, so no scaling and the value is treated as an integer
-- . resolution_w < 0 : scale up
-- . resolution_w > 0 : scale down
RETURN TO_SREAL(svec) / 2.0**REAL(resolution_w);
END;
FUNCTION RESIZE_NUM(u : UNSIGNED; w : NATURAL) RETURN UNSIGNED IS
BEGIN
-- left extend with '0' or remove MSbits and keep LS part (= u[w-1:0])
RETURN RESIZE(u, w); -- same as RESIZE for UNSIGNED
END;
FUNCTION RESIZE_NUM(s : SIGNED; w : NATURAL) RETURN SIGNED IS
BEGIN
-- extend sign bit or keep LS part
IF w>s'LENGTH THEN
RETURN RESIZE(s, w); -- extend sign bit
ELSE
-- RESIZE() wraps between -, 0 for negative and 0, + for positive, so it keeps the sign and w-1 LSbits
-- RESIZE_NUM() removes MSbits, so it wraps from + to - and from - to +, and it keeps the w LSbits
-- remove MSbits and keep LS part (= s[w-1:0])
-- use RESIZE(UNSIGNED()) rather than s[w-1:0] to be independent of RANGE of s
RETURN SIGNED(RESIZE(UNSIGNED(s), w));
END IF;
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;
-- Negate vec, assume value range fits -+c_max, so no logic needed to check for c_min
FUNCTION NEGATE_SVEC(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
BEGIN
-- use NUMERIC_STD to avoid range limitation of 32b INTEGER
-- default approach
RETURN STD_LOGIC_VECTOR(-SIGNED(vec)); -- negate by multiplying by -1
-- alternative equivalent approach
-- RETURN INCR_UVEC(NOT vec, 1); -- negate by using two complement negate
END;
-- Negate vec, but avoid overflow by forcing -min to +max. Use w <= vec'LENGTH.
FUNCTION NEGATE_SVEC(vec : STD_LOGIC_VECTOR; w : INTEGER) RETURN STD_LOGIC_VECTOR IS
CONSTANT c_max : INTEGER := 2**(w-1)-1;
CONSTANT c_min : INTEGER := -2**(w-1);
CONSTANT c_vec_w : NATURAL := vec'LENGTH;
VARIABLE v_vec : STD_LOGIC_VECTOR(c_vec_w-1 DOWNTO 0) := vec; -- independent of vec'RANGE
VARIABLE v_val : STD_LOGIC_VECTOR(w-1 DOWNTO 0);
BEGIN
v_val := v_vec(w-1 DOWNTO 0); -- operate on width w and resize to c_vec_w for return
-- use NUMERIC_STD to avoid range limitation of 32b INTEGER
IF SIGNED(v_val) = c_min THEN
RETURN STD_LOGIC_VECTOR(TO_SIGNED(c_max, c_vec_w)); -- most negative becomes most positive
ELSE
RETURN STD_LOGIC_VECTOR(RESIZE_NUM(-SIGNED(v_val), c_vec_w)); -- negate by multiplying by -1
END IF;
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
BEGIN
RETURN STD_LOGIC_VECTOR(SIGNED(vec) + 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 MULT_SVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
CONSTANT c_product_w : NATURAL := l_vec'LENGTH + r_vec'LENGTH;
VARIABLE v_product : STD_LOGIC_VECTOR(c_product_w-1 DOWNTO 0);
BEGIN
v_product := STD_LOGIC_VECTOR(SIGNED(l_vec) * SIGNED(r_vec));
RETURN v_product;
END;
FUNCTION MULT_UVEC(l_vec : STD_LOGIC_VECTOR; r_vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
CONSTANT c_product_w : NATURAL := l_vec'LENGTH + r_vec'LENGTH;
VARIABLE v_product : STD_LOGIC_VECTOR(c_product_w-1 DOWNTO 0);
BEGIN
v_product := STD_LOGIC_VECTOR(UNSIGNED(l_vec) * UNSIGNED(r_vec));
RETURN v_product;
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 COMPLEX_RADIUS(re, im : REAL) RETURN REAL IS
BEGIN
-- Must use ABS() with ** of real, because (negative)**2.0 yields error and value 0.0.
-- Must must use brackets (ABS()) to avoid compile error.
-- Alternative equivalent code would be: SQRT(re * re + im * im).
RETURN SQRT((ABS(re))**2.0 + (ABS(im))**2.0);
END;
FUNCTION COMPLEX_RADIUS(re, im : INTEGER) RETURN REAL IS
BEGIN
RETURN COMPLEX_RADIUS(REAL(re), REAL(im));
END;
FUNCTION COMPLEX_PHASE(re, im : REAL; radians : BOOLEAN) RETURN REAL IS
BEGIN
IF radians = TRUE THEN
RETURN ATAN2(Y => im, X => re);
ELSE
RETURN ATAN2(Y => im, X => re) * 360.0 / MATH_2_PI;
END IF;
END;
FUNCTION COMPLEX_PHASE(re, im : INTEGER; radians : BOOLEAN) RETURN REAL IS
BEGIN
RETURN COMPLEX_PHASE(REAL(re), REAL(im), radians);
END;
FUNCTION COMPLEX_PHASE(re, im : REAL) RETURN REAL IS
BEGIN
RETURN COMPLEX_PHASE(re, im, FALSE);
END;
FUNCTION COMPLEX_PHASE(re, im : INTEGER) RETURN REAL IS
BEGIN
RETURN COMPLEX_PHASE(REAL(re), REAL(im), FALSE);
END;
FUNCTION COMPLEX_RE(ampl, phase : REAL; radians : BOOLEAN) RETURN REAL IS
BEGIN
IF radians = TRUE THEN
RETURN ampl * COS(phase);
ELSE
RETURN ampl * COS(phase * MATH_2_PI / 360.0);
END IF;
END;
FUNCTION COMPLEX_RE(ampl, phase : INTEGER; radians : BOOLEAN) RETURN REAL IS
BEGIN
RETURN COMPLEX_RE(REAL(ampl), REAL(phase), radians);
END;
FUNCTION COMPLEX_RE(ampl, phase : REAL) RETURN REAL IS
BEGIN
RETURN COMPLEX_RE(ampl, phase, FALSE);
END;
FUNCTION COMPLEX_RE(ampl, phase : INTEGER) RETURN REAL IS
BEGIN
RETURN COMPLEX_RE(REAL(ampl), REAL(phase), FALSE);
END;
FUNCTION COMPLEX_IM(ampl, phase : REAL; radians : BOOLEAN) RETURN REAL IS
BEGIN
IF radians = TRUE THEN
RETURN ampl * SIN(phase);
ELSE
RETURN ampl * SIN(phase * MATH_2_PI / 360.0);
END IF;
END;
FUNCTION COMPLEX_IM(ampl, phase : INTEGER; radians : BOOLEAN) RETURN REAL IS
BEGIN
RETURN COMPLEX_IM(REAL(ampl), REAL(phase), radians);
END;
FUNCTION COMPLEX_IM(ampl, phase : REAL) RETURN REAL IS
BEGIN
RETURN COMPLEX_IM(ampl, phase, FALSE);
END;
FUNCTION COMPLEX_IM(ampl, phase : INTEGER) RETURN REAL IS
BEGIN
RETURN COMPLEX_IM(REAL(ampl), REAL(phase), FALSE);
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;
FUNCTION ROTATE_UVEC(vec : STD_LOGIC_VECTOR; shift : INTEGER) RETURN STD_LOGIC_VECTOR IS
BEGIN
IF shift < 0 THEN
RETURN STD_LOGIC_VECTOR(ROTATE_LEFT(UNSIGNED(vec), -shift)); -- /<-- vec <--\
-- \---------->/
ELSE
RETURN STD_LOGIC_VECTOR(ROTATE_RIGHT(UNSIGNED(vec), shift)); -- /--> vec -->\
-- \<----------/
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;
-------------------------------------------------------------------------------------------------
-- Rounding schemes
-- . https://support.astron.nl/confluence/display/L2M/L4+SDPFW+Decision%3A+Number+representation%2C+resizing+and+rounding
-------------------------------------------------------------------------------------------------
--
-- From https://en.wikipedia.org/wiki/Rounding it follows that there are three main
-- categories for rounding to integer:
--
-- 1) Direct rounding to integer :
-- . down : y = floor(x), is truncate of LSbits
-- . up : y = ceil(x),
-- . towards zero : y = truncate(x) = int(x), is truncate of fraction, is keep the integer part
-- = sgn(x) floor(|x|) = floor(x) when x >= 0, else ceil(x)
-- . away from zero : y = sgn(x) ceil(|x|) = ceil(x) when x >= 0, else floor(x)
-- 2) Rounding to nearest integer :
-- . half down : y = ceil(x - 0.5),
-- . half up : y = floor(x + 0.5),
-- . half towards zero : y = sgn(x) ceil(|x| - 0.5) = ceil(x - 0.5) when x >= 0, else floor(x + 0.5)
-- . half away from zero : y = sgn(x) floor(|x| + 0.5) = floor(x + 0.5) when x >= 0, else ceil(x - 0.5)
-- . round half to even : rounds to the nearest even integer when fraction = 0.5 else use
-- either floor(x + 0.5) or ceil(x - 0.5), because they are equivalent then. This avoid
-- DC bias and bias towards or away from zero.
--
-- 3) Randomized rounding to an integer : round to nearest when fraction != 0.5, round up or
-- down when fraction = 0.5. This avoid DC bias and bias towards or away from zero:
-- . alternate tie breaking : alternately select round up or round down when fraction = 0.5
-- else either floor(x + 0.5) or ceil(x - 0.5), because they are equivalent then.
-- . random tie breaking : idem as alternate tie breaking, but use random selection.
-- . stochastic rounding : round up or down with a probability that depends on proximity.
-- This avoids DC bias when the input is not random, e.g. when the input has a constant
-- fraction > 0. For DSP with ADC related data with sufficient dynamic range this does
-- not occur.
--
-- The advantage of round half to even, over round with tie breaking is, that for tie
-- breaking an external signal is needed to hold the alternate or random selector state,
-- whereas for round half to even the current input signal itself determines the
-- selection. Hence round half to even can be fully implemented in a function, whereas
-- a function for round using tie breaking requires an external state to manage the
-- selection.
--
-- * Half up introduces +DC bias when fraction 0.5 occurs.
-- * Half away from zero is also used by round() in VHDL math_real, Matlab, Python, TCL.
-- * Half away avoids DC bias, but does introduce bias away from zero, which can show
-- as a up bias in power values because (negative)**2 > 0 and (positive)**2 > 0.
--
-- Functions s_round() and u_round():
--
-- . u_round() supports half up (= half away) and half even.
-- . s_round() supports half away and half even.
-- . 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 VHDL math_real, 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, even : BOOLEAN) RETURN STD_LOGIC_VECTOR IS
-- # Round half away from zero when even = FALSE, else round half to even.
-- # Round half to even algorithm:
-- # vec: -3.5 -2.5 -1.5 -0.5 0.5 1.5 2.5 3.5
-- # floor(vec + 0.5) -4 -3 -2 -1 1 2 3 4
-- # round even -4 -2 -2 0 0 2 2 4
-- # round even clip -4 -2 -2 0 0 2 2 3, clip to c_clip = 3 when c_out_w = 3
-- Use SIGNED instead of NATURAL for c_half to avoid INTEGER (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
-- When c_out_w = 1, then c_clip = 0, because a 1 bit signed value is -1 or 0
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);
CONSTANT u_half : UNSIGNED(n-1 DOWNTO 0) := UNSIGNED(STD_LOGIC_VECTOR(c_half(n-1 DOWNTO 0))); -- convert to UNSIGNED to compare with u_fraction
VARIABLE u_fraction : UNSIGNED(n-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 even = FALSE THEN
-- Round half away
IF vec(vec'HIGH)='0' THEN
v_out := RESIZE_NUM(SHIFT_RIGHT(v_in + c_half + 0, n), c_out_w); -- Round half up for positive
ELSE
v_out := RESIZE_NUM(SHIFT_RIGHT(v_in + c_half - 1, n), c_out_w); -- Round half down for negative
END IF;
ELSE
-- Round half to even
v_out := RESIZE_NUM(SHIFT_RIGHT(v_in + c_half, n), c_out_w); -- Round to nearest using floor(vec + 0.5)
u_fraction := UNSIGNED(vec(n-1 DOWNTO 0));
IF u_fraction = u_half AND v_out(0) = '1' THEN -- Round half to even, so when odd subtract 1
v_out := v_out - 1; -- to make v_out even
END IF;
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) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN s_round(vec, n, clip, FALSE); -- no round half to even
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;
-- for unsigned round half away and round half up are equivalent
FUNCTION u_round(vec : STD_LOGIC_VECTOR; n : NATURAL; clip, even : BOOLEAN) RETURN STD_LOGIC_VECTOR IS
CONSTANT c_in_w : NATURAL := vec'LENGTH;
CONSTANT c_out_w : NATURAL := vec'LENGTH - n;
VARIABLE in_vec : STD_LOGIC_VECTOR(c_in_w DOWNTO 0);
VARIABLE out_vec : STD_LOGIC_VECTOR(c_out_w DOWNTO 0);
BEGIN
-- Convert unsigned to positive signed and back to be able to reuse s_round()
in_vec := '0' & vec;
out_vec := s_round(in_vec, n, clip, even);
RETURN out_vec(c_out_w-1 DOWNTO 0);
END;
FUNCTION u_round(vec : STD_LOGIC_VECTOR; n : NATURAL; clip : BOOLEAN) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN u_round(vec, n, clip, FALSE); -- no round half to even
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;