URL
https://opencores.org/ocsvn/dp_pkg/dp_pkg/trunk
Subversion Repositories dp_pkg
Compare Revisions
- This comparison shows the changes necessary to convert path
/dp_pkg/trunk
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/dp_stream_pkg.vhd
0,0 → 1,1293
-------------------------------------------------------------------------------- |
-- |
-- Copyright (C) 2010 |
-- 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/>. |
-- |
-------------------------------------------------------------------------------- |
|
LIBRARY IEEE, common_pkg_lib; |
USE IEEE.STD_LOGIC_1164.ALL; |
USE IEEE.numeric_std.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
|
PACKAGE dp_stream_pkg Is |
|
------------------------------------------------------------------------------ |
-- General DP stream record defintion |
------------------------------------------------------------------------------ |
|
-- Remarks: |
-- * Choose smallest maximum SOSI slv lengths that fit all use cases, because unconstrained record fields slv is not allowed |
-- * The large SOSI data field width of 256b has some disadvantages: |
-- . about 10% extra simulation time and PC memory usage compared to 72b (measured using tb_unb_tse_board) |
-- . a 256b number has 64 hex digits in the Wave window which is awkward because of the leading zeros when typically |
-- only 32b are used, fortunately integer representation still works OK (except 0 which is shown as blank). |
-- However the alternatives are not attractive, because they affect the implementation of the streaming |
-- components that use the SOSI record. Alternatives are e.g.: |
-- . define an extra long SOSI data field ldata[255:0] in addition to the existing data[71:0] field |
-- . use the array of SOSI records to contain wider data, all with the same SOSI control field values |
-- . define another similar SOSI record with data[255:0]. |
-- Therefore define data width as 256b, because the disadvantages are acceptable and the benefit is great, because all |
-- streaming components can remain as they are. |
-- * Added sync and bsn to SOSI to have timestamp information with the data |
-- * Added re and im to SOSI to support complex data for DSP |
-- * The sosi fields can be labeled in diffent groups: ctrl, info and data as shown in comment at the t_dp_sosi definition. |
-- This grouping is useful for functions that operate on a t_dp_sosi signal. |
-- * The info fields are valid at the sop or at the eop, but typically they hold their last active value to avoid unnessary |
-- toggling and to ease viewing in the wave window. |
CONSTANT c_dp_stream_bsn_w : NATURAL := 64; -- 64 is sufficient to count blocks of data for years |
CONSTANT c_dp_stream_data_w : NATURAL := 768; -- 72 is sufficient for max word 8 * 9-bit. 576 supports half rate DDR4 bus data width. The current 768 is enough for wide single clock SLVs (e.g. headers) |
CONSTANT c_dp_stream_dsp_data_w : NATURAL := 64; -- 64 is sufficient for DSP data, including complex power accumulates |
CONSTANT c_dp_stream_empty_w : NATURAL := 16; -- 8 is sufficient for max 256 symbols per data word, still use 16 bit to be able to count c_dp_stream_data_w in bits |
CONSTANT c_dp_stream_channel_w : NATURAL := 32; -- 32 is sufficient for several levels of hierarchy in mapping types of streams on to channels |
CONSTANT c_dp_stream_error_w : NATURAL := 32; -- 32 is sufficient for several levels of hierarchy in mapping error numbers, e.g. 32 different one-hot encoded errors, bit [0] = 0 = OK |
|
CONSTANT c_dp_stream_ok : NATURAL := 0; -- SOSI err field OK value |
CONSTANT c_dp_stream_err : NATURAL := 1; -- SOSI err field error value /= OK |
|
CONSTANT c_dp_stream_rl : NATURAL := 1; -- SISO default data path stream ready latency RL = 1 |
|
TYPE t_dp_siso IS RECORD -- Source In or Sink Out |
ready : STD_LOGIC; -- fine cycle based flow control using ready latency RL >= 0 |
xon : STD_LOGIC; -- coarse typically block based flow control using xon/xoff |
END RECORD; |
|
TYPE t_dp_sosi IS RECORD -- Source Out or Sink In |
sync : STD_LOGIC; -- ctrl |
bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); -- info at sop (block sequence number) |
data : STD_LOGIC_VECTOR(c_dp_stream_data_w-1 DOWNTO 0); -- data |
re : STD_LOGIC_VECTOR(c_dp_stream_dsp_data_w-1 DOWNTO 0); -- data |
im : STD_LOGIC_VECTOR(c_dp_stream_dsp_data_w-1 DOWNTO 0); -- data |
valid : STD_LOGIC; -- ctrl |
sop : STD_LOGIC; -- ctrl |
eop : STD_LOGIC; -- ctrl |
empty : STD_LOGIC_VECTOR(c_dp_stream_empty_w-1 DOWNTO 0); -- info at eop |
channel : STD_LOGIC_VECTOR(c_dp_stream_channel_w-1 DOWNTO 0); -- info at sop |
err : STD_LOGIC_VECTOR(c_dp_stream_error_w-1 DOWNTO 0); -- info at eop (name field 'err' to avoid the 'error' keyword) |
END RECORD; |
|
-- Initialise signal declarations with c_dp_stream_rst/rdy to ease the interpretation of slv fields with unused bits |
CONSTANT c_dp_siso_rst : t_dp_siso := ('0', '0'); |
CONSTANT c_dp_siso_x : t_dp_siso := ('X', 'X'); |
CONSTANT c_dp_siso_hold : t_dp_siso := ('0', '1'); |
CONSTANT c_dp_siso_rdy : t_dp_siso := ('1', '1'); |
CONSTANT c_dp_siso_flush : t_dp_siso := ('1', '0'); |
CONSTANT c_dp_sosi_rst : t_dp_sosi := ('0', (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), '0', '0', '0', (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0')); |
CONSTANT c_dp_sosi_x : t_dp_sosi := ('X', (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), 'X', 'X', 'X', (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X')); |
|
-- Use integers instead of slv for monitoring purposes (integer range limited to 31 bit plus sign bit) |
TYPE t_dp_sosi_integer IS RECORD |
sync : STD_LOGIC; |
bsn : NATURAL; |
data : INTEGER; |
re : INTEGER; |
im : INTEGER; |
valid : STD_LOGIC; |
sop : STD_LOGIC; |
eop : STD_LOGIC; |
empty : NATURAL; |
channel : NATURAL; |
err : NATURAL; |
END RECORD; |
|
-- Use unsigned instead of slv for monitoring purposes beyond the integer range of t_dp_sosi_integer |
TYPE t_dp_sosi_unsigned IS RECORD |
sync : STD_LOGIC; |
bsn : UNSIGNED(c_dp_stream_bsn_w-1 DOWNTO 0); |
data : UNSIGNED(c_dp_stream_data_w-1 DOWNTO 0); |
re : UNSIGNED(c_dp_stream_dsp_data_w-1 DOWNTO 0); |
im : UNSIGNED(c_dp_stream_dsp_data_w-1 DOWNTO 0); |
valid : STD_LOGIC; |
sop : STD_LOGIC; |
eop : STD_LOGIC; |
empty : UNSIGNED(c_dp_stream_empty_w-1 DOWNTO 0); |
channel : UNSIGNED(c_dp_stream_channel_w-1 DOWNTO 0); |
err : UNSIGNED(c_dp_stream_error_w-1 DOWNTO 0); |
END RECORD; |
|
CONSTANT c_dp_sosi_unsigned_rst : t_dp_sosi_unsigned := ('0', (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), '0', '0', '0', (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0')); |
CONSTANT c_dp_sosi_unsigned_ones : t_dp_sosi_unsigned := ('1', |
TO_UNSIGNED(1, c_dp_stream_bsn_w), |
TO_UNSIGNED(1, c_dp_stream_data_w), |
TO_UNSIGNED(1, c_dp_stream_dsp_data_w), |
TO_UNSIGNED(1, c_dp_stream_dsp_data_w), |
'1', '1', '1', |
TO_UNSIGNED(1, c_dp_stream_empty_w), |
TO_UNSIGNED(1, c_dp_stream_channel_w), |
TO_UNSIGNED(1, c_dp_stream_error_w)); |
|
-- Use boolean to define whether a t_dp_siso, t_dp_sosi field is used ('1') or not ('0') |
TYPE t_dp_siso_sl IS RECORD |
ready : STD_LOGIC; |
xon : STD_LOGIC; |
END RECORD; |
|
TYPE t_dp_sosi_sl IS RECORD |
sync : STD_LOGIC; |
bsn : STD_LOGIC; |
data : STD_LOGIC; |
re : STD_LOGIC; |
im : STD_LOGIC; |
valid : STD_LOGIC; |
sop : STD_LOGIC; |
eop : STD_LOGIC; |
empty : STD_LOGIC; |
channel : STD_LOGIC; |
err : STD_LOGIC; |
END RECORD; |
|
CONSTANT c_dp_siso_sl_rst : t_dp_siso_sl := ('0', '0'); |
CONSTANT c_dp_siso_sl_ones : t_dp_siso_sl := ('1', '1'); |
CONSTANT c_dp_sosi_sl_rst : t_dp_sosi_sl := ('0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'); |
CONSTANT c_dp_sosi_sl_ones : t_dp_sosi_sl := ('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'); |
|
-- Multi port or multi register array for DP stream records |
TYPE t_dp_siso_arr IS ARRAY (INTEGER RANGE <>) OF t_dp_siso; |
TYPE t_dp_sosi_arr IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi; |
|
TYPE t_dp_sosi_integer_arr IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_integer; |
TYPE t_dp_sosi_unsigned_arr IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_unsigned; |
|
TYPE t_dp_siso_sl_arr IS ARRAY (INTEGER RANGE <>) OF t_dp_siso_sl; |
TYPE t_dp_sosi_sl_arr IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_sl; |
|
-- Multi port or multi register slv arrays for DP stream records fields |
TYPE t_dp_bsn_slv_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); |
TYPE t_dp_data_slv_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_dp_stream_data_w-1 DOWNTO 0); |
TYPE t_dp_dsp_data_slv_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_dp_stream_dsp_data_w-1 DOWNTO 0); |
TYPE t_dp_empty_slv_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_dp_stream_empty_w-1 DOWNTO 0); |
TYPE t_dp_channel_slv_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_dp_stream_channel_w-1 DOWNTO 0); |
TYPE t_dp_error_slv_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_dp_stream_error_w-1 DOWNTO 0); |
|
-- Multi-dimemsion array types with fixed LS-dimension |
TYPE t_dp_siso_2arr_1 IS ARRAY (INTEGER RANGE <>) OF t_dp_siso_arr(0 DOWNTO 0); |
TYPE t_dp_sosi_2arr_1 IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_arr(0 DOWNTO 0); |
|
-- . 2 dimensional array with 2 fixed LS sosi/siso interfaces (dp_split, dp_concat) |
TYPE t_dp_siso_2arr_2 IS ARRAY (INTEGER RANGE <>) OF t_dp_siso_arr(1 DOWNTO 0); |
TYPE t_dp_sosi_2arr_2 IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_arr(1 DOWNTO 0); |
|
TYPE t_dp_siso_2arr_3 IS ARRAY (INTEGER RANGE <>) OF t_dp_siso_arr(2 DOWNTO 0); |
TYPE t_dp_sosi_2arr_3 IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_arr(2 DOWNTO 0); |
|
TYPE t_dp_siso_2arr_4 IS ARRAY (INTEGER RANGE <>) OF t_dp_siso_arr(3 DOWNTO 0); |
TYPE t_dp_sosi_2arr_4 IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_arr(3 DOWNTO 0); |
|
TYPE t_dp_siso_2arr_8 IS ARRAY (INTEGER RANGE <>) OF t_dp_siso_arr(7 DOWNTO 0); |
TYPE t_dp_sosi_2arr_8 IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_arr(7 DOWNTO 0); |
|
TYPE t_dp_siso_2arr_9 IS ARRAY (INTEGER RANGE <>) OF t_dp_siso_arr(8 DOWNTO 0); |
TYPE t_dp_sosi_2arr_9 IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_arr(8 DOWNTO 0); |
|
TYPE t_dp_siso_2arr_12 IS ARRAY (INTEGER RANGE <>) OF t_dp_siso_arr(11 DOWNTO 0); |
TYPE t_dp_sosi_2arr_12 IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_arr(11 DOWNTO 0); |
|
TYPE t_dp_siso_3arr_4_2 IS ARRAY (INTEGER RANGE <>) OF t_dp_siso_2arr_2(3 DOWNTO 0); |
TYPE t_dp_sosi_3arr_4_2 IS ARRAY (INTEGER RANGE <>) OF t_dp_sosi_2arr_2(3 DOWNTO 0); |
|
-- 2-dimensional streaming array type: |
-- Note: |
-- This t_*_mat is less useful then a t_*_2arr array of arrays, because assignments can only be done per element (i.e. not per row). However for t_*_2arr |
-- the arrays dimension must be fixed, so these t_*_2arr types are application dependent and need to be defined where used. |
TYPE t_dp_siso_mat IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF t_dp_siso; |
TYPE t_dp_sosi_mat IS ARRAY (INTEGER RANGE <>, INTEGER RANGE <>) OF t_dp_sosi; |
|
-- Check sosi.valid against siso.ready |
PROCEDURE proc_dp_siso_alert(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sosi : IN t_dp_sosi; |
SIGNAL siso : IN t_dp_siso; |
SIGNAL ready_reg : INOUT STD_LOGIC_VECTOR); |
|
-- Default RL=1 |
PROCEDURE proc_dp_siso_alert(SIGNAL clk : IN STD_LOGIC; |
SIGNAL sosi : IN t_dp_sosi; |
SIGNAL siso : IN t_dp_siso; |
SIGNAL ready_reg : INOUT STD_LOGIC_VECTOR); |
|
-- SOSI/SISO array version |
PROCEDURE proc_dp_siso_alert(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sosi_arr : IN t_dp_sosi_arr; |
SIGNAL siso_arr : IN t_dp_siso_arr; |
SIGNAL ready_reg : INOUT STD_LOGIC_VECTOR); |
|
-- SOSI/SISO array version with RL=1 |
PROCEDURE proc_dp_siso_alert(SIGNAL clk : IN STD_LOGIC; |
SIGNAL sosi_arr : IN t_dp_sosi_arr; |
SIGNAL siso_arr : IN t_dp_siso_arr; |
SIGNAL ready_reg : INOUT STD_LOGIC_VECTOR); |
|
-- Resize functions to fit an integer or an SLV in the corresponding t_dp_sosi field width |
-- . Use these functions to assign sosi data TO a record field |
-- . Use the range selection [n-1 DOWNTO 0] to assign sosi data FROM a record field to an slv |
-- . The unused sosi data field bits could remain undefined 'X', because the unused bits in the fields are not used at all. |
-- Typically the sosi data are treated as unsigned in the record field, so extended with '0'. However for interpretating |
-- signed data in the simulation wave window it is easier to use sign extension in the record field. Therefore TO_DP_SDATA |
-- and RESIZE_DP_SDATA are defined as well. |
FUNCTION TO_DP_BSN( n : NATURAL) RETURN STD_LOGIC_VECTOR; |
FUNCTION TO_DP_DATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- use integer to support 32 bit range, so -1 = 0xFFFFFFFF = +2**32-1 |
FUNCTION TO_DP_SDATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- use integer to support 32 bit range and signed |
FUNCTION TO_DP_UDATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- alias of TO_DP_DATA() |
FUNCTION TO_DP_DSP_DATA(n : INTEGER) RETURN STD_LOGIC_VECTOR; -- for re and im fields, signed data |
FUNCTION TO_DP_DSP_UDATA(n: INTEGER) RETURN STD_LOGIC_VECTOR; -- for re and im fields, unsigned data (useful to carry indices) |
FUNCTION TO_DP_EMPTY( n : NATURAL) RETURN STD_LOGIC_VECTOR; |
FUNCTION TO_DP_CHANNEL( n : NATURAL) RETURN STD_LOGIC_VECTOR; |
FUNCTION TO_DP_ERROR( n : NATURAL) RETURN STD_LOGIC_VECTOR; |
FUNCTION RESIZE_DP_BSN( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; |
FUNCTION RESIZE_DP_DATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- set unused MSBits to '0' |
FUNCTION RESIZE_DP_SDATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- sign extend unused MSBits |
FUNCTION RESIZE_DP_XDATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- set unused MSBits to 'X' |
FUNCTION RESIZE_DP_DSP_DATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- sign extend unused MSBits of re and im fields |
FUNCTION RESIZE_DP_EMPTY( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; |
FUNCTION RESIZE_DP_CHANNEL( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; |
FUNCTION RESIZE_DP_ERROR( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; |
|
FUNCTION INCR_DP_DATA( vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- unsigned vec(w-1:0) + dec |
FUNCTION INCR_DP_SDATA( vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- signed vec(w-1:0) + dec |
FUNCTION INCR_DP_DSP_DATA(vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR; -- signed vec(w-1:0) + dec |
|
FUNCTION REPLICATE_DP_DATA( seq : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR; -- replicate seq as often as fits in c_dp_stream_data_w |
FUNCTION UNREPLICATE_DP_DATA(data : STD_LOGIC_VECTOR; seq_w : NATURAL) RETURN STD_LOGIC_VECTOR; -- unreplicate data to width seq_w, return low seq_w bits and set mismatch MSbits bits to '1' |
|
FUNCTION TO_DP_SOSI_UNSIGNED(sync, valid, sop, eop : STD_LOGIC; bsn, data, re, im, empty, channel, err : UNSIGNED) RETURN t_dp_sosi_unsigned; |
|
-- Keep part of head data and combine part of tail data, use the other sosi from head_sosi |
FUNCTION func_dp_data_shift_first(head_sosi, tail_sosi : t_dp_sosi; symbol_w, nof_symbols_per_data, nof_symbols_from_tail : NATURAL) RETURN t_dp_sosi; |
-- Shift and combine part of previous data and this data, use the other sosi from prev_sosi |
FUNCTION func_dp_data_shift( prev_sosi, this_sosi : t_dp_sosi; symbol_w, nof_symbols_per_data, nof_symbols_from_this : NATURAL) RETURN t_dp_sosi; |
-- Shift part of tail data and account for input empty |
FUNCTION func_dp_data_shift_last( tail_sosi : t_dp_sosi; symbol_w, nof_symbols_per_data, nof_symbols_from_tail, input_empty : NATURAL) RETURN t_dp_sosi; |
|
-- Determine resulting empty if two streams are concatenated or split |
FUNCTION func_dp_empty_concat(head_empty, tail_empty : STD_LOGIC_VECTOR; nof_symbols_per_data : NATURAL) RETURN STD_LOGIC_VECTOR; |
FUNCTION func_dp_empty_split(input_empty, head_empty : STD_LOGIC_VECTOR; nof_symbols_per_data : NATURAL) RETURN STD_LOGIC_VECTOR; |
|
-- Multiplex the t_dp_sosi_arr based on the valid, assuming that at most one input is active valid. |
FUNCTION func_dp_sosi_arr_mux(dp : t_dp_sosi_arr) RETURN t_dp_sosi; |
|
-- Determine the combined logical value of corresponding STD_LOGIC fields in t_dp_*_arr (for all elements or only for the mask[]='1' elements) |
FUNCTION func_dp_stream_arr_and(dp : t_dp_siso_arr; mask : STD_LOGIC_VECTOR; str : STRING) RETURN STD_LOGIC; |
FUNCTION func_dp_stream_arr_and(dp : t_dp_sosi_arr; mask : STD_LOGIC_VECTOR; str : STRING) RETURN STD_LOGIC; |
FUNCTION func_dp_stream_arr_and(dp : t_dp_siso_arr; str : STRING) RETURN STD_LOGIC; |
FUNCTION func_dp_stream_arr_and(dp : t_dp_sosi_arr; str : STRING) RETURN STD_LOGIC; |
FUNCTION func_dp_stream_arr_or( dp : t_dp_siso_arr; mask : STD_LOGIC_VECTOR; str : STRING) RETURN STD_LOGIC; |
FUNCTION func_dp_stream_arr_or( dp : t_dp_sosi_arr; mask : STD_LOGIC_VECTOR; str : STRING) RETURN STD_LOGIC; |
FUNCTION func_dp_stream_arr_or( dp : t_dp_siso_arr; str : STRING) RETURN STD_LOGIC; |
FUNCTION func_dp_stream_arr_or( dp : t_dp_sosi_arr; str : STRING) RETURN STD_LOGIC; |
|
-- Functions to set or get a STD_LOGIC field as a STD_LOGIC_VECTOR to or from an siso or an sosi array |
FUNCTION func_dp_stream_arr_set(dp : t_dp_siso_arr; slv : STD_LOGIC_VECTOR; str : STRING) RETURN t_dp_siso_arr; |
FUNCTION func_dp_stream_arr_set(dp : t_dp_sosi_arr; slv : STD_LOGIC_VECTOR; str : STRING) RETURN t_dp_sosi_arr; |
FUNCTION func_dp_stream_arr_set(dp : t_dp_siso_arr; sl : STD_LOGIC; str : STRING) RETURN t_dp_siso_arr; |
FUNCTION func_dp_stream_arr_set(dp : t_dp_sosi_arr; sl : STD_LOGIC; str : STRING) RETURN t_dp_sosi_arr; |
FUNCTION func_dp_stream_arr_get(dp : t_dp_siso_arr; str : STRING) RETURN STD_LOGIC_VECTOR; |
FUNCTION func_dp_stream_arr_get(dp : t_dp_sosi_arr; str : STRING) RETURN STD_LOGIC_VECTOR; |
|
-- Functions to select elements from two siso or two sosi arrays (sel[] = '1' selects a, sel[] = '0' selects b) |
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a, b : t_dp_siso) RETURN t_dp_siso_arr; |
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a, b : t_dp_sosi) RETURN t_dp_sosi_arr; |
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a : t_dp_siso_arr; b : t_dp_siso) RETURN t_dp_siso_arr; |
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a : t_dp_sosi_arr; b : t_dp_sosi) RETURN t_dp_sosi_arr; |
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a : t_dp_siso; b : t_dp_siso_arr) RETURN t_dp_siso_arr; |
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a : t_dp_sosi; b : t_dp_sosi_arr) RETURN t_dp_sosi_arr; |
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a, b : t_dp_siso_arr) RETURN t_dp_siso_arr; |
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a, b : t_dp_sosi_arr) RETURN t_dp_sosi_arr; |
|
-- Fix reversed buses due to connecting TO to DOWNTO range arrays. |
FUNCTION func_dp_stream_arr_reverse_range(in_arr : t_dp_sosi_arr) RETURN t_dp_sosi_arr; |
FUNCTION func_dp_stream_arr_reverse_range(in_arr : t_dp_siso_arr) RETURN t_dp_siso_arr; |
|
-- Functions to combinatorially hold the data fields and to set or reset the control fields in an sosi array |
FUNCTION func_dp_stream_arr_combine_data_info_ctrl(dp : t_dp_sosi_arr; info, ctrl : t_dp_sosi) RETURN t_dp_sosi_arr; |
FUNCTION func_dp_stream_arr_set_info( dp : t_dp_sosi_arr; info : t_dp_sosi) RETURN t_dp_sosi_arr; |
FUNCTION func_dp_stream_arr_set_control( dp : t_dp_sosi_arr; ctrl : t_dp_sosi) RETURN t_dp_sosi_arr; |
FUNCTION func_dp_stream_arr_reset_control( dp : t_dp_sosi_arr ) RETURN t_dp_sosi_arr; |
|
-- Reset sosi ctrl and preserve the sosi data (to avoid unnecessary data toggling and to ease data view in Wave window) |
FUNCTION func_dp_stream_reset_control(dp : t_dp_sosi) RETURN t_dp_sosi; |
|
-- Functions to combinatorially determine the maximum and minimum sosi bsn[w-1:0] value in the sosi array (for all elements or only for the mask[]='1' elements) |
FUNCTION func_dp_stream_arr_bsn_max(dp : t_dp_sosi_arr; mask : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR; |
FUNCTION func_dp_stream_arr_bsn_max(dp : t_dp_sosi_arr; w : NATURAL) RETURN STD_LOGIC_VECTOR; |
FUNCTION func_dp_stream_arr_bsn_min(dp : t_dp_sosi_arr; mask : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR; |
FUNCTION func_dp_stream_arr_bsn_min(dp : t_dp_sosi_arr; w : NATURAL) RETURN STD_LOGIC_VECTOR; |
|
-- Function to copy the BSN of one valid stream to all output streams. |
FUNCTION func_dp_stream_arr_copy_valid_bsn(dp : t_dp_sosi_arr; mask : STD_LOGIC_VECTOR) RETURN t_dp_sosi_arr; |
|
-- Functions to combinatorially handle channels |
-- Note that the *_select and *_remove function are equivalent to dp_demux with g_combined=TRUE |
FUNCTION func_dp_stream_channel_set (st_sosi : t_dp_sosi; ch : NATURAL) RETURN t_dp_sosi; -- select channel nr, add the channel field |
FUNCTION func_dp_stream_channel_select(st_sosi : t_dp_sosi; ch : NATURAL) RETURN t_dp_sosi; -- select channel nr, skip the channel field |
FUNCTION func_dp_stream_channel_remove(st_sosi : t_dp_sosi; ch : NATURAL) RETURN t_dp_sosi; -- skip channel nr |
|
-- Functions to combinatorially handle the error field |
FUNCTION func_dp_stream_error_set(st_sosi : t_dp_sosi; n : NATURAL) RETURN t_dp_sosi; -- force err = 0, is OK |
|
-- Functions to combinatorially handle the BSN field |
FUNCTION func_dp_stream_bsn_set(st_sosi : t_dp_sosi; bsn : STD_LOGIC_VECTOR) RETURN t_dp_sosi; |
|
-- Functions to combine sosi fields |
FUNCTION func_dp_stream_combine_info_and_data(info, data : t_dp_sosi) RETURN t_dp_sosi; |
|
-- Functions to convert sosi fields |
FUNCTION func_dp_stream_slv_to_integer(slv_sosi : t_dp_sosi; w : NATURAL) RETURN t_dp_sosi_integer; |
|
-- Functions to set the DATA, RE and IM field in a stream. |
FUNCTION func_dp_stream_set_data(dp : t_dp_sosi; slv : STD_LOGIC_VECTOR; str : STRING ) RETURN t_dp_sosi; |
FUNCTION func_dp_stream_set_data(dp : t_dp_sosi_arr; slv : STD_LOGIC_VECTOR; str : STRING ) RETURN t_dp_sosi_arr; |
FUNCTION func_dp_stream_set_data(dp : t_dp_sosi_arr; slv : STD_LOGIC_VECTOR; str : STRING; mask : STD_LOGIC_VECTOR) RETURN t_dp_sosi_arr; |
|
-- Concatenate the data from a SOSI array into a single SOSI stream (assumes streams are in sync) |
FUNCTION func_dp_stream_concat(snk_in_arr : t_dp_sosi_arr; data_w : NATURAL) RETURN t_dp_sosi; -- Concat SOSI_ARR data into single SOSI |
FUNCTION func_dp_stream_concat(src_in : t_dp_siso; nof_streams : NATURAL) RETURN t_dp_siso_arr; -- Wire single SISO to SISO_ARR |
-- Deconcatenate data from SOSI into SOSI array |
FUNCTION func_dp_stream_deconcat(snk_in : t_dp_sosi; nof_streams, data_w : NATURAL) RETURN t_dp_sosi_arr; -- Deconcat SOSI data |
FUNCTION func_dp_stream_deconcat(src_out_arr : t_dp_siso_arr) RETURN t_dp_siso; -- Wire SISO_ARR(0) to single SISO |
|
END dp_stream_pkg; |
|
|
PACKAGE BODY dp_stream_pkg IS |
|
-- Check sosi.valid against siso.ready |
PROCEDURE proc_dp_siso_alert(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sosi : IN t_dp_sosi; |
SIGNAL siso : IN t_dp_siso; |
SIGNAL ready_reg : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
ready_reg(0) <= siso.ready; |
-- Register siso.ready in c_ready_latency registers |
IF rising_edge(clk) THEN |
-- Check DP sink |
IF sosi.valid = '1' AND ready_reg(c_ready_latency) = '0' THEN |
REPORT "RL ERROR" SEVERITY FAILURE; |
END IF; |
ready_reg( 1 TO c_ready_latency) <= ready_reg( 0 TO c_ready_latency-1); |
END IF; |
END proc_dp_siso_alert; |
|
-- Default RL=1 |
PROCEDURE proc_dp_siso_alert(SIGNAL clk : IN STD_LOGIC; |
SIGNAL sosi : IN t_dp_sosi; |
SIGNAL siso : IN t_dp_siso; |
SIGNAL ready_reg : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
proc_dp_siso_alert(1, clk, sosi, siso, ready_reg); |
END proc_dp_siso_alert; |
|
-- SOSI/SISO array version |
PROCEDURE proc_dp_siso_alert(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sosi_arr : IN t_dp_sosi_arr; |
SIGNAL siso_arr : IN t_dp_siso_arr; |
SIGNAL ready_reg : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
FOR i IN 0 TO sosi_arr'LENGTH-1 LOOP |
ready_reg(i*(c_ready_latency+1)) <= siso_arr(i).ready; -- SLV is used as an array: nof_streams*(0..c_ready_latency) |
END LOOP; |
-- Register siso.ready in c_ready_latency registers |
IF rising_edge(clk) THEN |
FOR i IN 0 TO sosi_arr'LENGTH-1 LOOP |
-- Check DP sink |
IF sosi_arr(i).valid = '1' AND ready_reg(i*(c_ready_latency+1)+1) = '0' THEN |
REPORT "RL ERROR" SEVERITY FAILURE; |
END IF; |
ready_reg(i*(c_ready_latency+1)+1 TO i*(c_ready_latency+1)+c_ready_latency) <= ready_reg(i*(c_ready_latency+1) TO i*(c_ready_latency+1)+c_ready_latency-1); |
END LOOP; |
END IF; |
END proc_dp_siso_alert; |
|
-- SOSI/SISO array version with RL=1 |
PROCEDURE proc_dp_siso_alert(SIGNAL clk : IN STD_LOGIC; |
SIGNAL sosi_arr : IN t_dp_sosi_arr; |
SIGNAL siso_arr : IN t_dp_siso_arr; |
SIGNAL ready_reg : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
proc_dp_siso_alert(1, clk, sosi_arr, siso_arr, ready_reg); |
END proc_dp_siso_alert; |
|
-- Resize functions to fit an integer or an SLV in the corresponding t_dp_sosi field width |
FUNCTION TO_DP_BSN(n : NATURAL) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_dp_stream_bsn_w); |
END TO_DP_BSN; |
|
FUNCTION TO_DP_DATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_dp_stream_data_w); |
END TO_DP_DATA; |
|
FUNCTION TO_DP_SDATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_SVEC(TO_SVEC(n, 32), c_dp_stream_data_w); |
END TO_DP_SDATA; |
|
FUNCTION TO_DP_UDATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN TO_DP_DATA(n); |
END TO_DP_UDATA; |
|
FUNCTION TO_DP_DSP_DATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_SVEC(TO_SVEC(n, 32), c_dp_stream_dsp_data_w); |
END TO_DP_DSP_DATA; |
|
FUNCTION TO_DP_DSP_UDATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_dp_stream_dsp_data_w); |
END TO_DP_DSP_UDATA; |
|
FUNCTION TO_DP_EMPTY(n : NATURAL) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN TO_UVEC(n, c_dp_stream_empty_w); |
END TO_DP_EMPTY; |
|
FUNCTION TO_DP_CHANNEL(n : NATURAL) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN TO_UVEC(n, c_dp_stream_channel_w); |
END TO_DP_CHANNEL; |
|
FUNCTION TO_DP_ERROR(n : NATURAL) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN TO_UVEC(n, c_dp_stream_error_w); |
END TO_DP_ERROR; |
|
FUNCTION RESIZE_DP_BSN(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_UVEC(vec, c_dp_stream_bsn_w); |
END RESIZE_DP_BSN; |
|
FUNCTION RESIZE_DP_DATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_UVEC(vec, c_dp_stream_data_w); |
END RESIZE_DP_DATA; |
|
FUNCTION RESIZE_DP_SDATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_SVEC(vec, c_dp_stream_data_w); |
END RESIZE_DP_SDATA; |
|
FUNCTION RESIZE_DP_XDATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
VARIABLE v_vec : STD_LOGIC_VECTOR(c_dp_stream_data_w-1 DOWNTO 0) := (OTHERS=>'X'); |
BEGIN |
v_vec(vec'LENGTH-1 DOWNTO 0) := vec; |
RETURN v_vec; |
END RESIZE_DP_XDATA; |
|
FUNCTION RESIZE_DP_DSP_DATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_SVEC(vec, c_dp_stream_dsp_data_w); |
END RESIZE_DP_DSP_DATA; |
|
FUNCTION RESIZE_DP_EMPTY(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_UVEC(vec, c_dp_stream_empty_w); |
END RESIZE_DP_EMPTY; |
|
FUNCTION RESIZE_DP_CHANNEL(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_UVEC(vec, c_dp_stream_channel_w); |
END RESIZE_DP_CHANNEL; |
|
FUNCTION RESIZE_DP_ERROR(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_UVEC(vec, c_dp_stream_error_w); |
END RESIZE_DP_ERROR; |
|
FUNCTION INCR_DP_DATA(vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_DP_DATA(STD_LOGIC_VECTOR(UNSIGNED(vec(w-1 DOWNTO 0)) + dec)); |
END INCR_DP_DATA; |
|
FUNCTION INCR_DP_SDATA(vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_DP_SDATA(STD_LOGIC_VECTOR(SIGNED(vec(w-1 DOWNTO 0)) + dec)); |
END INCR_DP_SDATA; |
|
FUNCTION INCR_DP_DSP_DATA(vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR IS |
BEGIN |
RETURN RESIZE_DP_DSP_DATA(STD_LOGIC_VECTOR(SIGNED(vec(w-1 DOWNTO 0)) + dec)); |
END INCR_DP_DSP_DATA; |
|
FUNCTION REPLICATE_DP_DATA(seq : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
CONSTANT c_seq_w : NATURAL := seq'LENGTH; |
CONSTANT c_nof_replications : NATURAL := ceil_div(c_dp_stream_data_w, c_seq_w); |
CONSTANT c_vec_w : NATURAL := ceil_value(c_dp_stream_data_w, c_seq_w); |
VARIABLE v_vec : STD_LOGIC_VECTOR(c_vec_w-1 DOWNTO 0); |
BEGIN |
FOR I IN 0 TO c_nof_replications-1 LOOP |
v_vec((I+1)*c_seq_w-1 DOWNTO I*c_seq_w) := seq; |
END LOOP; |
RETURN v_vec(c_dp_stream_data_w-1 DOWNTO 0); |
END REPLICATE_DP_DATA; |
|
FUNCTION UNREPLICATE_DP_DATA(data : STD_LOGIC_VECTOR; seq_w :NATURAL) RETURN STD_LOGIC_VECTOR IS |
CONSTANT c_data_w : NATURAL := data'LENGTH; |
CONSTANT c_nof_replications : NATURAL := ceil_div(c_data_w, seq_w); |
CONSTANT c_vec_w : NATURAL := ceil_value(c_data_w, seq_w); |
VARIABLE v_seq : STD_LOGIC_VECTOR(seq_w-1 DOWNTO 0); |
VARIABLE v_data : STD_LOGIC_VECTOR(c_vec_w-1 DOWNTO 0); |
VARIABLE v_vec : STD_LOGIC_VECTOR(c_vec_w-1 DOWNTO 0); |
BEGIN |
v_data := RESIZE_UVEC(data, c_vec_w); |
v_seq := v_data(seq_w-1 DOWNTO 0); -- low data part is the v_seq |
v_vec(seq_w-1 DOWNTO 0) := v_seq; -- keep v_seq at low part of return value |
IF c_nof_replications>1 THEN |
FOR I IN 1 TO c_nof_replications-1 LOOP |
v_vec((I+1)*seq_w-1 DOWNTO I*seq_w) := v_data((I+1)*seq_w-1 DOWNTO I*seq_w) XOR v_seq; -- set return bit to '1' for high part data bits that do not match low part v_seq |
END LOOP; |
END IF; |
RETURN v_vec(c_data_w-1 DOWNTO 0); |
END UNREPLICATE_DP_DATA; |
|
FUNCTION TO_DP_SOSI_UNSIGNED(sync, valid, sop, eop : STD_LOGIC; bsn, data, re, im, empty, channel, err : UNSIGNED) RETURN t_dp_sosi_unsigned IS |
VARIABLE v_sosi_unsigned : t_dp_sosi_unsigned; |
BEGIN |
v_sosi_unsigned.sync := sync; |
v_sosi_unsigned.valid := valid; |
v_sosi_unsigned.sop := sop; |
v_sosi_unsigned.eop := eop; |
v_sosi_unsigned.bsn := RESIZE(bsn, c_dp_stream_bsn_w); |
v_sosi_unsigned.data := RESIZE(data, c_dp_stream_data_w); |
v_sosi_unsigned.re := RESIZE(re, c_dp_stream_dsp_data_w); |
v_sosi_unsigned.im := RESIZE(im, c_dp_stream_dsp_data_w); |
v_sosi_unsigned.empty := RESIZE(empty, c_dp_stream_empty_w); |
v_sosi_unsigned.channel := RESIZE(channel, c_dp_stream_channel_w); |
v_sosi_unsigned.err := RESIZE(err, c_dp_stream_error_w); |
RETURN v_sosi_unsigned; |
END TO_DP_SOSI_UNSIGNED; |
|
-- Keep part of head data and combine part of tail data |
FUNCTION func_dp_data_shift_first(head_sosi, tail_sosi : t_dp_sosi; symbol_w, nof_symbols_per_data, nof_symbols_from_tail : NATURAL) RETURN t_dp_sosi IS |
VARIABLE vN : NATURAL := nof_symbols_per_data; |
VARIABLE v_sosi : t_dp_sosi; |
BEGIN |
ASSERT nof_symbols_from_tail<vN REPORT "func_dp_data_shift_first : no symbols from head" SEVERITY FAILURE; |
-- use the other sosi from head_sosi |
v_sosi := head_sosi; -- I = nof_symbols_from_tail = 0 |
FOR I IN 1 TO vN-1 LOOP -- I > 0 |
IF nof_symbols_from_tail = I THEN |
v_sosi.data(I*symbol_w-1 DOWNTO 0) := tail_sosi.data(vN*symbol_w-1 DOWNTO (vN-I)*symbol_w); |
END IF; |
END LOOP; |
RETURN v_sosi; |
END func_dp_data_shift_first; |
|
|
-- Shift and combine part of previous data and this data, |
FUNCTION func_dp_data_shift(prev_sosi, this_sosi : t_dp_sosi; symbol_w, nof_symbols_per_data, nof_symbols_from_this : NATURAL) RETURN t_dp_sosi IS |
VARIABLE vK : NATURAL := nof_symbols_from_this; |
VARIABLE vN : NATURAL := nof_symbols_per_data; |
VARIABLE v_sosi : t_dp_sosi; |
BEGIN |
-- use the other sosi from this_sosi if nof_symbols_from_this > 0 else use other sosi from prev_sosi |
IF vK>0 THEN |
v_sosi := this_sosi; |
ELSE |
v_sosi := prev_sosi; |
END IF; |
|
-- use sosi data from both if 0 < nof_symbols_from_this < nof_symbols_per_data (i.e. 0 < I < vN) |
IF vK<nof_symbols_per_data THEN -- I = vK = nof_symbols_from_this < vN |
-- Implementation using variable vK directly instead of via I in a LOOP |
-- IF vK > 0 THEN |
-- v_sosi.data(vN*symbol_w-1 DOWNTO vK*symbol_w) := prev_sosi.data((vN-vK)*symbol_w-1 DOWNTO 0); |
-- v_sosi.data( vK*symbol_w-1 DOWNTO 0) := this_sosi.data( vN *symbol_w-1 DOWNTO (vN-vK)*symbol_w); |
-- END IF; |
-- Implementaion using LOOP vK rather than VARIABLE vK directly as index to help synthesis and avoid potential multiplier |
v_sosi.data := prev_sosi.data; -- I = vK = nof_symbols_from_this = 0 |
FOR I IN 1 TO vN-1 LOOP -- I = vK = nof_symbols_from_this > 0 |
IF vK = I THEN |
v_sosi.data(vN*symbol_w-1 DOWNTO I*symbol_w) := prev_sosi.data((vN-I)*symbol_w-1 DOWNTO 0); |
v_sosi.data( I*symbol_w-1 DOWNTO 0) := this_sosi.data( vN *symbol_w-1 DOWNTO (vN-I)*symbol_w); |
END IF; |
END LOOP; |
END IF; |
RETURN v_sosi; |
END func_dp_data_shift; |
|
|
-- Shift part of tail data and account for input empty |
FUNCTION func_dp_data_shift_last(tail_sosi : t_dp_sosi; symbol_w, nof_symbols_per_data, nof_symbols_from_tail, input_empty : NATURAL) RETURN t_dp_sosi IS |
VARIABLE vK : NATURAL := nof_symbols_from_tail; |
VARIABLE vL : NATURAL := input_empty; |
VARIABLE vN : NATURAL := nof_symbols_per_data; |
VARIABLE v_sosi : t_dp_sosi; |
BEGIN |
ASSERT vK > 0 REPORT "func_dp_data_shift_last : no symbols from tail" SEVERITY FAILURE; |
ASSERT vK+vL<=vN REPORT "func_dp_data_shift_last : impossible shift" SEVERITY FAILURE; |
v_sosi := tail_sosi; |
-- Implementation using variable vK directly instead of via I in a LOOP |
-- IF vK > 0 THEN |
-- v_sosi.data(vN*symbol_w-1 DOWNTO (vN-vK)*symbol_w) <= tail_sosi.data((vK+vL)*symbol_w-1 DOWNTO vL*symbol_w); |
-- END IF; |
-- Implementation using LOOP vK rather than VARIABLE vK directly as index to help synthesis and avoid potential multiplier |
-- Implementation using LOOP vL rather than VARIABLE vL directly as index to help synthesis and avoid potential multiplier |
FOR I IN 1 TO vN-1 LOOP |
IF vK = I THEN |
FOR J IN 0 TO vN-1 LOOP |
IF vL = J THEN |
v_sosi.data(vN*symbol_w-1 DOWNTO (vN-I)*symbol_w) := tail_sosi.data((I+J)*symbol_w-1 DOWNTO J*symbol_w); |
END IF; |
END LOOP; |
END IF; |
END LOOP; |
RETURN v_sosi; |
END func_dp_data_shift_last; |
|
|
-- Determine resulting empty if two streams are concatenated |
-- . both empty must use the same nof symbols per data |
FUNCTION func_dp_empty_concat(head_empty, tail_empty : STD_LOGIC_VECTOR; nof_symbols_per_data : NATURAL) RETURN STD_LOGIC_VECTOR IS |
VARIABLE v_a, v_b, v_empty : NATURAL; |
BEGIN |
v_a := TO_UINT(head_empty); |
v_b := TO_UINT(tail_empty); |
v_empty := v_a + v_b; |
IF v_empty >= nof_symbols_per_data THEN |
v_empty := v_empty - nof_symbols_per_data; |
END IF; |
RETURN TO_UVEC(v_empty, head_empty'LENGTH); |
END func_dp_empty_concat; |
|
FUNCTION func_dp_empty_split(input_empty, head_empty : STD_LOGIC_VECTOR; nof_symbols_per_data : NATURAL) RETURN STD_LOGIC_VECTOR IS |
VARIABLE v_a, v_b, v_empty : NATURAL; |
BEGIN |
v_a := TO_UINT(input_empty); |
v_b := TO_UINT(head_empty); |
IF v_a >= v_b THEN |
v_empty := v_a - v_b; |
ELSE |
v_empty := (nof_symbols_per_data + v_a) - v_b; |
END IF; |
RETURN TO_UVEC(v_empty, head_empty'LENGTH); |
END func_dp_empty_split; |
|
|
-- Multiplex the t_dp_sosi_arr based on the valid, assuming that at most one input is active valid. |
FUNCTION func_dp_sosi_arr_mux(dp : t_dp_sosi_arr) RETURN t_dp_sosi IS |
VARIABLE v_sosi : t_dp_sosi := c_dp_sosi_rst; |
BEGIN |
FOR I IN dp'RANGE LOOP |
IF dp(I).valid='1' THEN |
v_sosi := dp(I); |
EXIT; |
END IF; |
END LOOP; |
RETURN v_sosi; |
END func_dp_sosi_arr_mux; |
|
|
-- Determine the combined logical value of corresponding STD_LOGIC fields in t_dp_*_arr (for all elements or only for the mask[]='1' elements) |
FUNCTION func_dp_stream_arr_and(dp : t_dp_siso_arr; mask : STD_LOGIC_VECTOR; str : STRING) RETURN STD_LOGIC IS |
VARIABLE v_vec : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>'1'); -- set default v_vec such that unmasked input have no influence on operation result |
VARIABLE v_any : STD_LOGIC := '0'; |
BEGIN |
-- map siso field to v_vec |
FOR I IN dp'RANGE LOOP |
IF mask(I)='1' THEN |
v_any := '1'; |
IF str="READY" THEN v_vec(I) := dp(I).ready; |
ELSIF str="XON" THEN v_vec(I) := dp(I).xon; |
ELSE REPORT "Error in func_dp_stream_arr_and for t_dp_siso_arr"; |
END IF; |
END IF; |
END LOOP; |
-- do operation on the selected record field |
IF v_any='1' THEN |
RETURN vector_and(v_vec); -- return AND of the masked input fields |
ELSE |
RETURN '0'; -- return '0' if no input was masked |
END IF; |
END func_dp_stream_arr_and; |
|
FUNCTION func_dp_stream_arr_and(dp : t_dp_sosi_arr; mask : STD_LOGIC_VECTOR; str : STRING) RETURN STD_LOGIC IS |
VARIABLE v_vec : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>'1'); -- set default v_vec such that unmasked input have no influence on operation result |
VARIABLE v_any : STD_LOGIC := '0'; |
BEGIN |
-- map siso field to v_vec |
FOR I IN dp'RANGE LOOP |
IF mask(I)='1' THEN |
v_any := '1'; |
IF str="VALID" THEN v_vec(I) := dp(I).valid; |
ELSIF str="SOP" THEN v_vec(I) := dp(I).sop; |
ELSIF str="EOP" THEN v_vec(I) := dp(I).eop; |
ELSIF str="SYNC" THEN v_vec(I) := dp(I).sync; |
ELSE REPORT "Error in func_dp_stream_arr_and for t_dp_sosi_arr"; |
END IF; |
END IF; |
END LOOP; |
-- do operation on the selected record field |
IF v_any='1' THEN |
RETURN vector_and(v_vec); -- return AND of the masked input fields |
ELSE |
RETURN '0'; -- return '0' if no input was masked |
END IF; |
END func_dp_stream_arr_and; |
|
FUNCTION func_dp_stream_arr_and(dp : t_dp_siso_arr; str : STRING) RETURN STD_LOGIC IS |
CONSTANT c_mask : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>'1'); |
BEGIN |
RETURN func_dp_stream_arr_and(dp, c_mask, str); |
END func_dp_stream_arr_and; |
|
FUNCTION func_dp_stream_arr_and(dp : t_dp_sosi_arr; str : STRING) RETURN STD_LOGIC IS |
CONSTANT c_mask : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>'1'); |
BEGIN |
RETURN func_dp_stream_arr_and(dp, c_mask, str); |
END func_dp_stream_arr_and; |
|
FUNCTION func_dp_stream_arr_or(dp : t_dp_siso_arr; mask : STD_LOGIC_VECTOR; str : STRING) RETURN STD_LOGIC IS |
VARIABLE v_vec : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>'0'); -- set default v_vec such that unmasked input have no influence on operation result |
VARIABLE v_any : STD_LOGIC := '0'; |
BEGIN |
-- map siso field to v_vec |
FOR I IN dp'RANGE LOOP |
IF mask(I)='1' THEN |
v_any := '1'; |
IF str="READY" THEN v_vec(I) := dp(I).ready; |
ELSIF str="XON" THEN v_vec(I) := dp(I).xon; |
ELSE REPORT "Error in func_dp_stream_arr_or for t_dp_siso_arr"; |
END IF; |
END IF; |
END LOOP; |
-- do operation on the selected record field |
IF v_any='1' THEN |
RETURN vector_or(v_vec); -- return OR of the masked input fields |
ELSE |
RETURN '0'; -- return '0' if no input was masked |
END IF; |
END func_dp_stream_arr_or; |
|
FUNCTION func_dp_stream_arr_or(dp : t_dp_sosi_arr; mask : STD_LOGIC_VECTOR; str : STRING) RETURN STD_LOGIC IS |
VARIABLE v_vec : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>'0'); -- set default v_vec such that unmasked input have no influence on operation result |
VARIABLE v_any : STD_LOGIC := '0'; |
BEGIN |
-- map siso field to v_vec |
FOR I IN dp'RANGE LOOP |
IF mask(I)='1' THEN |
v_any := '1'; |
IF str="VALID" THEN v_vec(I) := dp(I).valid; |
ELSIF str="SOP" THEN v_vec(I) := dp(I).sop; |
ELSIF str="EOP" THEN v_vec(I) := dp(I).eop; |
ELSIF str="SYNC" THEN v_vec(I) := dp(I).sync; |
ELSE REPORT "Error in func_dp_stream_arr_or for t_dp_sosi_arr"; |
END IF; |
END IF; |
END LOOP; |
-- do operation on the selected record field |
IF v_any='1' THEN |
RETURN vector_or(v_vec); -- return OR of the masked input fields |
ELSE |
RETURN '0'; -- return '0' if no input was masked |
END IF; |
END func_dp_stream_arr_or; |
|
FUNCTION func_dp_stream_arr_or(dp : t_dp_siso_arr; str : STRING) RETURN STD_LOGIC IS |
CONSTANT c_mask : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>'1'); |
BEGIN |
RETURN func_dp_stream_arr_or(dp, c_mask, str); |
END func_dp_stream_arr_or; |
|
FUNCTION func_dp_stream_arr_or(dp : t_dp_sosi_arr; str : STRING) RETURN STD_LOGIC IS |
CONSTANT c_mask : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>'1'); |
BEGIN |
RETURN func_dp_stream_arr_or(dp, c_mask, str); |
END func_dp_stream_arr_or; |
|
|
-- Functions to set or get a STD_LOGIC field as a STD_LOGIC_VECTOR to or from an siso or an sosi array |
FUNCTION func_dp_stream_arr_set(dp : t_dp_siso_arr; slv : STD_LOGIC_VECTOR; str : STRING) RETURN t_dp_siso_arr IS |
VARIABLE v_dp : t_dp_siso_arr(dp'RANGE) := dp; -- default |
VARIABLE v_slv : STD_LOGIC_VECTOR(dp'RANGE) := slv; -- map to ensure same range as for dp |
BEGIN |
FOR I IN dp'RANGE LOOP |
IF str="READY" THEN v_dp(I).ready := v_slv(I); |
ELSIF str="XON" THEN v_dp(I).xon := v_slv(I); |
ELSE REPORT "Error in func_dp_stream_arr_set for t_dp_siso_arr"; |
END IF; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_set; |
|
FUNCTION func_dp_stream_arr_set(dp : t_dp_sosi_arr; slv : STD_LOGIC_VECTOR; str : STRING) RETURN t_dp_sosi_arr IS |
VARIABLE v_dp : t_dp_sosi_arr(dp'RANGE) := dp; -- default |
VARIABLE v_slv : STD_LOGIC_VECTOR(dp'RANGE) := slv; -- map to ensure same range as for dp |
BEGIN |
FOR I IN dp'RANGE LOOP |
IF str="VALID" THEN v_dp(I).valid := v_slv(I); |
ELSIF str="SOP" THEN v_dp(I).sop := v_slv(I); |
ELSIF str="EOP" THEN v_dp(I).eop := v_slv(I); |
ELSIF str="SYNC" THEN v_dp(I).sync := v_slv(I); |
ELSE REPORT "Error in func_dp_stream_arr_set for t_dp_sosi_arr"; |
END IF; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_set; |
|
FUNCTION func_dp_stream_arr_set(dp : t_dp_siso_arr; sl : STD_LOGIC; str : STRING) RETURN t_dp_siso_arr IS |
VARIABLE v_slv : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>sl); |
BEGIN |
RETURN func_dp_stream_arr_set(dp, v_slv, str); |
END func_dp_stream_arr_set; |
|
FUNCTION func_dp_stream_arr_set(dp : t_dp_sosi_arr; sl : STD_LOGIC; str : STRING) RETURN t_dp_sosi_arr IS |
VARIABLE v_slv : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>sl); |
BEGIN |
RETURN func_dp_stream_arr_set(dp, v_slv, str); |
END func_dp_stream_arr_set; |
|
FUNCTION func_dp_stream_arr_get(dp : t_dp_siso_arr; str : STRING) RETURN STD_LOGIC_VECTOR IS |
VARIABLE v_ctrl : STD_LOGIC_VECTOR(dp'RANGE); |
BEGIN |
FOR I IN dp'RANGE LOOP |
IF str="READY" THEN v_ctrl(I) := dp(I).ready; |
ELSIF str="XON" THEN v_ctrl(I) := dp(I).xon; |
ELSE REPORT "Error in func_dp_stream_arr_get for t_dp_siso_arr"; |
END IF; |
END LOOP; |
RETURN v_ctrl; |
END func_dp_stream_arr_get; |
|
FUNCTION func_dp_stream_arr_get(dp : t_dp_sosi_arr; str : STRING) RETURN STD_LOGIC_VECTOR IS |
VARIABLE v_ctrl : STD_LOGIC_VECTOR(dp'RANGE); |
BEGIN |
FOR I IN dp'RANGE LOOP |
IF str="VALID" THEN v_ctrl(I) := dp(I).valid; |
ELSIF str="SOP" THEN v_ctrl(I) := dp(I).sop; |
ELSIF str="EOP" THEN v_ctrl(I) := dp(I).eop; |
ELSIF str="SYNC" THEN v_ctrl(I) := dp(I).sync; |
ELSE REPORT "Error in func_dp_stream_arr_get for t_dp_sosi_arr"; |
END IF; |
END LOOP; |
RETURN v_ctrl; |
END func_dp_stream_arr_get; |
|
|
-- Functions to select elements from two siso or two sosi arrays (sel[] = '1' selects a, sel[] = '0' selects b) |
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a, b : t_dp_siso) RETURN t_dp_siso_arr IS |
VARIABLE v_dp : t_dp_siso_arr(sel'RANGE); |
BEGIN |
FOR I IN sel'RANGE LOOP |
IF sel(I)='1' THEN |
v_dp(I) := a; |
ELSE |
v_dp(I) := b; |
END IF; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_select; |
|
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a : t_dp_siso_arr; b : t_dp_siso) RETURN t_dp_siso_arr IS |
VARIABLE v_dp : t_dp_siso_arr(sel'RANGE); |
BEGIN |
FOR I IN sel'RANGE LOOP |
IF sel(I)='1' THEN |
v_dp(I) := a(I); |
ELSE |
v_dp(I) := b; |
END IF; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_select; |
|
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a : t_dp_siso; b : t_dp_siso_arr) RETURN t_dp_siso_arr IS |
VARIABLE v_dp : t_dp_siso_arr(sel'RANGE); |
BEGIN |
FOR I IN sel'RANGE LOOP |
IF sel(I)='1' THEN |
v_dp(I) := a; |
ELSE |
v_dp(I) := b(I); |
END IF; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_select; |
|
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a, b : t_dp_siso_arr) RETURN t_dp_siso_arr IS |
VARIABLE v_dp : t_dp_siso_arr(sel'RANGE); |
BEGIN |
FOR I IN sel'RANGE LOOP |
IF sel(I)='1' THEN |
v_dp(I) := a(I); |
ELSE |
v_dp(I) := b(I); |
END IF; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_select; |
|
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a, b : t_dp_sosi) RETURN t_dp_sosi_arr IS |
VARIABLE v_dp : t_dp_sosi_arr(sel'RANGE); |
BEGIN |
FOR I IN sel'RANGE LOOP |
IF sel(I)='1' THEN |
v_dp(I) := a; |
ELSE |
v_dp(I) := b; |
END IF; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_select; |
|
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a : t_dp_sosi_arr; b : t_dp_sosi) RETURN t_dp_sosi_arr IS |
VARIABLE v_dp : t_dp_sosi_arr(sel'RANGE); |
BEGIN |
FOR I IN sel'RANGE LOOP |
IF sel(I)='1' THEN |
v_dp(I) := a(I); |
ELSE |
v_dp(I) := b; |
END IF; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_select; |
|
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a : t_dp_sosi; b : t_dp_sosi_arr) RETURN t_dp_sosi_arr IS |
VARIABLE v_dp : t_dp_sosi_arr(sel'RANGE); |
BEGIN |
FOR I IN sel'RANGE LOOP |
IF sel(I)='1' THEN |
v_dp(I) := a; |
ELSE |
v_dp(I) := b(I); |
END IF; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_select; |
|
FUNCTION func_dp_stream_arr_select(sel : STD_LOGIC_VECTOR; a, b : t_dp_sosi_arr) RETURN t_dp_sosi_arr IS |
VARIABLE v_dp : t_dp_sosi_arr(sel'RANGE); |
BEGIN |
FOR I IN sel'RANGE LOOP |
IF sel(I)='1' THEN |
v_dp(I) := a(I); |
ELSE |
v_dp(I) := b(I); |
END IF; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_select; |
|
FUNCTION func_dp_stream_arr_reverse_range(in_arr : t_dp_siso_arr) RETURN t_dp_siso_arr IS |
VARIABLE v_to_range : t_dp_siso_arr(0 TO in_arr'HIGH); |
VARIABLE v_downto_range : t_dp_siso_arr(in_arr'HIGH DOWNTO 0); |
BEGIN |
FOR i IN in_arr'RANGE LOOP |
v_to_range(i) := in_arr(in_arr'HIGH-i); |
v_downto_range(i) := in_arr(in_arr'HIGH-i); |
END LOOP; |
IF in_arr'LEFT>in_arr'RIGHT THEN |
RETURN v_downto_range; |
ELSIF in_arr'LEFT<in_arr'RIGHT THEN |
RETURN v_to_range; |
ELSE |
RETURN in_arr; |
END IF; |
END func_dp_stream_arr_reverse_range; |
|
FUNCTION func_dp_stream_arr_reverse_range(in_arr : t_dp_sosi_arr) RETURN t_dp_sosi_arr IS |
VARIABLE v_to_range : t_dp_sosi_arr(0 TO in_arr'HIGH); |
VARIABLE v_downto_range : t_dp_sosi_arr(in_arr'HIGH DOWNTO 0); |
BEGIN |
FOR i IN in_arr'RANGE LOOP |
v_to_range(i) := in_arr(in_arr'HIGH-i); |
v_downto_range(i) := in_arr(in_arr'HIGH-i); |
END LOOP; |
IF in_arr'LEFT>in_arr'RIGHT THEN |
RETURN v_downto_range; |
ELSIF in_arr'LEFT<in_arr'RIGHT THEN |
RETURN v_to_range; |
ELSE |
RETURN in_arr; |
END IF; |
END func_dp_stream_arr_reverse_range; |
|
-- Functions to combinatorially hold the data fields and to set or reset the info and control fields in an sosi array |
FUNCTION func_dp_stream_arr_combine_data_info_ctrl(dp : t_dp_sosi_arr; info, ctrl : t_dp_sosi) RETURN t_dp_sosi_arr IS |
VARIABLE v_dp : t_dp_sosi_arr(dp'RANGE) := dp; -- hold sosi data |
BEGIN |
v_dp := func_dp_stream_arr_set_info( v_dp, info); -- set sosi info |
v_dp := func_dp_stream_arr_set_control(v_dp, ctrl); -- set sosi ctrl |
RETURN v_dp; |
END func_dp_stream_arr_combine_data_info_ctrl; |
|
FUNCTION func_dp_stream_arr_set_info(dp : t_dp_sosi_arr; info : t_dp_sosi) RETURN t_dp_sosi_arr IS |
VARIABLE v_dp : t_dp_sosi_arr(dp'RANGE) := dp; -- hold sosi data |
BEGIN |
FOR I IN dp'RANGE LOOP -- set sosi info |
v_dp(I).bsn := info.bsn; -- sop |
v_dp(I).channel := info.channel; -- sop |
v_dp(I).empty := info.empty; -- eop |
v_dp(I).err := info.err; -- eop |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_set_info; |
|
FUNCTION func_dp_stream_arr_set_control(dp : t_dp_sosi_arr; ctrl : t_dp_sosi) RETURN t_dp_sosi_arr IS |
VARIABLE v_dp : t_dp_sosi_arr(dp'RANGE) := dp; -- hold sosi data |
BEGIN |
FOR I IN dp'RANGE LOOP -- set sosi control |
v_dp(I).valid := ctrl.valid; |
v_dp(I).sop := ctrl.sop; |
v_dp(I).eop := ctrl.eop; |
v_dp(I).sync := ctrl.sync; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_set_control; |
|
FUNCTION func_dp_stream_arr_reset_control(dp : t_dp_sosi_arr) RETURN t_dp_sosi_arr IS |
VARIABLE v_dp : t_dp_sosi_arr(dp'RANGE) := dp; -- hold sosi data |
BEGIN |
FOR I IN dp'RANGE LOOP -- reset sosi control |
v_dp(I).valid := '0'; |
v_dp(I).sop := '0'; |
v_dp(I).eop := '0'; |
v_dp(I).sync := '0'; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_reset_control; |
|
FUNCTION func_dp_stream_reset_control(dp : t_dp_sosi) RETURN t_dp_sosi IS |
VARIABLE v_dp : t_dp_sosi := dp; -- hold sosi data |
BEGIN |
-- reset sosi control |
v_dp.valid := '0'; |
v_dp.sop := '0'; |
v_dp.eop := '0'; |
v_dp.sync := '0'; |
RETURN v_dp; |
END func_dp_stream_reset_control; |
|
-- Functions to combinatorially determine the maximum and minimum sosi bsn[w-1:0] value in the sosi array (for all elements or only for the mask[]='1' elements) |
FUNCTION func_dp_stream_arr_bsn_max(dp : t_dp_sosi_arr; mask : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR IS |
VARIABLE v_bsn : STD_LOGIC_VECTOR(w-1 DOWNTO 0) := (OTHERS=>'0'); -- init max v_bsn with minimum value |
BEGIN |
FOR I IN dp'RANGE LOOP |
IF mask(I)='1' THEN |
IF UNSIGNED(v_bsn) < UNSIGNED(dp(I).bsn(w-1 DOWNTO 0)) THEN |
v_bsn := dp(I).bsn(w-1 DOWNTO 0); |
END IF; |
END IF; |
END LOOP; |
RETURN v_bsn; |
END func_dp_stream_arr_bsn_max; |
|
FUNCTION func_dp_stream_arr_bsn_max(dp : t_dp_sosi_arr; w : NATURAL) RETURN STD_LOGIC_VECTOR IS |
CONSTANT c_mask : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>'1'); |
BEGIN |
RETURN func_dp_stream_arr_bsn_max(dp, c_mask, w); |
END func_dp_stream_arr_bsn_max; |
|
FUNCTION func_dp_stream_arr_bsn_min(dp : t_dp_sosi_arr; mask : STD_LOGIC_VECTOR; w : NATURAL) RETURN STD_LOGIC_VECTOR IS |
VARIABLE v_bsn : STD_LOGIC_VECTOR(w-1 DOWNTO 0) := (OTHERS=>'1'); -- init min v_bsn with maximum value |
BEGIN |
FOR I IN dp'RANGE LOOP |
IF mask(I)='1' THEN |
IF UNSIGNED(v_bsn) > UNSIGNED(dp(I).bsn(w-1 DOWNTO 0)) THEN |
v_bsn := dp(I).bsn(w-1 DOWNTO 0); |
END IF; |
END IF; |
END LOOP; |
RETURN v_bsn; |
END func_dp_stream_arr_bsn_min; |
|
FUNCTION func_dp_stream_arr_bsn_min(dp : t_dp_sosi_arr; w : NATURAL) RETURN STD_LOGIC_VECTOR IS |
CONSTANT c_mask : STD_LOGIC_VECTOR(dp'RANGE) := (OTHERS=>'1'); |
BEGIN |
RETURN func_dp_stream_arr_bsn_min(dp, c_mask, w); |
END func_dp_stream_arr_bsn_min; |
|
-- Function to copy the BSN number of one valid stream to all other streams. |
FUNCTION func_dp_stream_arr_copy_valid_bsn(dp : t_dp_sosi_arr; mask : STD_LOGIC_VECTOR) RETURN t_dp_sosi_arr IS |
VARIABLE v_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := (OTHERS=>'0'); |
VARIABLE v_dp : t_dp_sosi_arr(dp'RANGE) := dp; -- hold sosi data |
BEGIN |
FOR I IN dp'RANGE LOOP |
IF mask(I)='1' THEN |
v_bsn := dp(I).bsn; |
END IF; |
END LOOP; |
FOR I IN dp'RANGE LOOP |
v_dp(I).bsn := v_bsn; |
END LOOP; |
RETURN v_dp; |
END func_dp_stream_arr_copy_valid_bsn; |
|
|
-- Functions to combinatorially handle channels |
FUNCTION func_dp_stream_channel_set(st_sosi : t_dp_sosi; ch : NATURAL) RETURN t_dp_sosi IS |
VARIABLE v_rec : t_dp_sosi := st_sosi; |
BEGIN |
v_rec.channel := TO_UVEC(ch, c_dp_stream_channel_w); |
RETURN v_rec; |
END func_dp_stream_channel_set; |
|
FUNCTION func_dp_stream_channel_select(st_sosi : t_dp_sosi; ch : NATURAL) RETURN t_dp_sosi IS |
VARIABLE v_rec : t_dp_sosi := st_sosi; |
BEGIN |
IF UNSIGNED(st_sosi.channel)/=ch THEN |
v_rec.valid := '0'; |
v_rec.sop := '0'; |
v_rec.eop := '0'; |
END IF; |
RETURN v_rec; |
END func_dp_stream_channel_select; |
|
FUNCTION func_dp_stream_channel_remove(st_sosi : t_dp_sosi; ch : NATURAL) RETURN t_dp_sosi IS |
VARIABLE v_rec : t_dp_sosi := st_sosi; |
BEGIN |
IF UNSIGNED(st_sosi.channel)=ch THEN |
v_rec.valid := '0'; |
v_rec.sop := '0'; |
v_rec.eop := '0'; |
END IF; |
RETURN v_rec; |
END func_dp_stream_channel_remove; |
|
|
FUNCTION func_dp_stream_error_set(st_sosi : t_dp_sosi; n : NATURAL) RETURN t_dp_sosi IS |
VARIABLE v_rec : t_dp_sosi := st_sosi; |
BEGIN |
v_rec.err := TO_UVEC(n, c_dp_stream_error_w); |
RETURN v_rec; |
END func_dp_stream_error_set; |
|
|
FUNCTION func_dp_stream_bsn_set(st_sosi : t_dp_sosi; bsn : STD_LOGIC_VECTOR) RETURN t_dp_sosi IS |
VARIABLE v_rec : t_dp_sosi := st_sosi; |
BEGIN |
v_rec.bsn := RESIZE_DP_BSN(bsn); |
RETURN v_rec; |
END func_dp_stream_bsn_set; |
|
|
FUNCTION func_dp_stream_combine_info_and_data(info, data : t_dp_sosi) RETURN t_dp_sosi IS |
VARIABLE v_rec : t_dp_sosi := data; -- Sosi data fields |
BEGIN |
-- Combine sosi data with the sosi info fields |
v_rec.sync := info.sync AND data.sop; -- force sync only active at data.sop |
v_rec.bsn := info.bsn; |
v_rec.channel := info.channel; |
v_rec.empty := info.empty; |
v_rec.err := info.err; |
RETURN v_rec; |
END func_dp_stream_combine_info_and_data; |
|
|
FUNCTION func_dp_stream_slv_to_integer(slv_sosi : t_dp_sosi; w : NATURAL) RETURN t_dp_sosi_integer IS |
VARIABLE v_rec : t_dp_sosi_integer; |
BEGIN |
v_rec.sync := slv_sosi.sync; |
v_rec.bsn := TO_UINT(slv_sosi.bsn(30 DOWNTO 0)); -- NATURAL'width = 31 bit |
v_rec.data := TO_SINT(slv_sosi.data(w-1 DOWNTO 0)); |
v_rec.re := TO_SINT(slv_sosi.re(w-1 DOWNTO 0)); |
v_rec.im := TO_SINT(slv_sosi.im(w-1 DOWNTO 0)); |
v_rec.valid := slv_sosi.valid; |
v_rec.sop := slv_sosi.sop; |
v_rec.eop := slv_sosi.eop; |
v_rec.empty := TO_UINT(slv_sosi.empty); |
v_rec.channel := TO_UINT(slv_sosi.channel); |
v_rec.err := TO_UINT(slv_sosi.err); |
RETURN v_rec; |
END func_dp_stream_slv_to_integer; |
|
FUNCTION func_dp_stream_set_data(dp : t_dp_sosi; slv : STD_LOGIC_VECTOR; str : STRING) RETURN t_dp_sosi IS |
VARIABLE v_dp : t_dp_sosi := dp; |
BEGIN |
IF str="DATA" THEN v_dp.data := RESIZE_DP_DATA(slv); |
ELSIF str="DSP" THEN v_dp.re := RESIZE_DP_DSP_DATA(slv); |
v_dp.im := RESIZE_DP_DSP_DATA(slv); |
ELSIF str="RE" THEN v_dp.re := RESIZE_DP_DSP_DATA(slv); |
ELSIF str="IM" THEN v_dp.im := RESIZE_DP_DSP_DATA(slv); |
ELSIF str="ALL" THEN v_dp.data := RESIZE_DP_DATA(slv); |
v_dp.re := RESIZE_DP_DSP_DATA(slv); |
v_dp.im := RESIZE_DP_DSP_DATA(slv); |
ELSE REPORT "Error in func_dp_stream_set_data for t_dp_sosi"; |
END IF; |
RETURN v_dp; |
END; |
|
FUNCTION func_dp_stream_set_data(dp : t_dp_sosi_arr; slv : STD_LOGIC_VECTOR; str : STRING) RETURN t_dp_sosi_arr IS |
VARIABLE v_dp : t_dp_sosi_arr(dp'RANGE) := dp; |
BEGIN |
FOR I IN dp'RANGE LOOP |
v_dp(I) := func_dp_stream_set_data(dp(I), slv, str); |
END LOOP; |
RETURN v_dp; |
END; |
|
FUNCTION func_dp_stream_set_data(dp : t_dp_sosi_arr; slv : STD_LOGIC_VECTOR; str : STRING; mask : STD_LOGIC_VECTOR) RETURN t_dp_sosi_arr IS |
VARIABLE v_dp : t_dp_sosi_arr(dp'RANGE) := dp; |
BEGIN |
FOR I IN dp'RANGE LOOP |
IF mask(I)='0' THEN |
v_dp(I) := func_dp_stream_set_data(dp(I), slv, str); |
END IF; |
END LOOP; |
RETURN v_dp; |
END; |
|
-- Concatenate the data (and complex fields) from a SOSI array into a single SOSI stream (assumes streams are in sync) |
FUNCTION func_dp_stream_concat(snk_in_arr : t_dp_sosi_arr; data_w : NATURAL) RETURN t_dp_sosi IS |
VARIABLE v_src_out : t_dp_sosi := snk_in_arr(0); |
VARIABLE v_compl_data_w : NATURAL := data_w/2; |
BEGIN |
FOR i IN snk_in_arr'RANGE LOOP |
v_src_out.data((i+1)* data_w-1 DOWNTO i* data_w) := snk_in_arr(i).data( data_w-1 DOWNTO 0); |
v_src_out.re( (i+1)*v_compl_data_w-1 DOWNTO i*v_compl_data_w) := snk_in_arr(i).re(v_compl_data_w-1 DOWNTO 0); |
v_src_out.im( (i+1)*v_compl_data_w-1 DOWNTO i*v_compl_data_w) := snk_in_arr(i).im(v_compl_data_w-1 DOWNTO 0); |
END LOOP; |
RETURN v_src_out; |
END; |
|
FUNCTION func_dp_stream_concat(src_in : t_dp_siso; nof_streams : NATURAL) RETURN t_dp_siso_arr IS -- Wire single SISO to SISO_ARR |
VARIABLE v_snk_out_arr : t_dp_siso_arr(nof_streams-1 DOWNTO 0); |
BEGIN |
FOR i IN v_snk_out_arr'RANGE LOOP |
v_snk_out_arr(i) := src_in; |
END LOOP; |
RETURN v_snk_out_arr; |
END; |
|
-- Deconcatenate data from SOSI into SOSI array |
FUNCTION func_dp_stream_deconcat(snk_in : t_dp_sosi; nof_streams, data_w : NATURAL) RETURN t_dp_sosi_arr IS |
VARIABLE v_src_out_arr : t_dp_sosi_arr(nof_streams-1 DOWNTO 0); |
VARIABLE v_compl_data_w : NATURAL := data_w/2; |
BEGIN |
FOR i IN v_src_out_arr'RANGE LOOP |
v_src_out_arr(i) := snk_in; |
v_src_out_arr(i).data := (OTHERS=>'0'); |
v_src_out_arr(i).re := (OTHERS=>'0'); |
v_src_out_arr(i).im := (OTHERS=>'0'); |
v_src_out_arr(i).data( data_w-1 DOWNTO 0) := snk_in.data((i+1)* data_w-1 DOWNTO i* data_w); |
v_src_out_arr(i).re( v_compl_data_w-1 DOWNTO 0) := snk_in.re ((i+1)*v_compl_data_w-1 DOWNTO i*v_compl_data_w); |
v_src_out_arr(i).im( v_compl_data_w-1 DOWNTO 0) := snk_in.im ((i+1)*v_compl_data_w-1 DOWNTO i*v_compl_data_w); |
END LOOP; |
RETURN v_src_out_arr; |
END; |
|
FUNCTION func_dp_stream_deconcat(src_out_arr : t_dp_siso_arr) RETURN t_dp_siso IS -- Wire SISO_ARR(0) to single SISO |
BEGIN |
RETURN src_out_arr(0); |
END; |
|
END dp_stream_pkg; |
|
/dp_stream_stimuli.vhd
0,0 → 1,185
------------------------------------------------------------------------------- |
-- |
-- Copyright (C) 2015 |
-- 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/>. |
-- |
------------------------------------------------------------------------------- |
|
-- Purpose: |
-- . The dp_stream_stimuli generates as stream of packets with counter data. |
-- Description: |
-- |
-- Remark: |
-- . The stimuli empty = 0 because the data in proc_dp_gen_block_data() is |
-- generated with one symbol per data (because symbol_w = data_w). |
-- |
-- Usage: |
-- . See tb_dp_example_no_dut for usage example |
-- |
|
LIBRARY IEEE, common_pkg_lib; |
USE IEEE.std_logic_1164.ALL; |
USE IEEE.numeric_std.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
USE common_pkg_lib.common_lfsr_sequences_pkg.ALL; |
USE common_pkg_lib.tb_common_pkg.ALL; |
USE work.dp_stream_pkg.ALL; |
USE work.tb_dp_pkg.ALL; |
|
|
ENTITY dp_stream_stimuli IS |
GENERIC ( |
g_instance_nr : NATURAL := 0; |
-- flow control |
g_random_w : NATURAL := 15; -- use different random width for stimuli and for verify to have different random sequences |
g_pulse_active : NATURAL := 1; |
g_pulse_period : NATURAL := 2; |
g_flow_control : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control |
-- initializations |
g_sync_period : NATURAL := 10; |
g_sync_offset : NATURAL := 0; |
g_data_init : NATURAL := 0; -- choose some easy to recognize and unique value, data will increment at every valid |
g_bsn_init : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := TO_DP_BSN(0); -- X"0877665544332211", bsn will increment at every sop |
g_err_init : NATURAL := 247; -- choose some easy to recognize and unique value |
g_err_incr : NATURAL := 1; -- when 0 keep fixed at init value, when 1 increment at every sop |
g_channel_init : NATURAL := 5; -- choose some easy to recognize and unique value |
g_channel_incr : NATURAL := 1; -- when 0 keep fixed at init value, when 1 increment at every sop |
-- specific |
g_in_dat_w : NATURAL := 32; |
g_nof_repeat : NATURAL := 5; |
g_pkt_len : NATURAL := 16; |
g_pkt_gap : NATURAL := 4 |
); |
PORT ( |
rst : IN STD_LOGIC; |
clk : IN STD_LOGIC; |
|
-- Generate stimuli |
src_in : IN t_dp_siso := c_dp_siso_rdy; |
src_out : OUT t_dp_sosi; |
|
-- End of stimuli |
last_snk_in : OUT t_dp_sosi; -- expected verify_snk_in after end of stimuli |
last_snk_in_evt : OUT STD_LOGIC; -- trigger verify to verify the last_snk_in |
tb_end : OUT STD_LOGIC -- signal end of tb as far as this dp_stream_stimuli is concerned |
); |
END dp_stream_stimuli; |
|
|
ARCHITECTURE str OF dp_stream_stimuli IS |
|
SIGNAL random : STD_LOGIC_VECTOR(g_random_w-1 DOWNTO 0) := TO_UVEC(g_instance_nr, g_random_w); -- use different initialization to have different random sequences per stream |
SIGNAL pulse : STD_LOGIC; |
SIGNAL pulse_en : STD_LOGIC := '1'; |
|
SIGNAL stimuli_en : STD_LOGIC := '1'; |
SIGNAL src_out_data : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
SIGNAL i_src_out : t_dp_sosi; |
|
BEGIN |
|
src_out <= i_src_out; |
|
------------------------------------------------------------------------------ |
-- STREAM CONTROL |
------------------------------------------------------------------------------ |
|
random <= func_common_random(random) WHEN rising_edge(clk); |
|
proc_common_gen_duty_pulse(g_pulse_active, g_pulse_period, '1', rst, clk, pulse_en, pulse); |
|
stimuli_en <= '1' WHEN g_flow_control=e_active ELSE |
random(random'HIGH) WHEN g_flow_control=e_random ELSE |
pulse WHEN g_flow_control=e_pulse; |
|
------------------------------------------------------------------------------ |
-- DATA GENERATION |
------------------------------------------------------------------------------ |
|
-- Generate data path input data |
p_stimuli_st : PROCESS |
VARIABLE v_sosi : t_dp_sosi := c_dp_sosi_rst; |
VARIABLE v_last : t_dp_sosi := c_dp_sosi_rst; |
BEGIN |
-- Initialisations |
last_snk_in <= c_dp_sosi_rst; |
last_snk_in_evt <= '0'; |
tb_end <= '0'; |
|
-- Adjust initial sosi field values by -1 to compensate for auto increment |
v_sosi.bsn := INCR_UVEC(g_bsn_init, -1); |
v_sosi.channel := INCR_UVEC(TO_DP_CHANNEL(g_channel_init), -g_channel_incr); |
v_sosi.data := INCR_UVEC(TO_DP_DATA(g_data_init), -g_pkt_len); |
v_sosi.err := INCR_UVEC(TO_DP_ERROR(g_err_init), -g_err_incr); |
|
i_src_out <= c_dp_sosi_rst; |
proc_common_wait_until_low(clk, rst); |
proc_common_wait_some_cycles(clk, 5); |
|
-- Generate g_nof_repeat packets |
FOR I IN 0 TO g_nof_repeat-1 LOOP |
-- Auto increment v_sosi field values for this packet |
v_sosi.bsn := INCR_UVEC(v_sosi.bsn, 1); |
v_sosi.sync := sel_a_b((UNSIGNED(v_sosi.bsn) MOD g_sync_period) = g_sync_offset, '1', '0'); -- insert sync starting at BSN=g_sync_offset and with period g_sync_period |
v_sosi.channel := INCR_UVEC(v_sosi.channel, g_channel_incr); |
v_sosi.data := INCR_UVEC(v_sosi.data, g_pkt_len); |
v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_in_dat_w-1 DOWNTO 0)); -- wrap when >= 2**g_in_dat_w |
v_sosi.err := INCR_UVEC(v_sosi.err, g_err_incr); |
|
-- Send packet |
proc_dp_gen_block_data(g_in_dat_w, TO_UINT(v_sosi.data), g_pkt_len, TO_UINT(v_sosi.channel), TO_UINT(v_sosi.err), v_sosi.sync, v_sosi.bsn, clk, stimuli_en, src_in, i_src_out); |
|
-- Insert optional gap between the packets |
proc_common_wait_some_cycles(clk, g_pkt_gap); |
|
-- Update v_last.sync |
IF v_sosi.sync='1' THEN v_last.sync := '1'; END IF; |
END LOOP; |
|
-- Update v_last control |
IF g_nof_repeat>0 THEN |
v_last.sop := '1'; |
v_last.eop := '1'; |
v_last.valid := '1'; |
END IF; |
|
-- Determine and keep last expected sosi field values after end of stimuli |
-- . e_qual |
v_last.bsn := STD_LOGIC_VECTOR( UNSIGNED(g_bsn_init) + g_nof_repeat-1); |
v_last.channel := TO_DP_CHANNEL(g_channel_init + (g_nof_repeat-1)*g_channel_incr); |
v_last.err := TO_DP_ERROR(g_err_init + (g_nof_repeat-1)*g_err_incr); |
-- . account for g_pkt_len |
v_last.data := INCR_UVEC(v_sosi.data, g_pkt_len-1); |
v_last.data := RESIZE_DP_DATA(v_last.data(g_in_dat_w-1 DOWNTO 0)); -- wrap when >= 2**g_in_dat_w |
last_snk_in <= v_last; |
|
-- Signal end of stimuli |
proc_common_wait_some_cycles(clk, 100); -- latency from stimuli to verify depends on the flow control, so wait sufficiently long for last packet to have passed through |
proc_common_gen_pulse(clk, last_snk_in_evt); |
proc_common_wait_some_cycles(clk, 50); |
tb_end <= '1'; |
WAIT; |
END PROCESS; |
|
------------------------------------------------------------------------------ |
-- Auxiliary |
------------------------------------------------------------------------------ |
|
-- Map to slv to ease monitoring in wave window |
src_out_data <= i_src_out.data(g_in_dat_w-1 DOWNTO 0); |
|
END str; |
/dp_stream_verify.vhd
0,0 → 1,200
------------------------------------------------------------------------------- |
-- |
-- Copyright (C) 2015 |
-- 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/>. |
-- |
------------------------------------------------------------------------------- |
|
-- Purpose: |
-- . The dp_stream_verify verifies the stream of packets with counter data that |
-- are generated by dp_stimuli_st. |
-- Description: |
-- The component can verify a stream: |
-- . The sosi control fields are verified conform the bus specifications |
-- eg. considering the RL, no missing eop, etc. |
-- . The sosi data fields are verified based on their previous value under |
-- the assumption that they contain incrementing data. Whether a field |
-- is checked depends on verify_snk_in_enable. |
-- |
-- The component also checks whether the stream is active at all. A |
-- pulse in verify_expected_snk_in_evt triggers the verification of the |
-- corresponding field in snk_in using the expected_snk_in as reference. |
-- |
-- Usage: |
-- . See tb_dp_example_no_dut for usage example |
-- |
|
LIBRARY IEEE, common_pkg_lib; |
USE IEEE.std_logic_1164.ALL; |
USE IEEE.numeric_std.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
USE common_pkg_lib.common_lfsr_sequences_pkg.ALL; |
USE common_pkg_lib.tb_common_pkg.ALL; |
USE work.dp_stream_pkg.ALL; |
USE work.tb_dp_pkg.ALL; |
|
|
ENTITY dp_stream_verify IS |
GENERIC ( |
g_instance_nr : NATURAL := 0; |
-- flow control |
g_random_w : NATURAL := 14; -- use different random width for stimuli and for verify to have different random sequences |
g_pulse_active : NATURAL := 1; |
g_pulse_period : NATURAL := 2; |
g_flow_control : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control |
-- initializations |
g_sync_period : NATURAL := 10; |
g_sync_offset : NATURAL := 7; |
g_snk_in_cnt_max : t_dp_sosi_unsigned := c_dp_sosi_unsigned_rst; -- default 0 is no wrap |
g_snk_in_cnt_gap : t_dp_sosi_unsigned := c_dp_sosi_unsigned_ones; -- default only accept increment +1 |
-- specific |
g_in_dat_w : NATURAL := 32; |
g_pkt_len : NATURAL := 16 |
); |
PORT ( |
rst : IN STD_LOGIC; |
clk : IN STD_LOGIC; |
|
-- Verify data |
snk_out : OUT t_dp_siso; |
snk_in : IN t_dp_sosi; |
|
-- During stimuli |
verify_snk_in_enable : IN t_dp_sosi_sl; -- enable to verify that the snk_in fields are incrementing |
|
-- End of stimuli |
expected_snk_in : IN t_dp_sosi; -- expected snk_in at verify_expected_snk_in_evt |
verify_expected_snk_in_evt : IN t_dp_sosi_sl -- trigger to verify the expected_snk_in |
); |
END dp_stream_verify; |
|
|
ARCHITECTURE tb OF dp_stream_verify IS |
|
CONSTANT c_rl : NATURAL := 1; |
CONSTANT c_no_dut : BOOLEAN:= TRUE; |
|
SIGNAL random : STD_LOGIC_VECTOR(g_random_w-1 DOWNTO 0) := TO_UVEC(g_instance_nr, g_random_w); -- use different initialization to have different random sequences per stream |
SIGNAL pulse : STD_LOGIC; |
SIGNAL pulse_en : STD_LOGIC := '1'; |
|
SIGNAL i_snk_out : t_dp_siso := c_dp_siso_rdy; |
SIGNAL prev_snk_out : t_dp_siso; |
SIGNAL hold_snk_in_data : STD_LOGIC_VECTOR(c_dp_stream_data_w-1 DOWNTO 0); -- used to hold valid data for verify at verify_expected_snk_in_evt |
SIGNAL snk_in_data : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
SIGNAL prev_snk_in : t_dp_sosi; |
|
SIGNAL hold_snk_in_sop : STD_LOGIC := '0'; |
SIGNAL detected_snk_in_ctrl : t_dp_sosi_sl := c_dp_sosi_sl_rst; |
SIGNAL verify_snk_in_increment : t_dp_sosi_sl := c_dp_sosi_sl_rst; |
SIGNAL verify_snk_in_ctrl : t_dp_sosi_sl := c_dp_sosi_sl_rst; |
|
SIGNAL exp_size : NATURAL; |
SIGNAL cnt_size : NATURAL; |
|
BEGIN |
|
snk_out <= i_snk_out; |
|
------------------------------------------------------------------------------ |
-- STREAM CONTROL |
------------------------------------------------------------------------------ |
|
random <= func_common_random(random) WHEN rising_edge(clk); |
|
proc_common_gen_duty_pulse(g_pulse_active, g_pulse_period, '1', rst, clk, pulse_en, pulse); |
|
i_snk_out.ready <= '1' WHEN g_flow_control=e_active ELSE |
random(random'HIGH) WHEN g_flow_control=e_random ELSE |
pulse WHEN g_flow_control=e_pulse; |
|
------------------------------------------------------------------------------ |
-- DATA VERIFICATION |
------------------------------------------------------------------------------ |
|
-- Detect first sync, sop, eop, valid |
detected_snk_in_ctrl.sync <= '1' WHEN snk_in.sync='1' AND rising_edge(clk); |
detected_snk_in_ctrl.valid <= '1' WHEN snk_in.valid='1' AND rising_edge(clk); |
detected_snk_in_ctrl.sop <= '1' WHEN snk_in.sop='1' AND rising_edge(clk); |
detected_snk_in_ctrl.eop <= '1' WHEN snk_in.eop='1' AND rising_edge(clk); |
|
-- Verify that the stimuli have been applied at all so at least one active sosi sync, sop, eop, valid field has been detected |
proc_dp_verify_value("snk_in.sync", clk, verify_expected_snk_in_evt.sync, expected_snk_in.sync, detected_snk_in_ctrl.sync); |
proc_dp_verify_value("snk_in.sop", clk, verify_expected_snk_in_evt.sop, expected_snk_in.sop, detected_snk_in_ctrl.sop); |
proc_dp_verify_value("snk_in.eop", clk, verify_expected_snk_in_evt.eop, expected_snk_in.eop, detected_snk_in_ctrl.eop); |
proc_dp_verify_value("snk_in.valid", clk, verify_expected_snk_in_evt.valid, expected_snk_in.valid, detected_snk_in_ctrl.valid); |
|
-- Verify that the last sosi data, bsn, channel and err fields are correct |
proc_dp_verify_value("snk_in.data", e_equal, clk, verify_expected_snk_in_evt.data, expected_snk_in.data, hold_snk_in_data); |
proc_dp_verify_value("snk_in.bsn", e_equal, clk, verify_expected_snk_in_evt.bsn, expected_snk_in.bsn, snk_in.bsn); |
proc_dp_verify_value("snk_in.channel", e_equal, clk, verify_expected_snk_in_evt.channel, expected_snk_in.channel, snk_in.channel); |
proc_dp_verify_value("snk_in.err", e_equal, clk, verify_expected_snk_in_evt.err, expected_snk_in.err, snk_in.err); |
|
-- Verify that the output is incrementing data, like the input stimuli |
p_verify_snk_in_increment : PROCESS(verify_snk_in_enable, detected_snk_in_ctrl) |
BEGIN |
verify_snk_in_increment <= verify_snk_in_enable; |
verify_snk_in_increment.data <= verify_snk_in_enable.data AND detected_snk_in_ctrl.valid; |
verify_snk_in_increment.re <= verify_snk_in_enable.re AND detected_snk_in_ctrl.valid; |
verify_snk_in_increment.im <= verify_snk_in_enable.im AND detected_snk_in_ctrl.valid; |
verify_snk_in_increment.bsn <= verify_snk_in_enable.bsn AND detected_snk_in_ctrl.sop; |
verify_snk_in_increment.channel <= verify_snk_in_enable.channel AND detected_snk_in_ctrl.sop; |
verify_snk_in_increment.empty <= verify_snk_in_enable.empty AND detected_snk_in_ctrl.eop; |
verify_snk_in_increment.err <= verify_snk_in_enable.err AND detected_snk_in_ctrl.eop; |
END PROCESS; |
|
proc_dp_verify_data("snk_in.data", c_rl, g_snk_in_cnt_max.data, g_snk_in_cnt_gap.data, clk, verify_snk_in_increment.data, i_snk_out.ready, snk_in.valid, snk_in.data, prev_snk_in.data); |
proc_dp_verify_data("snk_in.re", c_rl, g_snk_in_cnt_max.re, g_snk_in_cnt_gap.re, clk, verify_snk_in_increment.re, i_snk_out.ready, snk_in.valid, snk_in.re, prev_snk_in.re); |
proc_dp_verify_data("snk_in.im", c_rl, g_snk_in_cnt_max.im, g_snk_in_cnt_gap.im, clk, verify_snk_in_increment.im, i_snk_out.ready, snk_in.valid, snk_in.im, prev_snk_in.im); |
proc_dp_verify_data("snk_in.bsn", c_rl, g_snk_in_cnt_max.bsn, g_snk_in_cnt_gap.bsn, clk, verify_snk_in_increment.bsn, i_snk_out.ready, snk_in.sop, snk_in.bsn, prev_snk_in.bsn); |
proc_dp_verify_data("snk_in.channel", c_rl, g_snk_in_cnt_max.channel, g_snk_in_cnt_gap.channel, clk, verify_snk_in_increment.channel, i_snk_out.ready, snk_in.sop, snk_in.channel, prev_snk_in.channel); |
proc_dp_verify_data("snk_in.empty", c_rl, g_snk_in_cnt_max.empty, g_snk_in_cnt_gap.empty, clk, verify_snk_in_increment.empty, i_snk_out.ready, snk_in.eop, snk_in.empty, prev_snk_in.empty); |
proc_dp_verify_data("snk_in.err", c_rl, g_snk_in_cnt_max.err, g_snk_in_cnt_gap.err, clk, verify_snk_in_increment.err, i_snk_out.ready, snk_in.eop, snk_in.err, prev_snk_in.err); |
|
-- Verify that the snk_in control fields are correct |
p_verify_snk_in_ctrl: PROCESS(snk_in, verify_snk_in_enable) |
BEGIN |
verify_snk_in_ctrl.sync <= snk_in.sync AND verify_snk_in_enable.valid AND verify_snk_in_enable.sync; |
verify_snk_in_ctrl.sop <= snk_in.sop AND verify_snk_in_enable.valid AND verify_snk_in_enable.sop AND verify_snk_in_enable.eop; |
verify_snk_in_ctrl.eop <= snk_in.eop AND verify_snk_in_enable.valid AND verify_snk_in_enable.sop AND verify_snk_in_enable.eop; |
verify_snk_in_ctrl.valid <= snk_in.valid AND verify_snk_in_enable.valid; |
END PROCESS; |
|
-- Verify that the output sync occurs when expected |
proc_dp_verify_sync(g_sync_period, g_sync_offset, clk, detected_snk_in_ctrl.sop, verify_snk_in_ctrl.sync, verify_snk_in_ctrl.sop, snk_in.bsn); |
|
-- Verify output packet ctrl |
proc_dp_verify_sop_and_eop(clk, verify_snk_in_ctrl.valid, verify_snk_in_ctrl.sop, verify_snk_in_ctrl.eop, hold_snk_in_sop); |
|
-- Verify output packet block size |
exp_size <= g_pkt_len; |
|
proc_dp_verify_block_size(exp_size, clk, verify_snk_in_ctrl.valid, verify_snk_in_ctrl.sop, verify_snk_in_ctrl.eop, cnt_size); |
|
-- Verify output ready latency |
proc_dp_verify_valid(clk, detected_snk_in_ctrl.valid, i_snk_out.ready, prev_snk_out.ready, verify_snk_in_ctrl.valid); |
|
------------------------------------------------------------------------------ |
-- Auxiliary |
------------------------------------------------------------------------------ |
|
-- Map to slv to ease monitoring in wave window |
snk_in_data <= snk_in.data(g_in_dat_w-1 DOWNTO 0); |
|
hold_snk_in_data <= snk_in.data WHEN snk_in.valid='1'; |
|
END tb; |
/hdllib.cfg
0,0 → 1,20
hdl_lib_name = dp_pkg |
hdl_library_clause_name = dp_pkg_lib |
hdl_lib_uses_synth = common_pkg |
hdl_lib_uses_sim = |
hdl_lib_technology = |
|
synth_files = |
dp_stream_pkg.vhd |
tb_dp_pkg.vhd |
dp_stream_stimuli.vhd |
dp_stream_verify.vhd |
|
test_bench_files = |
|
regression_test_vhdl = |
|
[modelsim_project_file] |
|
|
[quartus_project_file] |
/tb_dp_pkg.vhd
0,0 → 1,2413
------------------------------------------------------------------------------- |
-- |
-- Copyright (C) 2010 |
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> |
-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.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/>. |
-- |
------------------------------------------------------------------------------- |
|
LIBRARY IEEE, common_pkg_lib; |
USE IEEE.std_logic_1164.ALL; |
USE IEEE.numeric_std.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
USE common_pkg_lib.common_lfsr_sequences_pkg.ALL; |
USE common_pkg_lib.tb_common_pkg.ALL; |
USE work.dp_stream_pkg.ALL; |
|
|
PACKAGE tb_dp_pkg IS |
|
------------------------------------------------------------------------------ |
-- Purpose: |
-- |
-- Test bench package for applying stimuli to a streaming data path. The |
-- input is counter data, the output is verified and an error is reported |
-- if a counter value is missing or duplicate. |
-- |
-- Description: |
-- |
-- The test is divided into intervals marked by sync to start a new subtest |
-- named by state. New subtests can be added by adding an extra sync interval |
-- and state name to this package. In each subtest the streaming interface |
-- DUT can be verified for different situations by manipulating: |
-- . cnt_en : cnt_en not always active when in_ready is asserted |
-- . out_ready : out_ready not always active |
-- |
-- Remarks: |
-- . See e.g. tb_dp_pipeline.vhd for how to use the procedures. |
-- . To run all stimuli in Modelsim do: |
-- > as 10 |
-- > run 400 us |
------------------------------------------------------------------------------ |
|
CONSTANT clk_period : TIME := 10 ns; -- 100 MHz |
CONSTANT c_dp_sync_interval : NATURAL := 3000; |
CONSTANT c_dp_test_interval : NATURAL := 100; |
CONSTANT c_dp_nof_toggle : NATURAL := 40; |
CONSTANT c_dp_nof_both : NATURAL := 50; |
|
-- The test bench uses other field widths than the standard t_dp_sosi record field widths, the assumptions are: |
-- . c_dp_data_w < c_dp_stream_data_w |
-- . c_dp_data_w > c_dp_stream_empty_w |
-- . c_dp_data_w > c_dp_stream_channel_w |
-- . c_dp_data_w > c_dp_stream_error_w |
CONSTANT c_dp_data_w : NATURAL := c_word_w; -- =32, choose wide enough to avoid out_data wrap around issue for p_verify |
CONSTANT c_dp_bsn_w : NATURAL := c_dp_data_w; -- c_dp_stream_bsn_w; |
CONSTANT c_dp_empty_w : NATURAL := c_dp_stream_empty_w; |
CONSTANT c_dp_channel_w : NATURAL := c_dp_stream_channel_w; |
CONSTANT c_dp_channel_user_w : NATURAL := c_dp_stream_channel_w/2; -- support some bits for mux input user streams channel widths |
CONSTANT c_dp_channel_mux_w : NATURAL :=(c_dp_stream_channel_w+1)/2; -- support rest bits for the nof input ports of a mux |
CONSTANT c_dp_error_w : NATURAL := c_dp_stream_error_w; |
|
TYPE t_dp_data_arr IS ARRAY (NATURAL RANGE <>) OF STD_LOGIC_VECTOR(c_dp_data_w-1 DOWNTO 0); |
|
-- The state name tells what kind of test is done in the sync interval |
TYPE t_dp_state_enum IS ( |
s_idle, |
s_both_active, |
s_pull_down_out_ready, |
s_pull_down_cnt_en, |
s_toggle_out_ready, |
s_toggle_cnt_en, |
s_toggle_both, |
s_pulse_cnt_en, |
s_chirp_out_ready, |
s_random, |
s_done |
); |
|
TYPE t_dp_value_enum IS ( |
e_equal, |
e_at_least |
); |
|
-- always active, random or pulse flow control |
TYPE t_dp_flow_control_enum IS ( |
e_active, |
e_random, |
e_pulse |
); |
|
TYPE t_dp_flow_control_enum_arr IS ARRAY (NATURAL RANGE <>) OF t_dp_flow_control_enum; |
|
CONSTANT c_dp_flow_control_enum_arr : t_dp_flow_control_enum_arr := (e_active, e_random, e_pulse); -- array all possible values that can be iterated over |
|
------------------------------------------------------------------------------ |
-- Stream source functions |
------------------------------------------------------------------------------ |
|
-- Block data generator with feedforward throttle control |
-- !!! old style: sync before sop |
-- !!! used by tb_dp_packetizing, do not use for new DP components |
PROCEDURE proc_dp_gen_block_data(CONSTANT c_nof_block_per_sync : IN NATURAL; |
CONSTANT c_block_size : IN NATURAL; |
CONSTANT c_gap_size : IN NATURAL; |
CONSTANT c_throttle_num : IN NATURAL; |
CONSTANT c_throttle_den : IN NATURAL; |
SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sync_nr : INOUT NATURAL; |
SIGNAL block_nr : INOUT NATURAL; |
SIGNAL cnt_sync : OUT STD_LOGIC; |
SIGNAL cnt_val : OUT STD_LOGIC; |
SIGNAL cnt_dat : INOUT STD_LOGIC_VECTOR); |
|
-- Block data generator with ready flow control and symbols counter |
PROCEDURE proc_dp_gen_block_data(CONSTANT c_ready_latency : IN NATURAL; -- 0, 1 are supported by proc_dp_stream_ready_latency() |
CONSTANT c_use_data : IN BOOLEAN; -- when TRUE use data field, else use re, im fields, and keep unused fields at 'X' |
CONSTANT c_data_w : IN NATURAL; -- data width for the data, re and im fields |
CONSTANT c_symbol_w : IN NATURAL; -- c_data_w/c_symbol_w must be an integer |
CONSTANT c_symbol_init : IN NATURAL; -- init counter for symbols in data field |
CONSTANT c_symbol_re_init : IN NATURAL; -- init counter for symbols in re field |
CONSTANT c_symbol_im_init : IN NATURAL; -- init counter for symbols in im field |
CONSTANT c_nof_symbols : IN NATURAL; -- nof symbols per frame for the data, re and im fields |
CONSTANT c_channel : IN NATURAL; -- channel field |
CONSTANT c_error : IN NATURAL; -- error field |
CONSTANT c_sync : IN STD_LOGIC; -- when '1' issue sync pulse during this block |
CONSTANT c_bsn : IN STD_LOGIC_VECTOR; -- bsn field |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; -- when '0' then no valid output even when src_in is ready |
SIGNAL src_in : IN t_dp_siso; |
SIGNAL src_out : OUT t_dp_sosi); |
|
PROCEDURE proc_dp_gen_block_data(CONSTANT c_data_w : IN NATURAL; -- data width for the data field |
CONSTANT c_symbol_init : IN NATURAL; -- init counter for the data in the data field |
CONSTANT c_nof_symbols : IN NATURAL; -- nof symbols per frame for the data fields |
CONSTANT c_channel : IN NATURAL; -- channel field |
CONSTANT c_error : IN NATURAL; -- error field |
CONSTANT c_sync : IN STD_LOGIC; -- when '1' issue sync pulse during this block |
CONSTANT c_bsn : IN STD_LOGIC_VECTOR; -- bsn field |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; -- when '0' then no valid output even when src_in is ready |
SIGNAL src_in : IN t_dp_siso; |
SIGNAL src_out : OUT t_dp_sosi); |
|
-- Handle stream ready signal, only support RL=0 or 1. |
PROCEDURE proc_dp_stream_ready_latency(CONSTANT c_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL ready : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; -- when '1' then active output when ready |
CONSTANT c_sync : IN STD_LOGIC; |
CONSTANT c_valid : IN STD_LOGIC; |
CONSTANT c_sop : IN STD_LOGIC; |
CONSTANT c_eop : IN STD_LOGIC; |
SIGNAL out_sync : OUT STD_LOGIC; |
SIGNAL out_valid : OUT STD_LOGIC; |
SIGNAL out_sop : OUT STD_LOGIC; |
SIGNAL out_eop : OUT STD_LOGIC); |
|
-- Initialize the data per symbol |
FUNCTION func_dp_data_init(c_data_w, c_symbol_w, init : NATURAL) RETURN STD_LOGIC_VECTOR; |
|
-- Increment the data per symbol |
FUNCTION func_dp_data_incr(c_data_w, c_symbol_w : NATURAL; data : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; |
|
-- Generate a counter data with valid |
PROCEDURE proc_dp_gen_data(CONSTANT c_ready_latency : IN NATURAL; -- 0, 1 are supported by proc_dp_stream_ready_latency() |
CONSTANT c_data_w : IN NATURAL; |
CONSTANT c_data_init : IN NATURAL; |
SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; -- when '0' then no valid output even when src_in is ready |
SIGNAL src_in : IN t_dp_siso; |
SIGNAL src_out : OUT t_dp_sosi); |
|
-- As above but with counter max |
PROCEDURE proc_dp_gen_data(CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_data_w : IN NATURAL; |
CONSTANT c_data_init : IN NATURAL; |
CONSTANT c_data_max : IN NATURAL; |
SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; |
SIGNAL src_in : IN t_dp_siso; |
SIGNAL src_out : OUT t_dp_sosi); |
|
-- Generate a frame with symbols counter |
PROCEDURE proc_dp_gen_frame(CONSTANT c_ready_latency : IN NATURAL; -- 0, 1 are supported by proc_dp_stream_ready_latency() |
CONSTANT c_data_w : IN NATURAL; |
CONSTANT c_symbol_w : IN NATURAL; -- c_data_w/c_symbol_w must be an integer |
CONSTANT c_symbol_init : IN NATURAL; |
CONSTANT c_nof_symbols : IN NATURAL; |
CONSTANT c_bsn : IN NATURAL; |
CONSTANT c_sync : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; -- when '0' then no valid output even when src_in is ready |
SIGNAL src_in : IN t_dp_siso; |
SIGNAL src_out : OUT t_dp_sosi); |
|
-- Input data counter |
PROCEDURE proc_dp_cnt_dat(SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; |
SIGNAL cnt_dat : INOUT STD_LOGIC_VECTOR); |
|
PROCEDURE proc_dp_cnt_dat(SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; |
SIGNAL cnt_val : INOUT STD_LOGIC; |
SIGNAL cnt_dat : INOUT STD_LOGIC_VECTOR); |
|
-- Transmit data |
PROCEDURE proc_dp_tx_data(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL cnt_val : IN STD_LOGIC; |
SIGNAL cnt_dat : IN STD_LOGIC_VECTOR; |
SIGNAL tx_data : INOUT t_dp_data_arr; |
SIGNAL tx_val : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_data : OUT STD_LOGIC_VECTOR; |
SIGNAL out_val : OUT STD_LOGIC); |
|
-- Transmit data control (use for sop, eop) |
PROCEDURE proc_dp_tx_ctrl(CONSTANT c_offset : IN NATURAL; |
CONSTANT c_period : IN NATURAL; |
SIGNAL data : IN STD_LOGIC_VECTOR; |
SIGNAL valid : IN STD_LOGIC; |
SIGNAL ctrl : OUT STD_LOGIC); |
|
-- Define sync interval |
PROCEDURE proc_dp_sync_interval(SIGNAL clk : IN STD_LOGIC; |
SIGNAL sync : OUT STD_LOGIC); |
|
-- Stimuli for cnt_en |
PROCEDURE proc_dp_count_en(SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sync : IN STD_LOGIC; |
SIGNAL lfsr : INOUT STD_LOGIC_VECTOR; |
SIGNAL state : OUT t_dp_state_enum; |
SIGNAL done : OUT STD_LOGIC; |
SIGNAL tb_end : OUT STD_LOGIC; |
SIGNAL cnt_en : OUT STD_LOGIC); |
|
------------------------------------------------------------------------------ |
-- Stream sink functions |
------------------------------------------------------------------------------ |
|
-- Stimuli for out_ready |
PROCEDURE proc_dp_out_ready(SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sync : IN STD_LOGIC; |
SIGNAL lfsr : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_ready : OUT STD_LOGIC); |
|
-- DUT output verify enable |
PROCEDURE proc_dp_verify_en(CONSTANT c_delay : IN NATURAL; |
SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sync : IN STD_LOGIC; |
SIGNAL verify_en : OUT STD_LOGIC); |
|
PROCEDURE proc_dp_verify_en(CONSTANT c_continuous : IN BOOLEAN; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL valid : IN STD_LOGIC; |
SIGNAL sop : IN STD_LOGIC; |
SIGNAL eop : IN STD_LOGIC; |
SIGNAL verify_en : OUT STD_LOGIC); |
|
-- Run and verify for some cycles |
PROCEDURE proc_dp_verify_run_some_cycles(CONSTANT nof_pre_clk : IN NATURAL; |
CONSTANT nof_verify_clk : IN NATURAL; |
CONSTANT nof_post_clk : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : OUT STD_LOGIC); |
|
-- Verify the expected value |
PROCEDURE proc_dp_verify_value(CONSTANT c_str : IN STRING; |
CONSTANT mode : IN t_dp_value_enum; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL en : IN STD_LOGIC; |
SIGNAL exp : IN STD_LOGIC_VECTOR; |
SIGNAL res : IN STD_LOGIC_VECTOR); |
|
PROCEDURE proc_dp_verify_value(CONSTANT mode : IN t_dp_value_enum; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL en : IN STD_LOGIC; |
SIGNAL exp : IN STD_LOGIC_VECTOR; |
SIGNAL res : IN STD_LOGIC_VECTOR); |
|
PROCEDURE proc_dp_verify_value(CONSTANT c_str : IN STRING; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL en : IN STD_LOGIC; |
SIGNAL exp : IN STD_LOGIC; |
SIGNAL res : IN STD_LOGIC); |
|
-- Verify output global and local BSN |
-- . incrementing or replicated global BSN |
-- . incrementing local BSN that starts at 1 |
PROCEDURE proc_dp_verify_bsn(CONSTANT c_use_local_bsn : IN BOOLEAN; -- use local BSN or only use global BSN |
CONSTANT c_global_bsn_increment : IN POSITIVE; -- increment per global BSN |
CONSTANT c_nof_replicated_global_bsn : IN POSITIVE; -- number of replicated global BSN |
CONSTANT c_block_per_sync : IN POSITIVE; -- of sop/eop blocks per sync interval |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_sync : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_bsn : IN STD_LOGIC_VECTOR; |
SIGNAL verify_en : INOUT STD_LOGIC; -- initialize '0', becomes '1' when bsn verification starts |
SIGNAL cnt_replicated_global_bsn : INOUT NATURAL; |
SIGNAL prev_out_bsn_global : INOUT STD_LOGIC_VECTOR; |
SIGNAL prev_out_bsn_local : INOUT STD_LOGIC_VECTOR); |
|
-- Verify incrementing data |
-- . wrap at c_out_data_max when >0, else no wrap when c_out_data_max=0 |
-- . default increment by +1, but also allow an increment by +c_out_data_gap |
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_out_data_max : IN UNSIGNED; |
CONSTANT c_out_data_gap : IN UNSIGNED; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR); |
|
-- Verify the DUT incrementing output data that wraps in range 0 ... c_out_data_max |
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_out_data_max : IN UNSIGNED; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR); |
|
-- Verify the DUT incrementing output data, fixed increment +1 |
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; -- by using sop or eop proc_dp_verify_data() can also be used to verify other SOSI fields like bsn, error, channel, empty |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR); |
|
-- Verify incrementing data with RL > 0 or no flow control, support wrap at maximum and increment gap |
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_out_data_max : IN UNSIGNED; |
CONSTANT c_out_data_gap : IN UNSIGNED; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR); |
|
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_out_data_max : IN NATURAL; |
CONSTANT c_out_data_gap : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR); |
|
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_out_data_max : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR); |
|
-- Verify incrementing data with RL > 0 or no flow control, fixed increment +1 |
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR); |
|
-- Verify the DUT output symbols |
PROCEDURE proc_dp_verify_symbols(CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_data_w : IN NATURAL; |
CONSTANT c_symbol_w : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL out_empty : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR); |
|
-- Verify the DUT output data with empty |
PROCEDURE proc_dp_verify_data_empty(CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_last_word : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL out_eop_1 : INOUT STD_LOGIC; |
SIGNAL out_eop_2 : INOUT STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL out_data_1 : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_data_2 : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_data_3 : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_empty : IN STD_LOGIC_VECTOR; |
SIGNAL out_empty_1 : INOUT STD_LOGIC_VECTOR); |
|
PROCEDURE proc_dp_verify_other_sosi(CONSTANT c_str : IN STRING; |
CONSTANT c_exp_data : IN STD_LOGIC_VECTOR; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL res_data : IN STD_LOGIC_VECTOR); |
|
PROCEDURE proc_dp_verify_valid(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL prev_out_ready : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_val : IN STD_LOGIC); |
|
PROCEDURE proc_dp_verify_valid(SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL prev_out_ready : INOUT STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC); |
|
-- Verify the DUT output sync |
PROCEDURE proc_dp_verify_sync(CONSTANT c_sync_period : IN NATURAL; |
CONSTANT c_sync_offset : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL sync : IN STD_LOGIC; |
SIGNAL sop : IN STD_LOGIC; |
SIGNAL bsn : IN STD_LOGIC_VECTOR); |
|
-- Verify the DUT output sop and eop |
PROCEDURE proc_dp_verify_sop_and_eop(CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_verify_valid : IN BOOLEAN; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL hold_sop : INOUT STD_LOGIC); |
|
PROCEDURE proc_dp_verify_sop_and_eop(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL hold_sop : INOUT STD_LOGIC); |
|
PROCEDURE proc_dp_verify_sop_and_eop(SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL hold_sop : INOUT STD_LOGIC); |
|
PROCEDURE proc_dp_verify_block_size(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL alt_size : IN NATURAL; -- alternative size (eg. use exp_size'last_value) |
SIGNAL exp_size : IN NATURAL; -- expected size |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL cnt_size : INOUT NATURAL); |
|
PROCEDURE proc_dp_verify_block_size(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL exp_size : IN NATURAL; -- expected size |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL cnt_size : INOUT NATURAL); |
|
PROCEDURE proc_dp_verify_block_size(SIGNAL alt_size : IN NATURAL; -- alternative size (eg. use exp_size'last_value) |
SIGNAL exp_size : IN NATURAL; -- expected size |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL cnt_size : INOUT NATURAL); |
|
PROCEDURE proc_dp_verify_block_size(SIGNAL exp_size : IN NATURAL; -- expected size |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL cnt_size : INOUT NATURAL); |
|
-- Verify the DUT output invalid between frames |
PROCEDURE proc_dp_verify_gap_invalid(SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_val : IN STD_LOGIC; |
SIGNAL in_sop : IN STD_LOGIC; |
SIGNAL in_eop : IN STD_LOGIC; |
SIGNAL out_gap : INOUT STD_LOGIC); -- declare initial gap signal = '1' |
|
-- Verify the DUT output control (use for sop, eop) |
PROCEDURE proc_dp_verify_ctrl(CONSTANT c_offset : IN NATURAL; |
CONSTANT c_period : IN NATURAL; |
CONSTANT c_str : IN STRING; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL data : IN STD_LOGIC_VECTOR; |
SIGNAL valid : IN STD_LOGIC; |
SIGNAL ctrl : IN STD_LOGIC); |
|
-- Wait for stream valid |
PROCEDURE proc_dp_stream_valid(SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_valid : IN STD_LOGIC); |
|
-- Wait for stream valid AND sop |
PROCEDURE proc_dp_stream_valid_sop(SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_valid : IN STD_LOGIC; |
SIGNAL in_sop : IN STD_LOGIC); |
|
-- Wait for stream valid AND eop |
PROCEDURE proc_dp_stream_valid_eop(SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_valid : IN STD_LOGIC; |
SIGNAL in_eop : IN STD_LOGIC); |
|
END tb_dp_pkg; |
|
|
PACKAGE BODY tb_dp_pkg IS |
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Block data generator with feedforward throttle control |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_gen_block_data(CONSTANT c_nof_block_per_sync : IN NATURAL; |
CONSTANT c_block_size : IN NATURAL; |
CONSTANT c_gap_size : IN NATURAL; |
CONSTANT c_throttle_num : IN NATURAL; |
CONSTANT c_throttle_den : IN NATURAL; |
SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sync_nr : INOUT NATURAL; |
SIGNAL block_nr : INOUT NATURAL; |
SIGNAL cnt_sync : OUT STD_LOGIC; |
SIGNAL cnt_val : OUT STD_LOGIC; |
SIGNAL cnt_dat : INOUT STD_LOGIC_VECTOR) IS |
CONSTANT c_start_delay : NATURAL := 10; |
VARIABLE v_throttle : NATURAL; |
BEGIN |
sync_nr <= 0; |
block_nr <= 0; |
|
cnt_sync <= '0'; |
cnt_val <= '0'; |
cnt_dat <= (cnt_dat'RANGE=>'1'); -- -1, so first valid cnt_dat starts at 0 |
|
-- allow some clock cycles before start after rst release |
WAIT UNTIL rst='0'; |
FOR I IN 0 TO c_start_delay-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- output first sync |
cnt_sync <= '1'; |
WAIT UNTIL rising_edge(clk); |
cnt_sync <= '0'; |
FOR I IN 1 TO c_gap_size-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
WHILE TRUE LOOP |
-- output block |
IF c_throttle_num >= c_throttle_den THEN |
-- no need to throttle, so cnt_val active during whole data block |
FOR I IN 0 TO c_block_size-1 LOOP |
cnt_val <= '1'; |
cnt_dat <= INCR_UVEC(cnt_dat, 1); |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
ELSE |
-- throttle cnt_val, so c_throttle_num active cnt_val cycles per c_throttle_den cycles |
FOR I IN 0 TO c_block_size/c_throttle_num-1 LOOP |
FOR J IN 0 TO c_throttle_num-1 LOOP |
cnt_val <= '1'; |
cnt_dat <= INCR_UVEC(cnt_dat, 1); |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
FOR J IN 0 TO c_throttle_den-c_throttle_num-1 LOOP |
cnt_val <= '0'; |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
END LOOP; |
END IF; |
cnt_val <= '0'; |
-- output sync for next block at first sample of gap |
IF block_nr>0 AND ((block_nr + 1) MOD c_nof_block_per_sync)=0 THEN |
cnt_sync <= '1'; |
sync_nr <= sync_nr+1; |
END IF; |
WAIT UNTIL rising_edge(clk); |
-- output rest of the gap |
cnt_sync <= '0'; |
FOR I IN 1 TO c_gap_size-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
-- next block |
block_nr <= block_nr+1; |
END LOOP; |
END proc_dp_gen_block_data; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Block data generator with ready flow control and symbols counter |
-- . dependent on in_en and src_in.ready |
-- . optional sync pulse at end of frame |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_gen_block_data(CONSTANT c_ready_latency : IN NATURAL; -- 0, 1 are supported by proc_dp_stream_ready_latency() |
CONSTANT c_use_data : IN BOOLEAN; -- when TRUE use data field, else use re, im fields, and keep unused fields at 'X' |
CONSTANT c_data_w : IN NATURAL; -- data width for the data, re and im fields |
CONSTANT c_symbol_w : IN NATURAL; -- c_data_w/c_symbol_w must be an integer |
CONSTANT c_symbol_init : IN NATURAL; -- init counter for symbols in data field |
CONSTANT c_symbol_re_init : IN NATURAL; -- init counter for symbols in re field |
CONSTANT c_symbol_im_init : IN NATURAL; -- init counter for symbols in im field |
CONSTANT c_nof_symbols : IN NATURAL; -- nof symbols per frame for the data, re and im fields |
CONSTANT c_channel : IN NATURAL; -- channel field |
CONSTANT c_error : IN NATURAL; -- error field |
CONSTANT c_sync : IN STD_LOGIC; -- when '1' issue sync pulse during this block |
CONSTANT c_bsn : IN STD_LOGIC_VECTOR; -- bsn field |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; -- when '0' then no valid output even when src_in is ready |
SIGNAL src_in : IN t_dp_siso; |
SIGNAL src_out : OUT t_dp_sosi) IS |
CONSTANT c_nof_symbols_per_data : NATURAL := c_data_w/c_symbol_w; |
CONSTANT c_div : NATURAL := c_nof_symbols / c_nof_symbols_per_data; |
CONSTANT c_mod : NATURAL := c_nof_symbols MOD c_nof_symbols_per_data; |
CONSTANT c_empty : NATURAL := sel_a_b(c_mod, c_nof_symbols_per_data - c_mod, 0); |
CONSTANT c_nof_data : NATURAL := sel_a_b(c_mod, 1, 0) + c_div; |
VARIABLE v_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0):= func_dp_data_init(c_data_w, c_symbol_w, c_symbol_init); |
VARIABLE v_re : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0):= func_dp_data_init(c_data_w, c_symbol_w, c_symbol_re_init); |
VARIABLE v_im : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0):= func_dp_data_init(c_data_w, c_symbol_w, c_symbol_im_init); |
BEGIN |
src_out <= c_dp_sosi_rst; |
IF src_in.xon='1' THEN |
-- Generate this block |
src_out.bsn <= RESIZE_DP_BSN(c_bsn); |
src_out.empty <= TO_DP_EMPTY(c_empty); |
src_out.channel <= TO_DP_CHANNEL(c_channel); |
src_out.err <= TO_DP_ERROR(c_error); |
IF c_use_data=TRUE THEN src_out.data <= RESIZE_DP_DATA(v_data); END IF; |
IF c_use_data=FALSE THEN src_out.re <= RESIZE_DP_DSP_DATA(v_re); END IF; |
IF c_use_data=FALSE THEN src_out.im <= RESIZE_DP_DSP_DATA(v_im); END IF; |
IF c_nof_data>1 THEN |
-- . sop |
proc_dp_stream_ready_latency(c_ready_latency, clk, src_in.ready, in_en, c_sync, '1', '1', '0', src_out.sync, src_out.valid, src_out.sop, src_out.eop); |
-- . valid |
FOR I IN 1 TO c_nof_data-2 LOOP |
v_data := func_dp_data_incr(c_data_w, c_symbol_w, v_data); |
v_re := func_dp_data_incr(c_data_w, c_symbol_w, v_re); |
v_im := func_dp_data_incr(c_data_w, c_symbol_w, v_im); |
IF c_use_data=TRUE THEN src_out.data <= RESIZE_DP_DATA(v_data); END IF; |
IF c_use_data=FALSE THEN src_out.re <= RESIZE_DP_DSP_DATA(v_re); END IF; |
IF c_use_data=FALSE THEN src_out.im <= RESIZE_DP_DSP_DATA(v_im); END IF; |
proc_dp_stream_ready_latency(c_ready_latency, clk, src_in.ready, in_en, '0', '1', '0', '0', src_out.sync, src_out.valid, src_out.sop, src_out.eop); |
END LOOP; |
|
-- . eop |
v_data := func_dp_data_incr(c_data_w, c_symbol_w, v_data); |
v_re := func_dp_data_incr(c_data_w, c_symbol_w, v_re); |
v_im := func_dp_data_incr(c_data_w, c_symbol_w, v_im); |
IF c_use_data=TRUE THEN src_out.data <= RESIZE_DP_DATA(v_data); END IF; |
IF c_use_data=FALSE THEN src_out.re <= RESIZE_DP_DSP_DATA(v_re); END IF; |
IF c_use_data=FALSE THEN src_out.im <= RESIZE_DP_DSP_DATA(v_im); END IF; |
proc_dp_stream_ready_latency(c_ready_latency, clk, src_in.ready, in_en, '0', '1', '0', '1', src_out.sync, src_out.valid, src_out.sop, src_out.eop); |
ELSE |
-- . sop and eop, frame has only one word |
proc_dp_stream_ready_latency(c_ready_latency, clk, src_in.ready, in_en, c_sync, '1', '1', '1', src_out.sync, src_out.valid, src_out.sop, src_out.eop); |
END IF; |
ELSE |
-- Skip this block |
proc_common_wait_some_cycles(clk, c_nof_data); |
END IF; |
END proc_dp_gen_block_data; |
|
|
PROCEDURE proc_dp_gen_block_data(CONSTANT c_data_w : IN NATURAL; -- data width for the data field |
CONSTANT c_symbol_init : IN NATURAL; -- init counter for the data in the data field |
CONSTANT c_nof_symbols : IN NATURAL; -- nof symbols per frame for the data fields |
CONSTANT c_channel : IN NATURAL; -- channel field |
CONSTANT c_error : IN NATURAL; -- error field |
CONSTANT c_sync : IN STD_LOGIC; -- when '1' issue sync pulse during this block |
CONSTANT c_bsn : IN STD_LOGIC_VECTOR; -- bsn field |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; -- when '0' then no valid output even when src_in is ready |
SIGNAL src_in : IN t_dp_siso; |
SIGNAL src_out : OUT t_dp_sosi) IS |
BEGIN |
proc_dp_gen_block_data(1, TRUE, c_data_w, c_data_w, c_symbol_init, 0, 0, c_nof_symbols, c_channel, c_error, c_sync, c_bsn, clk, in_en, src_in, src_out); |
END proc_dp_gen_block_data; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Handle stream ready signal |
-- . output active when src_in is ready and in_en='1' |
-- . only support RL=0 or 1, support for RL>1 requires keeping previous ready information in a STD_LOGIC_VECTOR(RL-1 DOWNTO 0). |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_stream_ready_latency(CONSTANT c_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL ready : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; |
CONSTANT c_sync : IN STD_LOGIC; |
CONSTANT c_valid : IN STD_LOGIC; |
CONSTANT c_sop : IN STD_LOGIC; |
CONSTANT c_eop : IN STD_LOGIC; |
SIGNAL out_sync : OUT STD_LOGIC; |
SIGNAL out_valid : OUT STD_LOGIC; |
SIGNAL out_sop : OUT STD_LOGIC; |
SIGNAL out_eop : OUT STD_LOGIC) IS |
BEGIN |
-- Default no output |
out_sync <= '0'; |
out_valid <= '0'; |
out_sop <= '0'; |
out_eop <= '0'; |
|
-- Skip cycles until in_en='1' |
WHILE in_en='0' LOOP |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
|
-- Active output when ready |
-- . RL = 0 |
IF c_latency=0 THEN |
-- show the available output until acknowledge |
out_sync <= c_sync; |
out_valid <= c_valid; |
out_sop <= c_sop; |
out_eop <= c_eop; |
WAIT UNTIL rising_edge(clk); |
WHILE ready /= '1' LOOP |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
-- ready has acknowledged the valid output |
END IF; |
|
-- . RL = 1 |
IF c_latency=1 THEN |
-- no valid output until request |
WHILE ready /= '1' LOOP |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
-- ready has requested this valid output |
out_sync <= c_sync; |
out_valid <= c_valid; |
out_sop <= c_sop; |
out_eop <= c_eop; |
WAIT UNTIL rising_edge(clk); |
END IF; |
|
-- Return with no active output |
out_sync <= '0'; |
out_valid <= '0'; |
out_sop <= '0'; |
out_eop <= '0'; |
END proc_dp_stream_ready_latency; |
|
|
------------------------------------------------------------------------------ |
-- FUNCTION: Initialize the data per symbol |
-- . use big endian |
-- . if c_data_w=32, c_symbol_w=8, init=3 then return 0x03040506 |
------------------------------------------------------------------------------ |
FUNCTION func_dp_data_init(c_data_w, c_symbol_w, init : NATURAL) RETURN STD_LOGIC_VECTOR IS |
CONSTANT c_nof_symbols_per_data : NATURAL := c_data_w/c_symbol_w; |
VARIABLE v_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); |
VARIABLE v_sym : STD_LOGIC_VECTOR(c_symbol_w-1 DOWNTO 0); |
BEGIN |
v_data := (OTHERS=>'0'); |
v_sym := TO_UVEC(init, c_symbol_w); |
FOR I IN c_nof_symbols_per_data-1 DOWNTO 0 LOOP |
v_data((I+1)*c_symbol_w-1 DOWNTO I*c_symbol_w) := v_sym; |
v_sym := INCR_UVEC(v_sym, 1); |
END LOOP; |
RETURN v_data; |
END func_dp_data_init; |
|
|
------------------------------------------------------------------------------ |
-- FUNCTION: Increment the data per symbol |
-- . use big endian |
-- . if c_data_w=32, c_symbol_w=8 then 0x00010203 returns 0x04050607 |
-- . the actual data'LENGTH must be >= c_data_w, unused bits become 0 |
-- . c_data_w/c_symbol_w must be an integer |
------------------------------------------------------------------------------ |
FUNCTION func_dp_data_incr(c_data_w, c_symbol_w : NATURAL; data : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
CONSTANT c_nof_symbols_per_data : NATURAL := c_data_w/c_symbol_w; |
VARIABLE v_data : STD_LOGIC_VECTOR(data'LENGTH-1 DOWNTO 0); |
VARIABLE v_sym : STD_LOGIC_VECTOR(c_symbol_w-1 DOWNTO 0); |
BEGIN |
v_data := (OTHERS=>'0'); |
v_sym := data(c_symbol_w-1 DOWNTO 0); |
FOR I IN c_nof_symbols_per_data-1 DOWNTO 0 LOOP |
v_sym := INCR_UVEC(v_sym, 1); |
v_data((I+1)*c_symbol_w-1 DOWNTO I*c_symbol_w) := v_sym; |
END LOOP; |
RETURN v_data; |
END func_dp_data_incr; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Generate counter data with valid |
-- . Output counter data dependent on in_en and src_in.ready |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_gen_data(CONSTANT c_ready_latency : IN NATURAL; -- 0, 1 are supported by proc_dp_stream_ready_latency() |
CONSTANT c_data_w : IN NATURAL; |
CONSTANT c_data_init : IN NATURAL; |
SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; -- when '0' then no valid output even when src_in is ready |
SIGNAL src_in : IN t_dp_siso; |
SIGNAL src_out : OUT t_dp_sosi) IS |
VARIABLE v_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0):= TO_UVEC(c_data_init, c_data_w); |
BEGIN |
src_out <= c_dp_sosi_rst; |
src_out.data <= RESIZE_DP_DATA(v_data); |
IF rst='0' THEN |
WAIT UNTIL rising_edge(clk); |
WHILE TRUE LOOP |
src_out.data <= RESIZE_DP_DATA(v_data); |
proc_dp_stream_ready_latency(c_ready_latency, clk, src_in.ready, in_en, '0', '1', '0', '0', src_out.sync, src_out.valid, src_out.sop, src_out.eop); |
v_data := INCR_UVEC(v_data, 1); |
END LOOP; |
END IF; |
END proc_dp_gen_data; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Generate counter data with valid |
-- . Output counter data dependent on in_en and src_in.ready |
-- . with maximum count value |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_gen_data(CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_data_w : IN NATURAL; |
CONSTANT c_data_init : IN NATURAL; |
CONSTANT c_data_max : IN NATURAL; |
SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; -- when '0' then no valid output even when src_in is ready |
SIGNAL src_in : IN t_dp_siso; |
SIGNAL src_out : OUT t_dp_sosi) IS |
VARIABLE v_cnt : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0):= TO_UVEC(c_data_init, c_data_w); |
BEGIN |
src_out <= c_dp_sosi_rst; |
src_out.data <= RESIZE_DP_DATA(v_cnt); |
IF rst='0' THEN |
WAIT UNTIL rising_edge(clk); |
WHILE TRUE LOOP |
src_out.data <= RESIZE_DP_DATA(v_cnt); |
proc_dp_stream_ready_latency(c_ready_latency, clk, src_in.ready, in_en, '0', '1', '0', '0', src_out.sync, src_out.valid, src_out.sop, src_out.eop); |
IF TO_UINT(v_cnt)=c_data_max THEN |
v_cnt := TO_UVEC(c_data_init, c_data_w); |
ELSE |
v_cnt := INCR_UVEC(v_cnt, 1); |
END IF; |
END LOOP; |
END IF; |
END proc_dp_gen_data; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Generate a frame with symbols counter |
-- . dependent on in_en and src_in.ready |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_gen_frame(CONSTANT c_ready_latency : IN NATURAL; -- 0, 1 are supported by proc_dp_stream_ready_latency() |
CONSTANT c_data_w : IN NATURAL; |
CONSTANT c_symbol_w : IN NATURAL; -- c_data_w/c_symbol_w must be an integer |
CONSTANT c_symbol_init : IN NATURAL; |
CONSTANT c_nof_symbols : IN NATURAL; |
CONSTANT c_bsn : IN NATURAL; |
CONSTANT c_sync : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; -- when '0' then no valid output even when src_in is ready |
SIGNAL src_in : IN t_dp_siso; |
SIGNAL src_out : OUT t_dp_sosi) IS |
CONSTANT c_nof_symbols_per_data : NATURAL := c_data_w/c_symbol_w; |
CONSTANT c_div : NATURAL := c_nof_symbols / c_nof_symbols_per_data; |
CONSTANT c_mod : NATURAL := c_nof_symbols MOD c_nof_symbols_per_data; |
CONSTANT c_empty : NATURAL := sel_a_b(c_mod, c_nof_symbols_per_data - c_mod, 0); |
CONSTANT c_nof_data : NATURAL := sel_a_b(c_mod, 1, 0) + c_div; |
VARIABLE v_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0):= func_dp_data_init(c_data_w, c_symbol_w, c_symbol_init); |
BEGIN |
src_out <= c_dp_sosi_rst; |
src_out.bsn <= TO_DP_BSN(c_bsn); |
src_out.empty <= TO_DP_EMPTY(c_empty); |
src_out.data <= RESIZE_DP_DATA(v_data); |
IF c_nof_data>1 THEN |
-- . sop |
proc_dp_stream_ready_latency(c_ready_latency, clk, src_in.ready, in_en, c_sync, '1', '1', '0', src_out.sync, src_out.valid, src_out.sop, src_out.eop); |
-- . valid |
FOR I IN 1 TO c_nof_data-2 LOOP |
v_data := func_dp_data_incr(c_data_w, c_symbol_w, v_data); |
src_out.data <= RESIZE_DP_DATA(v_data); |
proc_dp_stream_ready_latency(c_ready_latency, clk, src_in.ready, in_en, '0', '1', '0', '0', src_out.sync, src_out.valid, src_out.sop, src_out.eop); |
END LOOP; |
-- . eop |
v_data := func_dp_data_incr(c_data_w, c_symbol_w, v_data); |
src_out.data <= RESIZE_DP_DATA(v_data); |
proc_dp_stream_ready_latency(c_ready_latency, clk, src_in.ready, in_en, '0', '1', '0', '1', src_out.sync, src_out.valid, src_out.sop, src_out.eop); |
ELSE |
-- . sop and eop, frame has only one word |
proc_dp_stream_ready_latency(c_ready_latency, clk, src_in.ready, in_en, c_sync, '1', '1', '1', src_out.sync, src_out.valid, src_out.sop, src_out.eop); |
END IF; |
src_out.sync <= '0'; |
src_out.valid <= '0'; |
src_out.sop <= '0'; |
src_out.eop <= '0'; |
END proc_dp_gen_frame; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Input data counter |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_cnt_dat(SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; |
SIGNAL cnt_dat : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
IF rst='1' THEN |
cnt_dat <= (cnt_dat'RANGE=>'0'); |
ELSIF rising_edge(clk) THEN |
IF in_en='1' THEN |
cnt_dat <= STD_LOGIC_VECTOR(UNSIGNED(cnt_dat)+1); |
END IF; |
END IF; |
END proc_dp_cnt_dat; |
|
PROCEDURE proc_dp_cnt_dat(SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_en : IN STD_LOGIC; |
SIGNAL cnt_val : INOUT STD_LOGIC; |
SIGNAL cnt_dat : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
IF rst='1' THEN |
cnt_val <= '0'; |
cnt_dat <= (cnt_dat'RANGE=>'0'); |
ELSIF rising_edge(clk) THEN |
cnt_val <= '0'; |
IF in_en='1' THEN |
cnt_val <= '1'; |
cnt_dat <= STD_LOGIC_VECTOR(UNSIGNED(cnt_dat)+1); |
END IF; |
END IF; |
END proc_dp_cnt_dat; |
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Transmit data |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_tx_data(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL cnt_val : IN STD_LOGIC; |
SIGNAL cnt_dat : IN STD_LOGIC_VECTOR; |
SIGNAL tx_data : INOUT t_dp_data_arr; |
SIGNAL tx_val : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_data : OUT STD_LOGIC_VECTOR; |
SIGNAL out_val : OUT STD_LOGIC) IS |
CONSTANT c_void : NATURAL := sel_a_b(c_ready_latency, 1, 0); -- used to avoid empty range VHDL warnings when c_ready_latency=0 |
BEGIN |
-- TX data array for output ready latency [c_ready_latency], index [0] for zero latency combinatorial |
tx_data(0) <= cnt_dat; |
tx_val( 0) <= cnt_val; |
|
IF rst='1' THEN |
tx_data(1 TO c_ready_latency+c_void) <= (1 TO c_ready_latency+c_void=>(OTHERS=>'0')); |
tx_val( 1 TO c_ready_latency+c_void) <= (1 TO c_ready_latency+c_void=>'0'); |
ELSIF rising_edge(clk) THEN |
tx_data(1 TO c_ready_latency+c_void) <= tx_data(0 TO c_ready_latency+c_void-1); |
tx_val( 1 TO c_ready_latency+c_void) <= tx_val( 0 TO c_ready_latency+c_void-1); |
END IF; |
|
out_data <= tx_data(c_ready_latency); |
out_val <= tx_val(c_ready_latency); |
END proc_dp_tx_data; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Transmit data control (use for sop, eop) |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_tx_ctrl(CONSTANT c_offset : IN NATURAL; |
CONSTANT c_period : IN NATURAL; |
SIGNAL data : IN STD_LOGIC_VECTOR; |
SIGNAL valid : IN STD_LOGIC; |
SIGNAL ctrl : OUT STD_LOGIC) IS |
VARIABLE v_data : INTEGER; |
BEGIN |
v_data := TO_UINT(data); |
ctrl <= '0'; |
IF valid='1' AND ((v_data-c_offset) MOD c_period)=0 THEN |
ctrl <= '1'; |
END IF; |
END proc_dp_tx_ctrl; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Define test sync interval |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_sync_interval(SIGNAL clk : IN STD_LOGIC; |
SIGNAL sync : OUT STD_LOGIC) IS |
BEGIN |
sync <= '0'; |
FOR I IN 1 TO c_dp_sync_interval-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
sync <= '1'; |
WAIT UNTIL rising_edge(clk); |
END proc_dp_sync_interval; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Stimuli for cnt_en |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_count_en(SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sync : IN STD_LOGIC; |
SIGNAL lfsr : INOUT STD_LOGIC_VECTOR; |
SIGNAL state : OUT t_dp_state_enum; |
SIGNAL done : OUT STD_LOGIC; |
SIGNAL tb_end : OUT STD_LOGIC; |
SIGNAL cnt_en : OUT STD_LOGIC) IS |
BEGIN |
-- The counter operates at zero latency |
state <= s_idle; |
done <= '0'; |
tb_end <= '0'; |
cnt_en <= '0'; |
WAIT UNTIL rst='0'; |
WAIT UNTIL rising_edge(clk); |
-- The cnt_val may be asserted for every active in_ready, but als support |
-- cnt_val not asserted for every asserted in_ready. |
|
---------------------------------------------------------------------------- |
-- Interval 1 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
state <= s_both_active; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 2 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
state <= s_pull_down_out_ready; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 3 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
state <= s_pull_down_cnt_en; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 1 cycle |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 2 cycle |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 3 cycle |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 4 cycle |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 5 cycle |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 6 cycle |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 7 cycle |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 4 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
state <= s_toggle_out_ready; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 5 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
state <= s_toggle_cnt_en; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 1-1 toggle |
cnt_en <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
END LOOP; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 1-2 toggle |
cnt_en <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
END LOOP; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 2-1 toggle |
cnt_en <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
END LOOP; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 2-2 toggle |
cnt_en <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
END LOOP; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 1-3 toggle |
cnt_en <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
END LOOP; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 3-1 toggle |
cnt_en <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
END LOOP; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 2-3 toggle |
cnt_en <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
END LOOP; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 3-2 toggle |
cnt_en <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '1'; |
END LOOP; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 6 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
state <= s_toggle_both; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
FOR I IN 1 TO c_dp_nof_both LOOP |
cnt_en <= '0'; |
FOR J IN 1 TO I LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
cnt_en <= '1'; |
FOR J IN I TO c_dp_nof_both LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
END LOOP; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 7 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
state <= s_pulse_cnt_en; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
FOR I IN 1 TO 15 LOOP |
FOR J IN 1 TO 15 LOOP |
cnt_en <= '0'; |
FOR K IN 1 TO I LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
cnt_en <= '1'; |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
FOR J IN 1 TO 20 LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
END LOOP; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 8 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
state <= s_chirp_out_ready; |
cnt_en <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 9 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
state <= s_random; |
cnt_en <= '1'; |
|
FOR I IN 0 TO c_dp_sync_interval - c_dp_test_interval LOOP |
lfsr <= func_common_random(lfsr); |
cnt_en <= lfsr(lfsr'HIGH); |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
|
---------------------------------------------------------------------------- |
-- Done |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
state <= s_done; |
WAIT UNTIL rising_edge(clk); |
cnt_en <= '0'; |
|
-- pulse done |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
done <= '1'; |
WAIT UNTIL rising_edge(clk); |
done <= '0'; |
|
---------------------------------------------------------------------------- |
-- Testbench end |
---------------------------------------------------------------------------- |
-- set tb_end |
WAIT UNTIL sync='1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
tb_end <= '1'; |
WAIT; |
END proc_dp_count_en; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Stimuli for out_ready |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_out_ready(SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sync : IN STD_LOGIC; |
SIGNAL lfsr : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_ready : OUT STD_LOGIC) IS |
BEGIN |
out_ready <= '0'; |
WAIT UNTIL rst='0'; |
WAIT UNTIL rising_edge(clk); |
|
---------------------------------------------------------------------------- |
-- Interval 1 : Assert both cnt_en and out_ready |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 2 : Make out_ready low for 1 or more cycles |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 1 cycle |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 2 cycle |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 3 cycle |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 4 cycle |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 5 cycle |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 6 cycle |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 7 cycle |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 3 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 4 : Toggle out_ready for 1 or more cycles |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 1-1 toggle |
out_ready <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
END LOOP; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 1-2 toggle |
out_ready <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
END LOOP; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 2-1 toggle |
out_ready <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
END LOOP; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 2-2 toggle |
out_ready <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
END LOOP; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 1-3 toggle |
out_ready <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
END LOOP; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 3-1 toggle |
out_ready <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
END LOOP; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 2-3 toggle |
out_ready <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
END LOOP; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . 3-2 toggle |
out_ready <= '0'; |
FOR I IN 1 TO c_dp_nof_toggle LOOP |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '0'; |
WAIT UNTIL rising_edge(clk); |
WAIT UNTIL rising_edge(clk); |
out_ready <= '1'; |
END LOOP; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 5 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 6 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
FOR I IN 1 TO c_dp_nof_both LOOP |
out_ready <= '0'; |
FOR J IN I TO c_dp_nof_both LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
out_ready <= '1'; |
FOR J IN 1 TO I LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
END LOOP; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 7 |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 8 : Chirp out_ready |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
-- . slow toggle |
out_ready <= '0'; |
FOR I IN 0 TO c_dp_nof_toggle LOOP |
out_ready <= '0'; |
FOR J IN 0 TO I LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
out_ready <= '1'; |
FOR J IN 0 TO I LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
END LOOP; |
out_ready <= '1'; |
FOR I IN 0 TO c_dp_test_interval LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
---------------------------------------------------------------------------- |
-- Interval 9 : Random |
---------------------------------------------------------------------------- |
WAIT UNTIL sync='1'; |
out_ready <= '1'; |
|
FOR I IN 0 TO c_dp_sync_interval - c_dp_test_interval LOOP |
lfsr <= func_common_random(lfsr); |
out_ready <= lfsr(lfsr'HIGH); |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
|
---------------------------------------------------------------------------- |
-- Done |
---------------------------------------------------------------------------- |
WAIT; |
END proc_dp_out_ready; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: DUT output verify enable |
------------------------------------------------------------------------------ |
|
-- Fixed delay until verify_en active |
PROCEDURE proc_dp_verify_en(CONSTANT c_delay : IN NATURAL; |
SIGNAL rst : IN STD_LOGIC; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL sync : IN STD_LOGIC; |
SIGNAL verify_en : OUT STD_LOGIC) IS |
BEGIN |
verify_en <= '0'; |
WAIT UNTIL rst='0'; |
WAIT UNTIL rising_edge(clk); |
|
WAIT UNTIL sync='1'; |
-- Use c_delay delay before enabling the p_verify. |
FOR I IN 0 TO c_delay LOOP WAIT UNTIL rising_edge(clk); END LOOP; |
|
verify_en <= '1'; |
WAIT; |
END proc_dp_verify_en; |
|
|
-- Dynamicly depend on first valid data to make verify_en active |
PROCEDURE proc_dp_verify_en(CONSTANT c_continuous : IN BOOLEAN; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL valid : IN STD_LOGIC; |
SIGNAL sop : IN STD_LOGIC; |
SIGNAL eop : IN STD_LOGIC; |
SIGNAL verify_en : OUT STD_LOGIC) IS |
BEGIN |
IF rising_edge(clk) THEN |
IF c_continuous=TRUE THEN |
-- Verify across frames (so enable data verify after the first data has been output) |
IF valid='1' THEN |
verify_en <= '1'; |
END IF; |
ELSE |
-- Verify only per frame (so re-enable data verify after the every sop) |
IF eop='1' THEN |
verify_en <= '0'; |
ELSIF sop='1' THEN |
verify_en <= '1'; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_en; |
|
-- Run and verify for some cycles |
PROCEDURE proc_dp_verify_run_some_cycles(CONSTANT nof_pre_clk : IN NATURAL; |
CONSTANT nof_verify_clk : IN NATURAL; |
CONSTANT nof_post_clk : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : OUT STD_LOGIC) IS |
BEGIN |
proc_common_wait_some_cycles(clk, nof_pre_clk); |
verify_en <= '1'; |
proc_common_wait_some_cycles(clk, nof_verify_clk); |
verify_en <= '0'; |
proc_common_wait_some_cycles(clk, nof_post_clk); |
END proc_dp_verify_run_some_cycles; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Verify the expected value |
------------------------------------------------------------------------------ |
-- e.g. to check that a test has ran at all |
PROCEDURE proc_dp_verify_value(CONSTANT c_str : IN STRING; |
CONSTANT mode : IN t_dp_value_enum; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL en : IN STD_LOGIC; |
SIGNAL exp : IN STD_LOGIC_VECTOR; |
SIGNAL res : IN STD_LOGIC_VECTOR) IS |
BEGIN |
IF rising_edge(clk) THEN |
IF en='1' THEN |
IF mode = e_equal AND UNSIGNED(res) /= UNSIGNED(exp) THEN |
REPORT "DP : Wrong " & c_str & " result value" SEVERITY ERROR; |
END IF; |
IF mode = e_at_least AND UNSIGNED(res) < UNSIGNED(exp) THEN |
REPORT "DP : Wrong " & c_str & " result value too small" SEVERITY ERROR; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_value; |
|
PROCEDURE proc_dp_verify_value(CONSTANT mode : IN t_dp_value_enum; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL en : IN STD_LOGIC; |
SIGNAL exp : IN STD_LOGIC_VECTOR; |
SIGNAL res : IN STD_LOGIC_VECTOR) IS |
BEGIN |
proc_dp_verify_value("", mode, clk, en, exp, res); |
END proc_dp_verify_value; |
|
PROCEDURE proc_dp_verify_value(CONSTANT c_str : IN STRING; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL en : IN STD_LOGIC; |
SIGNAL exp : IN STD_LOGIC; |
SIGNAL res : IN STD_LOGIC) IS |
BEGIN |
IF rising_edge(clk) THEN |
IF en='1' THEN |
IF res /= exp THEN |
REPORT "DP : Wrong " & c_str & " result value" SEVERITY ERROR; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_value; |
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Verify output global and local BSN |
------------------------------------------------------------------------------ |
-- Verify BSN: |
-- . incrementing or replicated global BSN |
-- . incrementing local BSN that starts at 1 |
-- |
-- _ _ _ _ |
-- sync __| |____________| |____________| |____________| |____________ |
-- _ _ _ _ _ _ _ _ _ _ _ _ |
-- sop __| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__ c_block_per_sync = 3 |
-- |
-- c_use_local_bsn = FALSE: |
-- c_nof_replicated_global_bsn = 1 |
-- bsn 3 4 5 6 7 8 9 10 11 12 13 14 c_global_bsn_increment = 1 |
-- bsn 3 5 7 9 11 13 15 17 19 21 22 23 c_global_bsn_increment = 2 |
-- |
-- c_use_local_bsn = TRUE: |
-- |
-- global bsn 3 4 5 6 c_global_bsn_increment = 1, c_nof_replicated_global_bsn = 1 |
-- global bsn 3 6 9 12 c_global_bsn_increment = 3, c_nof_replicated_global_bsn = 1 |
-- global bsn 3 3 9 9 c_global_bsn_increment = 6, c_nof_replicated_global_bsn = 2 |
-- local bsn - 1 2 - 1 2 - 1 2 - 1 2 range 1:c_block_per_sync-1 |
-- |
-- The verify_en should initially be set to '0' and gets enabled when |
-- sufficient BSN history is available to do the verification. |
-- |
PROCEDURE proc_dp_verify_bsn(CONSTANT c_use_local_bsn : IN BOOLEAN; -- use local BSN or only use global BSN |
CONSTANT c_global_bsn_increment : IN POSITIVE; -- increment per global BSN |
CONSTANT c_nof_replicated_global_bsn : IN POSITIVE; -- number of replicated global BSN |
CONSTANT c_block_per_sync : IN POSITIVE; -- of sop/eop blocks per sync interval |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_sync : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_bsn : IN STD_LOGIC_VECTOR; |
SIGNAL verify_en : INOUT STD_LOGIC; -- initialize '0', becomes '1' when bsn verification starts |
SIGNAL cnt_replicated_global_bsn : INOUT NATURAL; |
SIGNAL prev_out_bsn_global : INOUT STD_LOGIC_VECTOR; |
SIGNAL prev_out_bsn_local : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
IF rising_edge(clk) THEN |
-- out_sop must be active, because only then out_bsn will differ from the previous out_bsn |
IF out_sop='1' THEN |
IF c_use_local_bsn=FALSE THEN |
------------------------------------------------------------------ |
-- Only use global BSN |
------------------------------------------------------------------ |
prev_out_bsn_global <= out_bsn; |
-- verify |
IF out_sync='1' THEN |
verify_en <= '1'; |
END IF; |
IF verify_en='1' THEN |
ASSERT UNSIGNED(out_bsn) = UNSIGNED(prev_out_bsn_global)+c_global_bsn_increment REPORT "DP : Wrong BSN increment" SEVERITY ERROR; |
END IF; |
ELSE |
------------------------------------------------------------------ |
-- Use global and local BSN |
------------------------------------------------------------------ |
IF out_sync='1' THEN |
prev_out_bsn_global <= out_bsn; |
IF UNSIGNED(out_bsn) /= UNSIGNED(prev_out_bsn_global) THEN |
verify_en <= '1'; -- wait until after last replicated global bsn |
cnt_replicated_global_bsn <= 0; |
ELSE |
cnt_replicated_global_bsn <= cnt_replicated_global_bsn + 1; |
END IF; |
prev_out_bsn_local <= TO_UVEC(0, prev_out_bsn_global'LENGTH); |
ELSE |
prev_out_bsn_local <= out_bsn; |
END IF; |
-- verify |
IF verify_en='1' THEN |
IF out_sync='1' THEN |
IF UNSIGNED(out_bsn) /= UNSIGNED(prev_out_bsn_global) THEN |
ASSERT cnt_replicated_global_bsn=c_nof_replicated_global_bsn-1 REPORT "DP : Wrong number of replicated global BSN" SEVERITY ERROR; |
ASSERT UNSIGNED(out_bsn)=UNSIGNED(prev_out_bsn_global)+c_global_bsn_increment REPORT "DP : Wrong global BSN increment" SEVERITY ERROR; |
ELSE |
ASSERT UNSIGNED(out_bsn)=UNSIGNED(prev_out_bsn_global) REPORT "DP : Wrong replicated global BSN" SEVERITY ERROR; |
END IF; |
ASSERT UNSIGNED(prev_out_bsn_local)=c_block_per_sync-1 REPORT "DP : Wrong last local BSN in sync interval" SEVERITY ERROR; |
ELSE |
ASSERT UNSIGNED(out_bsn)=UNSIGNED(prev_out_bsn_local)+1 REPORT "DP : Wrong local BSN increment" SEVERITY ERROR; |
END IF; |
END IF; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_bsn; |
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Verify the DUT output data |
------------------------------------------------------------------------------ |
|
-- Verify incrementing data |
-- . wrap at c_out_data_max when >0, else no wrap when c_out_data_max=0 |
-- . default increment by 1, but also allow an increment by c_out_data_gap |
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_out_data_max : IN UNSIGNED; |
CONSTANT c_out_data_gap : IN UNSIGNED; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; -- only needed when c_ready_latency = 0 |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
IF rising_edge(clk) THEN |
-- out_val must be active, because only the out_data will it differ from the previous out_data |
IF out_val='1' THEN |
-- for ready_latency > 0 out_val indicates new data |
-- for ready_latency = 0 out_val only indicates new data when it is confirmed by out_ready |
IF c_ready_latency/=0 OR (c_ready_latency=0 AND out_ready='1') THEN |
IF c_out_data_max=0 THEN |
prev_out_data <= out_data; -- no wrap detection |
ELSIF UNSIGNED(out_data)<c_out_data_max THEN |
prev_out_data <= out_data; -- no wrap |
ELSE |
prev_out_data <= TO_SVEC(-1, prev_out_data'LENGTH); -- do wrap |
END IF; |
IF verify_en='1' THEN |
IF UNSIGNED(out_data) /= UNSIGNED(prev_out_data)+1 AND -- check increment +1 |
UNSIGNED(out_data) /= UNSIGNED(prev_out_data)+c_out_data_gap AND -- increment +c_out_data_gap |
UNSIGNED(out_data) /= UNSIGNED(prev_out_data)+c_out_data_gap-c_out_data_max THEN -- increment +c_out_data_gap wrapped |
REPORT "DP : Wrong out_data " & c_str & " count" SEVERITY ERROR; |
END IF; |
END IF; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_data; |
|
-- Verify incrementing data that wraps in range 0 ... c_out_data_max |
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_out_data_max : IN UNSIGNED; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
proc_dp_verify_data(c_str, c_ready_latency, c_out_data_max, TO_UNSIGNED(1,1), clk, verify_en, out_ready, out_val, out_data, prev_out_data); |
END proc_dp_verify_data; |
|
-- Verify incrementing data |
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
proc_dp_verify_data(c_str, c_ready_latency, TO_UNSIGNED(0,1), TO_UNSIGNED(1,1), clk, verify_en, out_ready, out_val, out_data, prev_out_data); |
END proc_dp_verify_data; |
|
-- Verify incrementing data with RL > 0 or no flow control |
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_out_data_max : IN UNSIGNED; |
CONSTANT c_out_data_gap : IN UNSIGNED; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
-- Use out_val as void signal to pass on to unused out_ready, because a signal input can not connect a constant or variable |
proc_dp_verify_data(c_str, 1, c_out_data_max, c_out_data_gap, clk, verify_en, out_val, out_val, out_data, prev_out_data); |
END proc_dp_verify_data; |
|
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_out_data_max : IN NATURAL; |
CONSTANT c_out_data_gap : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR) IS |
CONSTANT c_data_w : NATURAL := out_data'LENGTH; |
BEGIN |
proc_dp_verify_data(c_str, TO_UNSIGNED(c_out_data_max, c_data_w), TO_UNSIGNED(c_out_data_gap, c_data_w), clk, verify_en, out_val, out_data, prev_out_data); |
END proc_dp_verify_data; |
|
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
CONSTANT c_out_data_max : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR) IS |
CONSTANT c_data_w : NATURAL := out_data'LENGTH; |
BEGIN |
proc_dp_verify_data(c_str, TO_UNSIGNED(c_out_data_max, c_data_w), TO_UNSIGNED(1, 1), clk, verify_en, out_val, out_data, prev_out_data); |
END proc_dp_verify_data; |
|
PROCEDURE proc_dp_verify_data(CONSTANT c_str : IN STRING; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR) IS |
BEGIN |
-- Use out_val as void signal to pass on to unused out_ready, because a signal input can not connect a constant or variable |
proc_dp_verify_data(c_str, 1, TO_UNSIGNED(0,1), TO_UNSIGNED(1,1), clk, verify_en, out_val, out_val, out_data, prev_out_data); |
END proc_dp_verify_data; |
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Verify incrementing symbols in data |
-- . for c_data_w = c_symbol_w proc_dp_verify_symbols() = proc_dp_verify_data() |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_verify_symbols(CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_data_w : IN NATURAL; |
CONSTANT c_symbol_w : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL out_empty : IN STD_LOGIC_VECTOR; |
SIGNAL prev_out_data : INOUT STD_LOGIC_VECTOR) IS |
CONSTANT c_nof_symbols_per_data : NATURAL := c_data_w/c_symbol_w; -- must be an integer |
CONSTANT c_empty_w : NATURAL := ceil_log2(c_nof_symbols_per_data); |
VARIABLE v_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); |
VARIABLE v_symbol : STD_LOGIC_VECTOR(c_symbol_w-1 DOWNTO 0); |
VARIABLE v_empty : NATURAL; |
BEGIN |
IF rising_edge(clk) THEN |
-- out_val must be active, because only the out_data will it differ from the previous out_data |
IF out_val='1' THEN |
-- for ready_latency > 0 out_val indicates new data |
-- for ready_latency = 0 out_val only indicates new data when it is confirmed by out_ready |
IF c_ready_latency/=0 OR (c_ready_latency=0 AND out_ready='1') THEN |
prev_out_data <= out_data; |
IF verify_en='1' THEN |
v_data := prev_out_data(c_data_w-1 DOWNTO 0); |
FOR I IN 0 TO c_nof_symbols_per_data-1 LOOP |
v_data((I+1)*c_symbol_w-1 DOWNTO I*c_symbol_w) := INCR_UVEC(v_data((I+1)*c_symbol_w-1 DOWNTO I*c_symbol_w), c_nof_symbols_per_data); -- increment each symbol |
END LOOP; |
IF out_eop='0' THEN |
IF UNSIGNED(out_data) /= UNSIGNED(v_data) THEN |
REPORT "DP : Wrong out_data symbols count" SEVERITY ERROR; |
END IF; |
ELSE |
v_empty := TO_UINT(out_empty(c_empty_w-1 DOWNTO 0)); |
IF UNSIGNED(out_data(c_data_w-1 DOWNTO v_empty*c_symbol_w)) /= UNSIGNED(v_data(c_data_w-1 DOWNTO v_empty*c_symbol_w)) THEN |
REPORT "DP : Wrong out_data symbols count at eop" SEVERITY ERROR; |
END IF; |
IF v_empty>0 THEN |
-- adjust prev_out_data for potentially undefined empty symbols in out_data |
v_symbol := v_data((v_empty+1)*c_symbol_w-1 DOWNTO v_empty*c_symbol_w); -- last valid symbol |
FOR I IN 0 TO c_nof_symbols_per_data-1 LOOP |
v_data((I+1)*c_symbol_w-1 DOWNTO I*c_symbol_w) := v_symbol; -- put the last valid symbol at the end of the v_data |
v_symbol := INCR_UVEC(v_symbol, -1); -- decrement each symbol towards the beginning of v_data |
END LOOP; |
prev_out_data <= v_data; |
END IF; |
END IF; |
END IF; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_symbols; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Verify the DUT output data with empty |
-- . account for stream empty |
-- . support last word replace (e.g. by a CRC instead of the count, or use |
-- c_last_word=out_data for no replace) |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_verify_data_empty(CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_last_word : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL out_eop_1 : INOUT STD_LOGIC; |
SIGNAL out_eop_2 : INOUT STD_LOGIC; |
SIGNAL out_data : IN STD_LOGIC_VECTOR; |
SIGNAL out_data_1 : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_data_2 : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_data_3 : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_empty : IN STD_LOGIC_VECTOR; |
SIGNAL out_empty_1 : INOUT STD_LOGIC_VECTOR) IS |
VARIABLE v_last_word : STD_LOGIC_VECTOR(out_data'RANGE); |
VARIABLE v_ref_data : STD_LOGIC_VECTOR(out_data'RANGE); |
VARIABLE v_empty_data : STD_LOGIC_VECTOR(out_data'RANGE); |
BEGIN |
IF rising_edge(clk) THEN |
-- out_val must be active, because only then out_data will differ from the previous out_data |
IF out_val='1' THEN |
-- for ready_latency > 0 out_val indicates new data |
-- for ready_latency = 0 out_val only indicates new data when it is confirmed by out_ready |
IF c_ready_latency/=0 OR (c_ready_latency=0 AND out_ready='1') THEN |
-- default expected data |
out_data_1 <= out_data; |
out_data_2 <= out_data_1; |
out_data_3 <= out_data_2; |
out_empty_1 <= out_empty; |
out_eop_1 <= out_eop; |
out_eop_2 <= out_eop_1; |
IF verify_en='1' THEN |
-- assume sufficient valid cycles between eop and sop, so no need to check for out_sop with regard to eop empty |
IF out_eop='0' AND out_eop_1='0' AND out_eop_2='0'THEN |
-- verify out_data from eop-n to eop-2 and from eop+1 to eop+n, n>2 |
v_ref_data := INCR_UVEC(out_data_2, 1); |
IF UNSIGNED(out_data_1) /= UNSIGNED(v_ref_data) THEN |
REPORT "DP : Wrong out_data count" SEVERITY ERROR; |
END IF; |
ELSE |
-- the empty and crc replace affect data at eop_1 and eop, so need to check data from eop-2 to eop-1 to eop to eop+1 |
v_last_word := TO_UVEC(c_last_word, out_data'LENGTH); |
IF out_eop='1' THEN |
-- verify out_data at eop |
CASE TO_INTEGER(UNSIGNED(out_empty)) IS |
WHEN 0 => v_empty_data := v_last_word; |
WHEN 1 => v_empty_data := v_last_word(3*c_byte_w-1 DOWNTO 0) & c_slv0(1*c_byte_w-1 DOWNTO 0); |
WHEN 2 => v_empty_data := v_last_word(2*c_byte_w-1 DOWNTO 0) & c_slv0(2*c_byte_w-1 DOWNTO 0); |
WHEN 3 => v_empty_data := v_last_word(1*c_byte_w-1 DOWNTO 0) & c_slv0(3*c_byte_w-1 DOWNTO 0); |
WHEN OTHERS => NULL; |
END CASE; |
IF UNSIGNED(out_data) /= UNSIGNED(v_empty_data) THEN |
REPORT "DP : Wrong out_data count at eop" SEVERITY ERROR; |
END IF; |
ELSIF out_eop_1='1' THEN |
-- verify out_data from eop-2 to eop-1 |
v_ref_data := INCR_UVEC(out_data_3, 1); |
CASE TO_INTEGER(UNSIGNED(out_empty_1)) IS |
WHEN 0 => v_empty_data := v_ref_data; |
WHEN 1 => v_empty_data := v_ref_data(4*c_byte_w-1 DOWNTO 1*c_byte_w) & v_last_word(4*c_byte_w-1 DOWNTO 3*c_byte_w); |
WHEN 2 => v_empty_data := v_ref_data(4*c_byte_w-1 DOWNTO 2*c_byte_w) & v_last_word(4*c_byte_w-1 DOWNTO 2*c_byte_w); |
WHEN 3 => v_empty_data := v_ref_data(4*c_byte_w-1 DOWNTO 3*c_byte_w) & v_last_word(4*c_byte_w-1 DOWNTO 1*c_byte_w); |
WHEN OTHERS => NULL; |
END CASE; |
IF UNSIGNED(out_data_2) /= UNSIGNED(v_empty_data) THEN |
REPORT "DP : Wrong out_data count at eop-1" SEVERITY ERROR; |
END IF; |
-- verify out_data from eop-2 to eop+1 |
v_ref_data := INCR_UVEC(out_data_3, 3); |
IF UNSIGNED(out_data) /= UNSIGNED(v_ref_data) THEN |
REPORT "DP : Wrong out_data count at eop+1" SEVERITY ERROR; |
END IF; |
END IF; |
END IF; |
END IF; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_data_empty; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Verify the DUT output other SOSI data |
-- . Suited to verify the empty, error, channel fields assuming that these |
-- are treated in the same way in parallel to the SOSI data. |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_verify_other_sosi(CONSTANT c_str : IN STRING; |
CONSTANT c_exp_data : IN STD_LOGIC_VECTOR; -- use constant to support assignment via FUNCTION return value |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL res_data : IN STD_LOGIC_VECTOR) IS |
BEGIN |
IF rising_edge(clk) THEN |
IF verify_en='1' THEN |
IF c_str="bsn" THEN |
IF UNSIGNED(c_exp_data(c_dp_bsn_w-1 DOWNTO 0))/=UNSIGNED(res_data(c_dp_bsn_w-1 DOWNTO 0)) THEN |
REPORT "DP : Wrong sosi.bsn value" SEVERITY ERROR; |
END IF; |
ELSIF c_str="empty" THEN |
IF UNSIGNED(c_exp_data(c_dp_empty_w-1 DOWNTO 0))/=UNSIGNED(res_data(c_dp_empty_w-1 DOWNTO 0)) THEN |
REPORT "DP : Wrong sosi.empty value" SEVERITY ERROR; |
END IF; |
ELSIF c_str="channel" THEN |
IF UNSIGNED(c_exp_data(c_dp_channel_user_w-1 DOWNTO 0))/=UNSIGNED(res_data(c_dp_channel_user_w-1 DOWNTO 0)) THEN |
REPORT "DP : Wrong sosi.channel value" SEVERITY ERROR; |
END IF; |
ELSIF c_str="error" THEN |
IF UNSIGNED(c_exp_data(c_dp_error_w-1 DOWNTO 0))/=UNSIGNED(res_data(c_dp_error_w-1 DOWNTO 0)) THEN |
REPORT "DP : Wrong sosi.error value" SEVERITY ERROR; |
END IF; |
ELSE |
REPORT "proc_dp_verify_other_sosi : Unknown sosi." & c_str & "field" SEVERITY FAILURE; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_other_sosi; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Verify the DUT output valid |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_verify_valid(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL prev_out_ready : INOUT STD_LOGIC_VECTOR; |
SIGNAL out_val : IN STD_LOGIC) IS |
BEGIN |
IF rising_edge(clk) THEN |
-- for ready_latency > 0 out_val may only be asserted after out_ready |
-- for ready_latency = 0 out_val may always be asserted |
prev_out_ready <= (prev_out_ready'RANGE=>'0'); |
IF c_ready_latency/=0 THEN |
IF c_ready_latency=1 THEN |
prev_out_ready(0) <= out_ready; |
ELSE |
prev_out_ready <= out_ready & prev_out_ready(0 TO c_ready_latency-1); |
END IF; |
IF verify_en='1' AND out_val='1' THEN |
IF prev_out_ready(c_ready_latency-1)/='1' THEN |
REPORT "DP : Wrong ready latency between out_ready and out_val" SEVERITY ERROR; |
END IF; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_valid; |
|
PROCEDURE proc_dp_verify_valid(SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL prev_out_ready : INOUT STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC) IS |
BEGIN |
-- Can not reuse: |
-- proc_dp_verify_valid(1, clk, verify_en, out_ready, prev_out_ready, out_val); |
-- because prev_out_ready needs to map from STD_LOGIC to STD_LOGIC_VECTOR. Therefore copy paste code for RL=1: |
IF rising_edge(clk) THEN |
-- for ready_latency = 1 out_val may only be asserted after out_ready |
prev_out_ready <= out_ready; |
IF verify_en='1' AND out_val='1' THEN |
IF prev_out_ready/='1' THEN |
REPORT "DP : Wrong ready latency between out_ready and out_val" SEVERITY ERROR; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_valid; |
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Verify the DUT output sync |
-- . sync is defined such that it can only be active at sop |
-- . assume that the sync occures priodically at bsn MOD c_sync_period = c_sync_offset |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_verify_sync(CONSTANT c_sync_period : IN NATURAL; -- BSN sync period |
CONSTANT c_sync_offset : IN NATURAL; -- BSN sync offset |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL sync : IN STD_LOGIC; |
SIGNAL sop : IN STD_LOGIC; |
SIGNAL bsn : IN STD_LOGIC_VECTOR) IS |
CONSTANT c_bsn_w : NATURAL := sel_a_b(bsn'LENGTH>31, 31, bsn'LENGTH); -- use maximally 31 bit of BSN slv to allow calculations with integers |
VARIABLE v_expected_sync : BOOLEAN; |
BEGIN |
IF rising_edge(clk) THEN |
IF verify_en='1' THEN |
v_expected_sync := (TO_UINT(bsn(c_bsn_w-1 DOWNTO 0))-c_sync_offset) MOD c_sync_period = 0; |
-- Check for unexpected sync |
IF sync='1' THEN |
ASSERT v_expected_sync = TRUE |
REPORT "Error: Unexpected sync at BSN" SEVERITY ERROR; |
ASSERT sop = '1' |
REPORT "Error: Unexpected sync at inactive sop" SEVERITY ERROR; |
END IF; |
-- Check for missing sync |
IF sop='1' AND v_expected_sync=TRUE THEN |
ASSERT sync = '1' |
REPORT "Error: Missing sync" SEVERITY ERROR; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_sync; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Verify the DUT output sop and eop |
------------------------------------------------------------------------------ |
-- sop and eop in pairs, valid during packet and invalid between packets |
PROCEDURE proc_dp_verify_sop_and_eop(CONSTANT c_ready_latency : IN NATURAL; |
CONSTANT c_verify_valid : IN BOOLEAN; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL hold_sop : INOUT STD_LOGIC) IS |
BEGIN |
IF rising_edge(clk) THEN |
IF out_val='0' THEN |
IF out_sop='1' THEN REPORT "DP : Wrong active sop during invalid" SEVERITY ERROR; END IF; |
IF out_eop='1' THEN REPORT "DP : Wrong active eop during invalid" SEVERITY ERROR; END IF; |
ELSE |
-- for ready_latency > 0 out_val indicates new data |
-- for ready_latency = 0 out_val only indicates new data when it is confirmed by out_ready |
IF c_ready_latency/=0 OR (c_ready_latency=0 AND out_ready='1') THEN |
IF out_sop='1' THEN |
hold_sop <= '1'; |
IF hold_sop='1' THEN |
REPORT "DP : Unexpected sop without eop" SEVERITY ERROR; |
END IF; |
END IF; |
IF out_eop='1' THEN |
hold_sop <= '0'; |
IF hold_sop='0' AND out_sop='0' THEN |
REPORT "DP : Unexpected eop without sop" SEVERITY ERROR; |
END IF; |
END IF; |
-- out_val='1' |
IF c_verify_valid=TRUE AND out_sop='0' AND hold_sop='0' THEN |
REPORT "DP : Unexpected valid in gap between eop and sop" SEVERITY ERROR; |
END IF; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_sop_and_eop; |
|
PROCEDURE proc_dp_verify_sop_and_eop(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL hold_sop : INOUT STD_LOGIC) IS |
BEGIN |
proc_dp_verify_sop_and_eop(c_ready_latency, TRUE, clk, out_ready, out_val, out_sop, out_eop, hold_sop); |
END proc_dp_verify_sop_and_eop; |
|
PROCEDURE proc_dp_verify_sop_and_eop(SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL hold_sop : INOUT STD_LOGIC) IS |
BEGIN |
-- Use out_val as void signal to pass on to unused out_ready, because a signal input can not connect a constant or variable |
proc_dp_verify_sop_and_eop(1, TRUE, clk, out_val, out_val, out_sop, out_eop, hold_sop); |
END proc_dp_verify_sop_and_eop; |
|
PROCEDURE proc_dp_verify_block_size(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL alt_size : IN NATURAL; -- alternative size |
SIGNAL exp_size : IN NATURAL; -- expected size |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL cnt_size : INOUT NATURAL) IS |
BEGIN |
IF rising_edge(clk) THEN |
IF out_val='1' THEN |
-- for ready_latency > 0 out_val indicates new data |
-- for ready_latency = 0 out_val only indicates new data when it is confirmed by out_ready |
IF c_ready_latency/=0 OR (c_ready_latency=0 AND out_ready='1') THEN |
IF out_sop='1' THEN |
cnt_size <= 1; |
ELSIF out_eop='1' THEN |
cnt_size <= 0; |
IF cnt_size/=alt_size-1 AND cnt_size/=exp_size-1 THEN |
REPORT "DP : Unexpected block size" SEVERITY ERROR; |
END IF; |
ELSE |
cnt_size <= cnt_size+1; |
END IF; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_block_size; |
|
PROCEDURE proc_dp_verify_block_size(CONSTANT c_ready_latency : IN NATURAL; |
SIGNAL exp_size : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_ready : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL cnt_size : INOUT NATURAL) IS |
BEGIN |
proc_dp_verify_block_size(c_ready_latency, exp_size, exp_size, clk, out_ready, out_val, out_sop, out_eop, cnt_size); |
END proc_dp_verify_block_size; |
|
PROCEDURE proc_dp_verify_block_size(SIGNAL alt_size : IN NATURAL; -- alternative size |
SIGNAL exp_size : IN NATURAL; -- expected size |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL cnt_size : INOUT NATURAL) IS |
BEGIN |
-- Use out_val as void signal to pass on to unused out_ready, because a signal input can not connect a constant or variable |
proc_dp_verify_block_size(1, alt_size, exp_size, clk, out_val, out_val, out_sop, out_eop, cnt_size); |
END proc_dp_verify_block_size; |
|
PROCEDURE proc_dp_verify_block_size(SIGNAL exp_size : IN NATURAL; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL out_val : IN STD_LOGIC; |
SIGNAL out_sop : IN STD_LOGIC; |
SIGNAL out_eop : IN STD_LOGIC; |
SIGNAL cnt_size : INOUT NATURAL) IS |
BEGIN |
-- Use out_val as void signal to pass on to unused out_ready, because a signal input can not connect a constant or variable |
proc_dp_verify_block_size(1, exp_size, exp_size, clk, out_val, out_val, out_sop, out_eop, cnt_size); |
END proc_dp_verify_block_size; |
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Verify the DUT output invalid between frames |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_verify_gap_invalid(SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_val : IN STD_LOGIC; |
SIGNAL in_sop : IN STD_LOGIC; |
SIGNAL in_eop : IN STD_LOGIC; |
SIGNAL out_gap : INOUT STD_LOGIC) IS |
BEGIN |
IF rising_edge(clk) THEN |
IF in_eop='1' THEN |
out_gap <= '1'; |
ELSIF in_sop='1' THEN |
out_gap <= '0'; |
ELSIF in_val='1' AND out_gap='1' THEN |
REPORT "DP : Wrong valid in gap between eop and sop" SEVERITY ERROR; |
END IF; |
END IF; |
END proc_dp_verify_gap_invalid; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Verify the DUT output control (use for sop, eop) |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_verify_ctrl(CONSTANT c_offset : IN NATURAL; |
CONSTANT c_period : IN NATURAL; |
CONSTANT c_str : IN STRING; |
SIGNAL clk : IN STD_LOGIC; |
SIGNAL verify_en : IN STD_LOGIC; |
SIGNAL data : IN STD_LOGIC_VECTOR; |
SIGNAL valid : IN STD_LOGIC; |
SIGNAL ctrl : IN STD_LOGIC) IS |
VARIABLE v_data : INTEGER; |
BEGIN |
IF rising_edge(clk) THEN |
IF verify_en='1' THEN |
v_data := TO_UINT(data); |
IF ((v_data-c_offset) MOD c_period)=0 THEN |
IF valid='1' AND ctrl/='1' THEN |
REPORT "DP : Wrong data control, missing " & c_str SEVERITY ERROR; |
END IF; |
ELSE |
IF ctrl='1' THEN |
REPORT "DP : Wrong data control, unexpected " & c_str SEVERITY ERROR; |
END IF; |
END IF; |
END IF; |
END IF; |
END proc_dp_verify_ctrl; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Wait for stream valid |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_stream_valid(SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_valid : IN STD_LOGIC) IS |
BEGIN |
WAIT UNTIL rising_edge(clk); |
WHILE in_valid /= '1' LOOP |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
END proc_dp_stream_valid; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Wait for stream valid AND sop |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_stream_valid_sop(SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_valid : IN STD_LOGIC; |
SIGNAL in_sop : IN STD_LOGIC) IS |
BEGIN |
WAIT UNTIL rising_edge(clk); |
WHILE in_valid /= '1' AND in_sop /= '1' LOOP |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
END proc_dp_stream_valid_sop; |
|
|
------------------------------------------------------------------------------ |
-- PROCEDURE: Wait for stream valid AND eop |
------------------------------------------------------------------------------ |
PROCEDURE proc_dp_stream_valid_eop(SIGNAL clk : IN STD_LOGIC; |
SIGNAL in_valid : IN STD_LOGIC; |
SIGNAL in_eop : IN STD_LOGIC) IS |
BEGIN |
WAIT UNTIL rising_edge(clk); |
WHILE in_valid /= '1' AND in_eop /= '1' LOOP |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
END proc_dp_stream_valid_eop; |
|
END tb_dp_pkg; |