Skip to content
Snippets Groups Projects
Commit a425b849 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Verify lost stream data and lost data flag in channel bit 0, via g_lost_stream_id in tb.

parent 29335661
No related branches found
No related tags found
1 merge request!159Use v.busy, instead of r.busy, to allow start_pulse at mm_done, to support...
...@@ -26,13 +26,17 @@ ...@@ -26,13 +26,17 @@
-- input stream that is ahead of the other remote input streams. After a -- input stream that is ahead of the other remote input streams. After a
-- certain number of blocks on input 0, the same block on all remote -- certain number of blocks on input 0, the same block on all remote
-- inputs should also have arrived. If not then they are replaced by -- inputs should also have arrived. If not then they are replaced by
-- replacement data. The output streams are paced by the block rate of input 0. -- replacement data. The output streams are paced by the block rate of
-- The user has to read the block within the block period. -- input 0. The user has to read the block within the block period.
-- --
-- Features: -- Features:
-- . uses lost_data flag and replacement data to replace lost input blocks -- . The g_block_size <= block period, so supports input blocks arriving
-- with or without data valid gaps
-- . uses replacement data to replace lost input blocks and channel bit 0 as
-- lost_data flag
-- . uses replacement data to replace disabled input streams -- . uses replacement data to replace disabled input streams
-- . output block can be read in arbitrary order -- . output block can be read in arbitrary order via g_use_mm_output = TRUE
-- . output block can be streamed via g_use_mm_output = FALSE
-- --
-- For more detailed description see: -- For more detailed description see:
-- https://support.astron.nl/confluence/display/L2M/L6+FWLIB+Design+Document%3A+BSN+aligner+v2 -- https://support.astron.nl/confluence/display/L2M/L6+FWLIB+Design+Document%3A+BSN+aligner+v2
...@@ -53,13 +57,13 @@ USE work.dp_stream_pkg.ALL; ...@@ -53,13 +57,13 @@ USE work.dp_stream_pkg.ALL;
ENTITY dp_bsn_align_v2 IS ENTITY dp_bsn_align_v2 IS
GENERIC ( GENERIC (
g_nof_streams : NATURAL; -- number of input and output streams g_nof_streams : NATURAL; -- >= 2, number of input and output streams
g_bsn_latency_max : NATURAL; -- Maximum travel latency of a remote block in number of block periods T_blk g_bsn_latency_max : NATURAL; -- maximum travel latency of a remote block in number of block periods T_blk
g_nof_aligners_max : POSITIVE := 1; -- 1 when only align at last node, > 1 when align at every intermediate node g_nof_aligners_max : POSITIVE := 1; -- 1 when only align at last node, > 1 when align at every intermediate node
g_block_size : NATURAL := 32; -- > 1, g_block_size=1 is not supported g_block_size : NATURAL := 32; -- > 1, g_block_size=1 is not supported
g_bsn_w : NATURAL := c_dp_stream_bsn_w; -- number of bits in sosi BSN g_bsn_w : NATURAL := c_dp_stream_bsn_w; -- number of bits in sosi BSN
g_data_w : NATURAL; -- number of bits in sosi data g_data_w : NATURAL; -- number of bits in sosi data
g_replacement_value : INTEGER := 0; -- output sosi data value for missing input blocks g_data_replacement_value : INTEGER := 0; -- output sosi data value for missing input blocks
g_use_mm_output : BOOLEAN := FALSE; -- output via MM or via streaming DP g_use_mm_output : BOOLEAN := FALSE; -- output via MM or via streaming DP
g_pipeline_input : NATURAL := 0; -- >= 0, choose 0 for wires, choose 1 to ease timing closure g_pipeline_input : NATURAL := 0; -- >= 0, choose 0 for wires, choose 1 to ease timing closure
g_rd_latency : NATURAL := 1 -- 1 or 2, choose 2 to ease timing closure g_rd_latency : NATURAL := 1 -- 1 or 2, choose 2 to ease timing closure
...@@ -107,10 +111,15 @@ ARCHITECTURE rtl OF dp_bsn_align_v2 IS ...@@ -107,10 +111,15 @@ ARCHITECTURE rtl OF dp_bsn_align_v2 IS
-- avoid that synthesis may infer a too larger multiplier -- avoid that synthesis may infer a too larger multiplier
CONSTANT c_product_w : NATURAL := c_blk_pointer_w + c_block_size_w; CONSTANT c_product_w : NATURAL := c_blk_pointer_w + c_block_size_w;
-- Output on lost data flag via out_sosi_arr().channel bit 0
CONSTANT c_channel_w : NATURAL := 1;
TYPE t_bsn_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); TYPE t_bsn_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
TYPE t_channel_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_channel_w-1 DOWNTO 0);
TYPE t_adr_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_mem_ram.adr_w-1 DOWNTO 0); TYPE t_adr_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_mem_ram.adr_w-1 DOWNTO 0);
TYPE t_filled_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_buffer_nof_blocks-1 DOWNTO 0); TYPE t_filled_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_buffer_nof_blocks-1 DOWNTO 0);
-- State
TYPE t_reg IS RECORD TYPE t_reg IS RECORD
-- p_write_arr -- p_write_arr
wr_pointer : NATURAL; wr_pointer : NATURAL;
...@@ -128,14 +137,20 @@ ARCHITECTURE rtl OF dp_bsn_align_v2 IS ...@@ -128,14 +137,20 @@ ARCHITECTURE rtl OF dp_bsn_align_v2 IS
rd_offset : STD_LOGIC_VECTOR(c_mem_ram.adr_w-1 DOWNTO 0); rd_offset : STD_LOGIC_VECTOR(c_mem_ram.adr_w-1 DOWNTO 0);
rd_copi : t_mem_copi; rd_copi : t_mem_copi;
fill_cipo_arr : t_mem_cipo_arr(g_nof_streams-1 DOWNTO 0); -- used combinatorial to contain rd_cipo_arr from buffer or replacement data fill_cipo_arr : t_mem_cipo_arr(g_nof_streams-1 DOWNTO 0); -- used combinatorial to contain rd_cipo_arr from buffer or replacement data
out_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); -- hold BSN for streaming output out_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); -- hold BSN until next sop, for easy view in Wave window
out_channel_arr : t_channel_arr(g_nof_streams-1 DOWNTO 0); -- hold channel until next sop per stream, for easy view in Wave window
END RECORD; END RECORD;
-- Wires and auxiliary variables in p_comb
-- . For unique representation as signal wire, the p_comb should assign each
-- field in t_comb only once to a variable. It is allowed to reasign a
-- t_comb variable in p_comb, but then only the last assignment value will
-- be visible via the signal dbg_wires in the Wave window.
TYPE t_comb IS RECORD TYPE t_comb IS RECORD
ref_sosi : t_dp_sosi; ref_sosi : t_dp_sosi;
pointer_slv : STD_LOGIC_VECTOR(c_blk_pointer_w-1 DOWNTO 0); pointer_slv : STD_LOGIC_VECTOR(c_blk_pointer_w-1 DOWNTO 0);
product_slv : STD_LOGIC_VECTOR(c_product_w-1 DOWNTO 0); product_slv : STD_LOGIC_VECTOR(c_product_w-1 DOWNTO 0);
lost_data_flag : STD_LOGIC; lost_data_flags_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
END RECORD; END RECORD;
...@@ -151,14 +166,15 @@ ARCHITECTURE rtl OF dp_bsn_align_v2 IS ...@@ -151,14 +166,15 @@ ARCHITECTURE rtl OF dp_bsn_align_v2 IS
(OTHERS=>'0'), (OTHERS=>'0'),
c_mem_copi_rst, c_mem_copi_rst,
(OTHERS=>c_mem_cipo_rst), (OTHERS=>c_mem_cipo_rst),
(OTHERS=>'0')); (OTHERS=>'0'),
(OTHERS=>(OTHERS=>'0')));
-- State registers for p_comb -- State registers for p_comb
SIGNAL r : t_reg; SIGNAL r : t_reg;
SIGNAL nxt_r : t_reg; SIGNAL nxt_r : t_reg;
-- Memoryless signals in p_comb (wires used as local auxiliary variables) -- Memoryless signals in p_comb (wires used as local variables)
SIGNAL s : t_comb; SIGNAL dbg_wires : t_comb;
-- Structural signals (wires used to connect components and IO) -- Structural signals (wires used to connect components and IO)
SIGNAL dp_done : STD_LOGIC; SIGNAL dp_done : STD_LOGIC;
...@@ -180,7 +196,7 @@ ARCHITECTURE rtl OF dp_bsn_align_v2 IS ...@@ -180,7 +196,7 @@ ARCHITECTURE rtl OF dp_bsn_align_v2 IS
SIGNAL dbg_block_size : NATURAL := g_block_size; SIGNAL dbg_block_size : NATURAL := g_block_size;
SIGNAL dbg_bsn_w : NATURAL := g_bsn_w; SIGNAL dbg_bsn_w : NATURAL := g_bsn_w;
SIGNAL dbg_data_w : NATURAL := g_data_w; SIGNAL dbg_data_w : NATURAL := g_data_w;
SIGNAL dbg_replacement_value : INTEGER := g_replacement_value; SIGNAL dbg_data_replacement_value : INTEGER := g_data_replacement_value;
SIGNAL dbg_use_mm_output : BOOLEAN := g_use_mm_output; SIGNAL dbg_use_mm_output : BOOLEAN := g_use_mm_output;
SIGNAL dbg_pipeline_input : NATURAL := g_pipeline_input; SIGNAL dbg_pipeline_input : NATURAL := g_pipeline_input;
SIGNAL dbg_rd_latency : NATURAL := g_rd_latency; SIGNAL dbg_rd_latency : NATURAL := g_rd_latency;
...@@ -202,7 +218,7 @@ BEGIN ...@@ -202,7 +218,7 @@ BEGIN
p_comb : PROCESS(r, in_sosi_arr_p, mm_copi, dp_copi, rd_cipo_arr, rd_sosi_arr) p_comb : PROCESS(r, in_sosi_arr_p, mm_copi, dp_copi, rd_cipo_arr, rd_sosi_arr)
VARIABLE v : t_reg; -- State variable VARIABLE v : t_reg; -- State variable
VARIABLE d : t_comb; -- Memoryless auxiliary variables, local wires VARIABLE w : t_comb; -- Local wires = memoryless auxiliary variables
BEGIN BEGIN
v := r; -- state signals v := r; -- state signals
v.mm_sosi := func_dp_stream_reset_control(r.mm_sosi); v.mm_sosi := func_dp_stream_reset_control(r.mm_sosi);
...@@ -222,24 +238,24 @@ BEGIN ...@@ -222,24 +238,24 @@ BEGIN
IF in_sosi_arr_p(I).sop = '1' THEN IF in_sosi_arr_p(I).sop = '1' THEN
-- . set address at start of block -- . set address at start of block
d.pointer_slv := in_sosi_arr_p(I).bsn(c_blk_pointer_w-1 DOWNTO 0); w.pointer_slv := in_sosi_arr_p(I).bsn(c_blk_pointer_w-1 DOWNTO 0);
d.product_slv := MULT_UVEC(d.pointer_slv, c_block_size_slv); w.product_slv := MULT_UVEC(w.pointer_slv, c_block_size_slv);
v.wr_copi_arr(I).address := RESIZE_MEM_ADDRESS(d.product_slv); v.wr_copi_arr(I).address := RESIZE_MEM_ADDRESS(w.product_slv);
-- . set filled flag at sop, so assume rest of block will follow in time -- . set filled flag at sop, so assume rest of block will follow in time
v.filled_arr(I)(TO_UINT(d.pointer_slv)) := '1'; v.filled_arr(I)(TO_UINT(w.pointer_slv)) := '1';
END IF; END IF;
END LOOP; END LOOP;
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- p_control, all at sop of local reference input 0 -- p_control, all at sop of local reference input 0
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
d.ref_sosi := in_sosi_arr_p(0); w.ref_sosi := in_sosi_arr_p(0);
IF d.ref_sosi.sop = '1' THEN IF w.ref_sosi.sop = '1' THEN
-- . write sync & bsn buffer -- . write sync & bsn buffer
v.wr_pointer := TO_UINT(d.ref_sosi.bsn(c_blk_pointer_w-1 DOWNTO 0)); v.wr_pointer := TO_UINT(w.ref_sosi.bsn(c_blk_pointer_w-1 DOWNTO 0));
v.sync_arr(v.wr_pointer) := d.ref_sosi.sync; v.sync_arr(v.wr_pointer) := w.ref_sosi.sync;
v.bsn_arr(v.wr_pointer) := d.ref_sosi.bsn(g_bsn_w-1 DOWNTO 0); v.bsn_arr(v.wr_pointer) := w.ref_sosi.bsn(g_bsn_w-1 DOWNTO 0);
-- . update read block pointer at g_bsn_latency_max blocks behind the reference write pointer -- . update read block pointer at g_bsn_latency_max blocks behind the reference write pointer
IF g_nof_aligners_max = 1 THEN IF g_nof_aligners_max = 1 THEN
...@@ -252,9 +268,9 @@ BEGIN ...@@ -252,9 +268,9 @@ BEGIN
END IF; END IF;
-- . update read address of read block pointer -- . update read address of read block pointer
d.pointer_slv := TO_UVEC(v.rd_pointer, c_blk_pointer_w); w.pointer_slv := TO_UVEC(v.rd_pointer, c_blk_pointer_w);
d.product_slv := MULT_UVEC(d.pointer_slv, c_block_size_slv); w.product_slv := MULT_UVEC(w.pointer_slv, c_block_size_slv);
v.rd_offset := RESIZE_UVEC(d.product_slv, c_mem_ram.adr_w); v.rd_offset := RESIZE_UVEC(w.product_slv, c_mem_ram.adr_w);
-- . issue mm_sosi, if there is output ready to be read, indicated by filled reference block -- . issue mm_sosi, if there is output ready to be read, indicated by filled reference block
IF r.filled_arr(0)(v.rd_pointer) = '1' THEN IF r.filled_arr(0)(v.rd_pointer) = '1' THEN
...@@ -268,10 +284,10 @@ BEGIN ...@@ -268,10 +284,10 @@ BEGIN
-- determine whether the ouput has to insert replacement data -- determine whether the ouput has to insert replacement data
v.mm_sosi.channel := (OTHERS=>'0'); v.mm_sosi.channel := (OTHERS=>'0');
FOR I IN 0 TO g_nof_streams-1 LOOP FOR I IN 0 TO g_nof_streams-1 LOOP
d.lost_data_flag := NOT v.filled_arr(I)(v.rd_pointer); w.lost_data_flags_arr(I) := NOT v.filled_arr(I)(v.rd_pointer);
IF stream_en_arr(I) = '1' THEN -- use MM bit at sop IF stream_en_arr(I) = '1' THEN -- use MM bit at sop
v.use_replacement_data(I) := d.lost_data_flag; -- enabled stream, so replace the data if the data was lost v.use_replacement_data(I) := w.lost_data_flags_arr(I); -- enabled stream, so replace the data if the data was lost
v.mm_sosi.channel(I) := d.lost_data_flag; -- enabled stream, so flag the data if the data was lost v.mm_sosi.channel(I) := w.lost_data_flags_arr(I); -- enabled stream, so flag the data if the data was lost
ELSE ELSE
v.use_replacement_data(I) := '1'; -- disabled stream, so replace the data, but do not flag the data as lost v.use_replacement_data(I) := '1'; -- disabled stream, so replace the data, but do not flag the data as lost
END IF; END IF;
...@@ -294,7 +310,7 @@ BEGIN ...@@ -294,7 +310,7 @@ BEGIN
-- . if necessary, replace a stream by replacement data -- . if necessary, replace a stream by replacement data
FOR I IN 0 TO g_nof_streams-1 LOOP FOR I IN 0 TO g_nof_streams-1 LOOP
IF r.use_replacement_data(I) = '1' THEN IF r.use_replacement_data(I) = '1' THEN
v.fill_cipo_arr(I).rddata := TO_MEM_SDATA(g_replacement_value); v.fill_cipo_arr(I).rddata := TO_MEM_SDATA(g_data_replacement_value);
END IF; END IF;
END LOOP; END LOOP;
...@@ -327,26 +343,33 @@ BEGIN ...@@ -327,26 +343,33 @@ BEGIN
END IF; END IF;
-- . pass on input data from the buffer -- . pass on input data from the buffer
d.out_sosi_arr := rd_sosi_arr; -- = v.fill_cipo_arr in streaming format, contains the w.out_sosi_arr := rd_sosi_arr; -- = v.fill_cipo_arr in streaming format, contains the
-- input data from the buffer or replacement data -- input data from the buffer or replacement data
IF rd_sosi_arr(0).sop = '1' THEN IF rd_sosi_arr(0).sop = '1' THEN
-- . at sop pass on input info from r.dp_sosi to all streams in out_sosi_arr -- . at sop pass on input info from r.dp_sosi to all streams in out_sosi_arr
d.out_sosi_arr := func_dp_stream_arr_set(d.out_sosi_arr, r.dp_sosi.sync, "SYNC"); w.out_sosi_arr := func_dp_stream_arr_set(w.out_sosi_arr, r.dp_sosi.sync, "SYNC");
d.out_sosi_arr := func_dp_stream_arr_set(d.out_sosi_arr, r.dp_sosi.bsn, "BSN"); w.out_sosi_arr := func_dp_stream_arr_set(w.out_sosi_arr, r.dp_sosi.bsn, "BSN");
FOR I IN 0 TO g_nof_streams-1 LOOP FOR I IN 0 TO g_nof_streams-1 LOOP
-- . pass on the lost flag per stream -- . pass on the lost flag per stream
d.out_sosi_arr(I).channel := RESIZE_DP_CHANNEL(slv(r.dp_sosi.channel(I))); w.out_sosi_arr(I).channel := RESIZE_DP_CHANNEL(slv(r.dp_sosi.channel(I)));
END LOOP; END LOOP;
-- . hold BSN until next sop, to ease view in wave window -- . hold sop info fields until next sop, to ease view in wave window
v.out_bsn := r.dp_sosi.bsn(g_bsn_w-1 DOWNTO 0); v.out_bsn := r.dp_sosi.bsn(g_bsn_w-1 DOWNTO 0);
FOR I IN 0 TO g_nof_streams-1 LOOP
v.out_channel_arr(I) := w.out_sosi_arr(I).channel(c_channel_w-1 DOWNTO 0);
END LOOP;
ELSE ELSE
-- . until next sop pass on BSN, to ease view in wave window -- . until next sop pass on BSN to all streams, to ease view in wave window
d.out_sosi_arr := func_dp_stream_arr_set(d.out_sosi_arr, r.out_bsn, "BSN"); w.out_sosi_arr := func_dp_stream_arr_set(w.out_sosi_arr, r.out_bsn, "BSN");
FOR I IN 0 TO g_nof_streams-1 LOOP
-- . until next sop pass on channel bit 0 per stream, to ease view in wave window
w.out_sosi_arr(I).channel := RESIZE_DP_CHANNEL(r.out_channel_arr(I));
END LOOP;
END IF; END IF;
-- . output via DP streaming interface -- . output via DP streaming interface
out_sosi_arr <= d.out_sosi_arr; out_sosi_arr <= w.out_sosi_arr;
-- . no output via MM interface -- . no output via MM interface
mm_cipo_arr <= (OTHERS => c_mem_cipo_rst); mm_cipo_arr <= (OTHERS => c_mem_cipo_rst);
...@@ -357,8 +380,8 @@ BEGIN ...@@ -357,8 +380,8 @@ BEGIN
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
nxt_r <= v; nxt_r <= v;
-- memory less signals, only for view in wave window -- local wires, only for view in wave window
s <= d; dbg_wires <= w;
END PROCESS; END PROCESS;
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
-- . gaps or no gaps between blocks via g_block_period >= g_block_size -- . gaps or no gaps between blocks via g_block_period >= g_block_size
-- . g_bsn_latency_max in combination with g_tb_diff_delay -- . g_bsn_latency_max in combination with g_tb_diff_delay
-- . g_use_mm_output using DUT MM to DP or external MM to DP in tb -- . g_use_mm_output using DUT MM to DP or external MM to DP in tb
-- . g_replacement_value for a remote g_disable_stream (one is enough -- . g_data_replacement_value for a remote g_disable_stream_id (one is enough
-- to verify), the local stream cannot be disabled. -- to verify), the local stream cannot be disabled.
-- Usage: -- Usage:
-- > as 10 -- > as 10
...@@ -52,8 +52,9 @@ ENTITY tb_dp_bsn_align_v2 IS ...@@ -52,8 +52,9 @@ ENTITY tb_dp_bsn_align_v2 IS
g_block_period : NATURAL := 20; -- >= g_block_size, = g_block_size + c_gap_size g_block_period : NATURAL := 20; -- >= g_block_size, = g_block_size + c_gap_size
g_bsn_w : NATURAL := c_dp_stream_bsn_w; -- number of bits in sosi BSN g_bsn_w : NATURAL := c_dp_stream_bsn_w; -- number of bits in sosi BSN
g_data_w : NATURAL := 16; -- number of bits in sosi data g_data_w : NATURAL := 16; -- number of bits in sosi data
g_replacement_value : INTEGER := 17; -- output sosi data replacement value for missing input blocks g_data_replacement_value : INTEGER := 17; -- output sosi data replacement value for missing input blocks
g_disable_stream : NATURAL := 0; -- default 0 to enable all streams, > 0 selects stream that will be disabled g_disable_stream_id : NATURAL := 0; -- default 0 to enable all streams, > 0 selects stream that will be disabled
g_lost_stream_id : NATURAL := 1; -- default 0 to have all streams, > 0 selects stream that will be lost
g_use_mm_output : BOOLEAN := FALSE; -- output via MM or via streaming DP g_use_mm_output : BOOLEAN := FALSE; -- output via MM or via streaming DP
g_pipeline_input : NATURAL := 0; -- >= 0, choose 0 for wires, choose 1 to ease timing closure g_pipeline_input : NATURAL := 0; -- >= 0, choose 0 for wires, choose 1 to ease timing closure
g_rd_latency : NATURAL := 1; -- 1 or 2, choose 2 to ease timing closure g_rd_latency : NATURAL := 1; -- 1 or 2, choose 2 to ease timing closure
...@@ -123,6 +124,7 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS ...@@ -123,6 +124,7 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS
SIGNAL node_index : NATURAL := 0; SIGNAL node_index : NATURAL := 0;
SIGNAL stream_en_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '1'); -- default all streams are enabled SIGNAL stream_en_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '1'); -- default all streams are enabled
SIGNAL stream_lost_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '0'); -- default no streams are lost
SIGNAL ref_siso_arr : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); SIGNAL ref_siso_arr : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
SIGNAL ref_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); -- generated stimuli SIGNAL ref_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); -- generated stimuli
...@@ -160,11 +162,11 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS ...@@ -160,11 +162,11 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS
SIGNAL out_data_arr : t_data_arr; SIGNAL out_data_arr : t_data_arr;
SIGNAL hold_data_arr : t_data_arr; SIGNAL hold_data_arr : t_data_arr;
SIGNAL out_bsn_arr : t_bsn_arr; SIGNAL out_bsn_arr : t_bsn_arr;
SIGNAL out_bsn : INTEGER;
SIGNAL out_channel_arr : t_channel_arr; SIGNAL out_channel_arr : t_channel_arr;
SIGNAL out_err_arr : t_err_arr; SIGNAL out_err_arr : t_err_arr;
SIGNAL tb_state : t_tb_state; SIGNAL tb_state : t_tb_state;
SIGNAL tb_bsn : INTEGER;
SIGNAL restart_cnt_arr : t_nat_integer_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => -1); SIGNAL restart_cnt_arr : t_nat_integer_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => -1);
SIGNAL restart_cnt : INTEGER := 0; SIGNAL restart_cnt : INTEGER := 0;
SIGNAL ref_sosi_arr_dly : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL ref_sosi_arr_dly : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
...@@ -176,6 +178,7 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS ...@@ -176,6 +178,7 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS
SIGNAL hold_out_sop_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL hold_out_sop_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL expected_out_bsn_arr : t_bsn_arr; SIGNAL expected_out_bsn_arr : t_bsn_arr;
SIGNAL expected_out_data_arr : t_data_arr; SIGNAL expected_out_data_arr : t_data_arr;
SIGNAL expected_out_channel_arr : t_channel_arr;
SIGNAL dbg_func_delay_max : NATURAL := func_input_delay(g_nof_streams - 1); SIGNAL dbg_func_delay_max : NATURAL := func_input_delay(g_nof_streams - 1);
...@@ -213,16 +216,30 @@ BEGIN ...@@ -213,16 +216,30 @@ BEGIN
v_data := v_data + g_block_size; v_data := v_data + g_block_size;
proc_common_wait_some_cycles(clk, c_gap_size); -- create gap between frames proc_common_wait_some_cycles(clk, c_gap_size); -- create gap between frames
END LOOP; END LOOP;
-- no gap between restarts, to ease verification by maintaining fixed latency of out_sosi_arr_exp -- no gap between restarts, to ease verification by maintaining fixed
-- latency of out_sosi_arr_exp
restart_cnt_arr(I) <= restart_cnt_arr(I) + 1; restart_cnt_arr(I) <= restart_cnt_arr(I) + 1;
END LOOP; END LOOP;
-- End of stimuli, g_bsn_latency_max blocks remain in DUT buffer -- End of stimuli
-- . default g_bsn_latency_max blocks remain in DUT buffer
expected_out_bsn_arr(I) <= TO_UVEC(v_bsn-1 - c_align_latency_nof_blocks, c_bsn_w); expected_out_bsn_arr(I) <= TO_UVEC(v_bsn-1 - c_align_latency_nof_blocks, c_bsn_w);
expected_out_data_arr(I) <= TO_UVEC(v_data-1 - c_align_latency_nof_valid, c_data_w); expected_out_data_arr(I) <= TO_UVEC(v_data-1 - c_align_latency_nof_valid, c_data_w);
IF I > 0 AND I = g_disable_stream THEN -- . default no data is lost, so all channel(0) lost data flags are 0
-- Expected stream disable replacement value expected_out_channel_arr(I) <= TO_DP_CHANNEL(0);
expected_out_data_arr(I) <= TO_UVEC(g_replacement_value, c_data_w);
-- Account for disturbed remote input streams
IF I > 0 THEN
IF I = g_disable_stream_id THEN
-- Expected stream disable replacement data value
expected_out_data_arr(I) <= TO_UVEC(g_data_replacement_value, c_data_w);
END IF;
IF I = g_lost_stream_id THEN
-- Expected stream lost replacement data value and expected lost
-- flag channel(0) value
expected_out_data_arr(I) <= TO_UVEC(g_data_replacement_value, c_data_w);
expected_out_channel_arr(I) <= TO_DP_CHANNEL(1);
END IF;
END IF; END IF;
proc_common_wait_some_cycles(clk, 100); proc_common_wait_some_cycles(clk, 100);
...@@ -235,8 +252,26 @@ BEGIN ...@@ -235,8 +252,26 @@ BEGIN
END PROCESS; END PROCESS;
END GENERATE; END GENERATE;
-- Model remote input stream enable/disable tb_end <= vector_and(tb_end_arr);
stream_en_arr(g_disable_stream) <= '0' WHEN g_disable_stream > 0;
-- Model misalignment latency between the input streams
gen_rx_sosi_arr : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE
rx_sosi_arr(I) <= TRANSPORT ref_sosi_arr(I) AFTER func_input_delay(I) * clk_period;
END GENERATE;
-- Model enable/disable remote input stream
stream_en_arr(g_disable_stream_id) <= '0' WHEN g_disable_stream_id > 0;
-- Model lost remote input stream
stream_lost_arr(g_lost_stream_id) <= '1' WHEN g_lost_stream_id > 0;
p_in_sosi_arr : PROCESS(rx_sosi_arr, stream_lost_arr)
BEGIN
in_sosi_arr <= rx_sosi_arr;
IF stream_lost_arr(g_lost_stream_id) = '1' THEN
in_sosi_arr(g_lost_stream_id) <= RESET_DP_SOSI_CTRL(rx_sosi_arr(g_lost_stream_id));
END IF;
END PROCESS;
-- Use tb_state to view tb progress in Wave window -- Use tb_state to view tb progress in Wave window
restart_cnt <= restart_cnt_arr(0); restart_cnt <= restart_cnt_arr(0);
...@@ -249,16 +284,6 @@ BEGIN ...@@ -249,16 +284,6 @@ BEGIN
IF restart_cnt > 1 THEN tb_state <= s_restart; END IF; IF restart_cnt > 1 THEN tb_state <= s_restart; END IF;
END PROCESS; END PROCESS;
-- Model misalignment latency between the input streams
gen_rx_sosi_arr : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE
rx_sosi_arr(I) <= TRANSPORT ref_sosi_arr(I) AFTER func_input_delay(I) * clk_period;
END GENERATE;
-- Model lost input
in_sosi_arr <= rx_sosi_arr;
tb_end <= vector_and(tb_end_arr);
mon_sosi : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE mon_sosi : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE
-- Ease in_sosi_arr monitoring -- Ease in_sosi_arr monitoring
in_sync_arr(I) <= in_sosi_arr(I).sync; in_sync_arr(I) <= in_sosi_arr(I).sync;
...@@ -283,14 +308,14 @@ BEGIN ...@@ -283,14 +308,14 @@ BEGIN
out_sosi <= out_sosi_arr(0); -- take out_sosi control and info from out_sosi_arr(0) out_sosi <= out_sosi_arr(0); -- take out_sosi control and info from out_sosi_arr(0)
out_bsn <= TO_UINT(out_sosi.bsn); -- = out_bsn_arr().bsn = out_sosi_arr(I).bsn
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- DATA VERIFICATION, use multiple ways to increase coverage -- DATA VERIFICATION, use multiple ways to increase coverage
-- a) Use proc_dp_verify_*() to verify output compared to prev output -- a) Use proc_dp_verify_*() to verify output sosi format
-- b) Use delayed in_sosi_arr as expected out_sosi_arr -- b) Use delayed in_sosi_arr as expected out_sosi_arr to verify output sosi
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
tb_bsn <= TO_UINT(out_sosi.bsn);
ref_sosi_arr_dly <= TRANSPORT ref_sosi_arr AFTER c_total_latency * clk_period; ref_sosi_arr_dly <= TRANSPORT ref_sosi_arr AFTER c_total_latency * clk_period;
out_sosi_arr_exp <= ref_sosi_arr_dly WHEN rising_edge(clk); out_sosi_arr_exp <= ref_sosi_arr_dly WHEN rising_edge(clk);
out_sosi_exp <= out_sosi_arr_exp(0); -- take out_sosi_exp control and info from out_sosi_arr_exp(0) out_sosi_exp <= out_sosi_arr_exp(0); -- take out_sosi_exp control and info from out_sosi_arr_exp(0)
...@@ -303,9 +328,9 @@ BEGIN ...@@ -303,9 +328,9 @@ BEGIN
-- . Verify that the stimuli have been applied at all -- . Verify that the stimuli have been applied at all
hold_data_arr(I) <= out_data_arr(I) WHEN out_val_arr(I) = '1'; -- hold last valid data hold_data_arr(I) <= out_data_arr(I) WHEN out_val_arr(I) = '1'; -- hold last valid data
proc_dp_verify_value("out_data_arr", e_equal, clk, verify_done_arr(I), expected_out_data_arr(I), hold_data_arr(I)); proc_dp_verify_value("out_data_arr", e_equal, clk, verify_done_arr(I), expected_out_data_arr(I), hold_data_arr(I));
proc_dp_verify_value("out_bsn_arr", e_equal, clk, verify_done_arr(I), expected_out_bsn_arr(I), out_bsn_arr(I)); proc_dp_verify_value("out_bsn_arr", e_equal, clk, verify_done_arr(I), expected_out_bsn_arr(I), out_bsn_arr(I));
proc_dp_verify_value("out_channel_arr", e_equal, clk, verify_done_arr(I), expected_out_channel_arr(I), out_channel_arr(I));
END GENERATE; END GENERATE;
-- . Use delayed in_sosi_arr as expected out_sosi_arr, this is possible -- . Use delayed in_sosi_arr as expected out_sosi_arr, this is possible
...@@ -329,14 +354,23 @@ BEGIN ...@@ -329,14 +354,23 @@ BEGIN
ASSERT out_sosi_arr(I).sop = out_sosi_arr_exp(I).sop REPORT "Wrong sop for output " & int_to_str(I) SEVERITY ERROR; ASSERT out_sosi_arr(I).sop = out_sosi_arr_exp(I).sop REPORT "Wrong sop for output " & int_to_str(I) SEVERITY ERROR;
ASSERT out_sosi_arr(I).eop = out_sosi_arr_exp(I).eop REPORT "Wrong eop for output " & int_to_str(I) SEVERITY ERROR; ASSERT out_sosi_arr(I).eop = out_sosi_arr_exp(I).eop REPORT "Wrong eop for output " & int_to_str(I) SEVERITY ERROR;
ASSERT out_sosi_arr(I).valid = out_sosi_arr_exp(I).valid REPORT "Wrong valid for output " & int_to_str(I) SEVERITY ERROR; ASSERT out_sosi_arr(I).valid = out_sosi_arr_exp(I).valid REPORT "Wrong valid for output " & int_to_str(I) SEVERITY ERROR;
IF stream_en_arr(I) = '1' THEN -- data field
IF stream_en_arr(I) = '1' AND stream_lost_arr(I) = '0' THEN
ASSERT out_sosi_arr(I).data = out_sosi_arr_exp(I).data REPORT "Wrong data for output " & int_to_str(I) & " : " ASSERT out_sosi_arr(I).data = out_sosi_arr_exp(I).data REPORT "Wrong data for output " & int_to_str(I) & " : "
& int_to_str(TO_UINT(out_sosi_arr(I).data)) & " /= " & int_to_str(TO_UINT(out_sosi_arr(I).data)) & " /= "
& int_to_str(TO_UINT(out_sosi_arr_exp(I).data)) SEVERITY ERROR; & int_to_str(TO_UINT(out_sosi_arr_exp(I).data)) SEVERITY ERROR;
ELSE ELSE
ASSERT TO_UINT(out_sosi_arr(I).data) = g_replacement_value REPORT "Wrong data for output " & int_to_str(I) & " : " ASSERT TO_UINT(out_sosi_arr(I).data) = g_data_replacement_value REPORT "Wrong replacement data for output " & int_to_str(I) & " : "
& int_to_str(TO_UINT(out_sosi_arr(I).data)) & " /= " & int_to_str(TO_UINT(out_sosi_arr(I).data)) & " /= "
& int_to_str(g_replacement_value) SEVERITY ERROR; & int_to_str(g_data_replacement_value) SEVERITY ERROR;
END IF;
IF out_sosi_arr_exp(I).sop = '1' THEN
-- channel field with lost flag bit 0
IF stream_lost_arr(I) = '0' THEN
ASSERT out_sosi_arr(I).channel = out_sosi_arr_exp(I).channel REPORT "Wrong lost flag bit in channel /= 0 for output " & int_to_str(I) SEVERITY ERROR;
ELSE
ASSERT out_sosi_arr(I).channel = TO_DP_CHANNEL(1) REPORT "Wrong lost flag bit channel /= 1 for output " & int_to_str(I) SEVERITY ERROR;
END IF;
END IF; END IF;
END IF; END IF;
END IF; END IF;
...@@ -355,7 +389,7 @@ BEGIN ...@@ -355,7 +389,7 @@ BEGIN
g_block_size => g_block_size, g_block_size => g_block_size,
g_bsn_w => g_bsn_w, g_bsn_w => g_bsn_w,
g_data_w => g_data_w, g_data_w => g_data_w,
g_replacement_value => g_replacement_value, g_data_replacement_value => g_data_replacement_value,
g_use_mm_output => g_use_mm_output, -- output via MM or via streaming DP g_use_mm_output => g_use_mm_output, -- output via MM or via streaming DP
g_pipeline_input => g_pipeline_input, -- >= 0, choose 0 for wires, choose 1 to ease timing closure g_pipeline_input => g_pipeline_input, -- >= 0, choose 0 for wires, choose 1 to ease timing closure
g_rd_latency => g_rd_latency -- 1 or 2, choose 2 to ease timing closure g_rd_latency => g_rd_latency -- 1 or 2, choose 2 to ease timing closure
......
...@@ -50,8 +50,9 @@ BEGIN ...@@ -50,8 +50,9 @@ BEGIN
-- g_block_period : NATURAL := 20; -- >= g_block_size, = g_block_size + c_gap_size -- g_block_period : NATURAL := 20; -- >= g_block_size, = g_block_size + c_gap_size
-- g_bsn_w : NATURAL := c_dp_stream_bsn_w; -- number of bits in sosi BSN -- g_bsn_w : NATURAL := c_dp_stream_bsn_w; -- number of bits in sosi BSN
-- g_data_w : NATURAL := 16; -- number of bits in sosi data -- g_data_w : NATURAL := 16; -- number of bits in sosi data
-- c_replacement_value : INTEGER := 0; -- output sosi data replacement value for missing input blocks -- g_data_replacement_value : INTEGER := 0; -- output sosi data replacement value for missing input blocks
-- g_disable_stream : NATURAL := 0; -- default 0 to enable all streams, > 0 selects stream that will be disabled -- g_disable_stream_id : NATURAL := 0; -- default 0 to enable all streams, > 0 selects stream that will be disabled
-- g_lost_stream_id : NATURAL := 0; -- default 0 to have all streams, > 0 selects stream that will be lost
-- g_use_mm_output : BOOLEAN := FALSE; -- output via MM or via streaming DP -- g_use_mm_output : BOOLEAN := FALSE; -- output via MM or via streaming DP
-- g_pipeline_input : NATURAL := 1; -- >= 0, choose 0 for wires, choose 1 to ease timing closure -- g_pipeline_input : NATURAL := 1; -- >= 0, choose 0 for wires, choose 1 to ease timing closure
-- g_rd_latency : NATURAL := 2; -- 1 or 2, choose 2 to ease timing closure -- g_rd_latency : NATURAL := 2; -- 1 or 2, choose 2 to ease timing closure
...@@ -62,14 +63,15 @@ BEGIN ...@@ -62,14 +63,15 @@ BEGIN
-- g_tb_nof_restart : NATURAL := 1; -- number of times to restart the input stimuli -- g_tb_nof_restart : NATURAL := 1; -- number of times to restart the input stimuli
-- g_tb_nof_blocks : NATURAL := 10 -- number of input blocks per restart -- g_tb_nof_blocks : NATURAL := 10 -- number of input blocks per restart
u_mm_output : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 1, 1, c_block, c_period, 32, 16, 17, 0, TRUE, 0, 1, 0, 2, c_nof_blk); u_mm_output : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 1, 1, c_block, c_period, 32, 16, 17, 0, 0, TRUE, 0, 1, 0, 2, c_nof_blk);
u_dp_output : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 1, 1, c_block, c_period, 32, 16, 17, 0, FALSE, 0, 1, 0, 2, c_nof_blk); u_dp_output : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 1, 1, c_block, c_period, 32, 16, 17, 0, 0, FALSE, 0, 1, 0, 2, c_nof_blk);
u_dp_output_bsn_lat_2 : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 2, 1, c_block, c_period, 32, 16, 17, 0, FALSE, 0, 1, 0, 2, c_nof_blk); u_bsn_lat_max_2 : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 2, 1, c_block, c_period, 32, 16, 17, 0, 0, FALSE, 0, 1, 0, 2, c_nof_blk);
u_dp_output_bsn_lat_3 : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 3, 1, c_block, c_period, 32, 16, 17, 0, FALSE, 0, 1, 0, 2, c_nof_blk); u_bsn_lat_max_3 : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 3, 1, c_block, c_period, 32, 16, 17, 0, 0, FALSE, 0, 1, 0, 2, c_nof_blk);
u_dp_output_p1_rd2 : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 1, 1, c_block, c_period, 32, 16, 17, 0, FALSE, 1, 2, 0, 2, c_nof_blk); u_pipe1_rdlat2 : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 1, 1, c_block, c_period, 32, 16, 17, 0, 0, FALSE, 1, 2, 0, 2, c_nof_blk);
u_dp_zero_gap : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 1, 1, c_block, c_block, 32, 16, 17, 0, FALSE, 0, 1, 0, 2, c_nof_blk); u_zero_gap : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 1, 1, c_block, c_block, 32, 16, 17, 0, 0, FALSE, 0, 1, 0, 2, c_nof_blk);
u_dp_disable_one : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (4, 1, 1, c_block, c_period, 32, 16, 17, 2, FALSE, 0, 1, 0, 2, c_nof_blk); u_stream_disable : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (3, 1, 1, c_block, c_period, 32, 16, 17, 2, 0, FALSE, 0, 1, 0, 2, c_nof_blk);
u_stream_lost : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (3, 1, 1, c_block, c_period, 32, 16, 17, 0, 2, FALSE, 0, 1, 0, 2, c_nof_blk);
u_diff_delay_no_loss : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 1, 1, c_block, c_period, 32, 16, 17, 0, FALSE, 0, 1, -1, 2, c_nof_blk); u_stream_disable_lost : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (4, 1, 1, c_block, c_period, 32, 16, 17, 1, 2, FALSE, 0, 1, 0, 2, c_nof_blk);
u_diff_delay_no_loss : ENTITY work.tb_dp_bsn_align_v2 GENERIC MAP (2, 1, 1, c_block, c_period, 32, 16, 17, 0, 0, FALSE, 0, 1, -1, 2, c_nof_blk);
END tb; END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment