From 9747ac57db58090e77f68b1176544a5cc4fe32af Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Wed, 29 Sep 2021 16:10:45 +0200 Subject: [PATCH] Use g_tb_nof_restart. Added verify_en_delayed_arr using out_sosi_arr_exp. Improved out_sosi_arr_exp. --- .../base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd | 164 ++++++++++-------- 1 file changed, 92 insertions(+), 72 deletions(-) diff --git a/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd b/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd index ef8cea35ca..cc561ee13f 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd @@ -37,11 +37,11 @@ USE dp_lib.tb_dp_pkg.ALL; ENTITY tb_dp_bsn_align_v2 IS GENERIC ( -- DUT - g_nof_streams : NATURAL := 5; -- number of input and output streams + g_nof_streams : NATURAL := 2; -- number of input and output streams g_bsn_latency_max : NATURAL := 2; -- 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_block_size : NATURAL := 11; -- > 1, g_block_size=1 is not supported - g_gap_size : NATURAL := 9; -- block period = g_block_size + g_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_data_w : NATURAL := 16; -- number of bits in sosi data g_replacement_value : INTEGER := 17; -- output sosi data replacement value for missing input blocks @@ -50,8 +50,9 @@ ENTITY tb_dp_bsn_align_v2 IS g_rd_latency : NATURAL := 2; -- 1 or 2, choose 2 to ease timing closure -- TB - g_diff_delay_max : NATURAL := 45; -- maximum nof clk delay between any inputs, <= c_align_latency - g_nof_repeat : NATURAL := 8 + g_tb_diff_delay_max : NATURAL := 10; -- maximum nof clk delay between any inputs, <= c_align_latency_nof_clk + g_tb_nof_restart : NATURAL := 2; -- number of times to restart the input stimuli + g_tb_nof_blocks : NATURAL := 20 -- number of input blocks per restart ); END tb_dp_bsn_align_v2; @@ -62,17 +63,21 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS CONSTANT c_data_w : NATURAL := 16; CONSTANT c_data_init : INTEGER := 0; - CONSTANT c_bsn_w : NATURAL := 16; - CONSTANT c_bsn_init : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := TO_UVEC(3, c_bsn_w); + CONSTANT c_bsn_w : NATURAL := 16; -- use <= 31 bit to fit NATURAL + CONSTANT c_bsn_init : NATURAL := 3; CONSTANT c_channel_init : INTEGER := 0; CONSTANT c_err_init : NATURAL := 247; CONSTANT c_sync_period : NATURAL := 7; CONSTANT c_sync_offset : NATURAL := 2; - CONSTANT c_block_period : NATURAL := g_block_size + g_gap_size; + CONSTANT c_gap_size : NATURAL := g_block_period - g_block_size; CONSTANT c_dut_latency : NATURAL := g_pipeline_input + g_rd_latency + 2; - CONSTANT c_align_latency : NATURAL := g_bsn_latency_max * c_block_period; - CONSTANT c_total_latency : NATURAL := c_dut_latency + c_align_latency; + CONSTANT c_align_latency_nof_valid : NATURAL := g_bsn_latency_max * g_block_size; + CONSTANT c_align_latency_nof_clk : NATURAL := g_bsn_latency_max * g_block_period; + CONSTANT c_total_latency : NATURAL := c_dut_latency + c_align_latency_nof_clk; + CONSTANT c_verify_nof_blocks : NATURAL := g_tb_nof_blocks - g_bsn_latency_max; -- skip last blocks + + TYPE t_tb_state IS (s_idle, s_start, s_restart, s_lost); TYPE t_data_arr IS ARRAY (g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); TYPE t_bsn_arr IS ARRAY (g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0); @@ -86,18 +91,18 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); END RECORD; - SIGNAL tb_end_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL tb_end_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL tb_end : STD_LOGIC; SIGNAL clk : STD_LOGIC := '1'; SIGNAL rst : STD_LOGIC := '1'; 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 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); - SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_sosi_rst); + SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); SIGNAL in_sync_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); SIGNAL in_sop_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); @@ -119,8 +124,9 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS SIGNAL r : t_reg; SIGNAL nxt_r : t_reg; - SIGNAL out_siso_arr : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy); + SIGNAL out_siso_arr : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); SIGNAL out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + SIGNAL out_sosi : t_dp_sosi; SIGNAL out_sync_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); SIGNAL out_sop_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); @@ -131,14 +137,18 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS SIGNAL out_channel_arr : t_channel_arr; SIGNAL out_err_arr : t_err_arr; + SIGNAL tb_state : t_tb_state; SIGNAL tb_bsn : INTEGER; - SIGNAL ref_sosi_arr_dly : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); - SIGNAL out_sosi_arr_exp : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); - SIGNAL verify_done_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'0'); - SIGNAL verify_en_prev_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); - SIGNAL verify_en_delayed_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); - - SIGNAL hold_out_sop_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0); + SIGNAL restart_cnt_arr : t_nat_integer_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => -1); + 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 out_sosi_arr_exp : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL out_sosi_exp : t_dp_sosi; + SIGNAL verify_done_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL verify_en_prev_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL verify_en_delayed_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 prev_out_bsn_arr : t_bsn_arr; SIGNAL expected_out_bsn_arr : t_bsn_arr; SIGNAL prev_out_data_arr : t_data_arr; @@ -147,10 +157,10 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS -- Return input delay as function of inputs stream index I FUNCTION func_input_delay(I : NATURAL) RETURN NATURAL IS BEGIN - RETURN g_diff_delay_max * I / (g_nof_streams - 1); + RETURN g_tb_diff_delay_max * I / (g_nof_streams - 1); END; - SIGNAL dbg_diff_delay_max : NATURAL := g_diff_delay_max; + SIGNAL dbg_tb_diff_delay_max : NATURAL := g_tb_diff_delay_max; SIGNAL dbg_func_delay_max : NATURAL := func_input_delay(g_nof_streams - 1); BEGIN @@ -166,35 +176,34 @@ BEGIN gen_input : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE p_stimuli : PROCESS VARIABLE v_sync : STD_LOGIC := '0'; - VARIABLE v_bsn : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := c_bsn_init; + VARIABLE v_bsn : NATURAL; VARIABLE v_data : NATURAL := c_data_init; VARIABLE v_channel : NATURAL := c_channel_init; VARIABLE v_err : NATURAL := c_err_init; - VARIABLE v_diff_bsn : NATURAL := 0; BEGIN v_data := v_data + I; ref_sosi_arr(I) <= c_dp_sosi_rst; proc_common_wait_until_low(clk, rst); proc_common_wait_some_cycles(clk, 10); - + restart_cnt_arr(I) <= restart_cnt_arr(I) + 1; + -- Begin of stimuli - FOR R IN 0 TO g_nof_repeat-v_diff_bsn-1 LOOP - v_sync := sel_a_b(TO_UINT(v_bsn) MOD c_sync_period = c_sync_offset, '1', '0'); - proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_data_w, v_data, 0, 0, g_block_size, v_channel, v_err, v_sync, v_bsn, clk, stream_en_arr(I), ref_siso_arr(I), ref_sosi_arr(I)); - v_bsn := INCR_UVEC(v_bsn, 1); - v_data := v_data + g_block_size; - proc_common_wait_some_cycles(clk, g_gap_size); -- create gap between frames + FOR S IN 0 TO g_tb_nof_restart-1 LOOP + v_bsn := c_bsn_init; + FOR R IN 0 TO g_tb_nof_blocks-1 LOOP + v_sync := sel_a_b(v_bsn MOD c_sync_period = c_sync_offset, '1', '0'); + proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_data_w, v_data, 0, 0, g_block_size, v_channel, v_err, v_sync, TO_UVEC(v_bsn, c_bsn_w), clk, stream_en_arr(I), ref_siso_arr(I), ref_sosi_arr(I)); + v_bsn := v_bsn + 1; + v_data := v_data + g_block_size; + proc_common_wait_some_cycles(clk, c_gap_size); -- create gap between frames + END LOOP; + -- 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; END LOOP; - + -- End of stimuli, g_bsn_latency_max blocks remain in DUT buffer - expected_out_bsn_arr(I) <= INCR_UVEC(v_bsn, -1 - g_bsn_latency_max); - IF func_input_delay(I) <= c_align_latency THEN - -- Verify expected input data - expected_out_data_arr(I) <= TO_UVEC(v_data-1 -g_bsn_latency_max*g_block_size, c_data_w); - ELSE - -- Verify expected replacement data for lost input block - expected_out_data_arr(I) <= TO_UVEC(g_replacement_value, c_data_w); - END IF; + expected_out_bsn_arr(I) <= TO_UVEC(v_bsn-1 - g_bsn_latency_max, c_bsn_w); + expected_out_data_arr(I) <= TO_UVEC(v_data-1 - c_align_latency_nof_valid, c_data_w); proc_common_wait_some_cycles(clk, 100); verify_done_arr(I) <= '1'; @@ -206,6 +215,17 @@ BEGIN END PROCESS; END GENERATE; + -- Use tb_state to view tb progress in Wave window + restart_cnt <= restart_cnt_arr(0); + + p_tb_state : PROCESS(restart_cnt) + BEGIN + tb_state <= s_idle; + IF restart_cnt = 0 THEN tb_state <= s_start; END IF; + IF restart_cnt = 1 THEN tb_state <= s_restart; END IF; + IF restart_cnt = 2 THEN tb_state <= s_lost; END IF; + END PROCESS; + -- Create latency misalignment between the input streams gen_in_sosi_arr : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE in_sosi_arr(I) <= TRANSPORT ref_sosi_arr(I) AFTER func_input_delay(I) * clk_period; @@ -236,25 +256,36 @@ BEGIN out_err_arr(I) <= out_sosi_arr(I).err; END GENERATE; + out_sosi <= out_sosi_arr(0); -- take out_sosi control and info from out_sosi_arr(0) + ------------------------------------------------------------------------------ -- DATA VERIFICATION, use multiple ways to increase coverage -- a) Use proc_dp_verify_*() to verify output compared to prev output -- b) Use delayed in_sosi_arr as expected out_sosi_arr ------------------------------------------------------------------------------ + tb_bsn <= TO_UINT(out_sosi.bsn); + + 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_exp <= out_sosi_arr_exp(0); -- take out_sosi_exp control and info from out_sosi_arr_exp(0) + ------------------------------------------------------------------------------ -- a) Use proc_dp_verify_() ------------------------------------------------------------------------------ p_verify_en_prev_arr : PROCESS BEGIN - verify_en_prev_arr <= (OTHERS => '0'); - IF g_diff_delay_max <= c_align_latency THEN + WAIT UNTIL rising_edge(clk); + IF g_tb_diff_delay_max <= c_align_latency_nof_clk THEN -- Can only verify incrementing sosi data when no blocks get lost - -- Skip sample of first block from verification, because then there is no prev_out_bsn_arr, prev_out_data_arr yet - proc_common_wait_until_high(clk, out_sosi_arr(0).sop); - verify_en_prev_arr <= (OTHERS => '1'); + -- Use sop to skip sample of first block from verification, because then there is no prev_out_bsn_arr, prev_out_data_arr yet + IF out_sosi_exp.sop = '1' THEN + verify_en_prev_arr <= (OTHERS => '0'); + IF TO_UINT(out_sosi_exp.bsn) - c_bsn_init < c_verify_nof_blocks THEN + verify_en_prev_arr <= (OTHERS => '1'); + END IF; + END IF; END IF; - WAIT; END PROCESS; gen_verify_prev_sosi : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE @@ -263,8 +294,8 @@ BEGIN proc_dp_verify_sop_and_eop(clk, out_val_arr(I), out_sop_arr(I), out_eop_arr(I), hold_out_sop_arr(I)); -- . Verify that the output is incrementing, like the input stimuli - proc_dp_verify_data("out_sosi.data", c_rl, clk, verify_en_prev_arr(I), out_siso_arr(I).ready, out_val_arr(I), out_data_arr(I), prev_out_data_arr(I)); - proc_dp_verify_data("out_sosi.bsn", c_rl, clk, verify_en_prev_arr(I), out_siso_arr(I).ready, out_sop_arr(I), out_bsn_arr(I), prev_out_bsn_arr(I)); + proc_dp_verify_data("out_sosi_arr().data", c_rl, clk, verify_en_prev_arr(I), out_siso_arr(I).ready, out_val_arr(I), out_data_arr(I), prev_out_data_arr(I)); + proc_dp_verify_data("out_sosi_arr().bsn", c_rl, clk, verify_en_prev_arr(I), out_siso_arr(I).ready, out_sop_arr(I), out_bsn_arr(I), prev_out_bsn_arr(I)); -- . Verify that the stimuli have been applied at all proc_dp_verify_value("out_data_arr", e_equal, clk, verify_done_arr(I), expected_out_data_arr(I), prev_out_data_arr(I)); @@ -274,19 +305,16 @@ BEGIN ------------------------------------------------------------------------------ -- b) Use delayed in_sosi_arr as expected out_sosi_arr ------------------------------------------------------------------------------ - tb_bsn <= TO_UINT(out_sosi_arr(0).bsn); - - 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); - - p_verify_en_delayed_arr : PROCESS + p_verify_en_delayed_arr : PROCESS(out_sosi_exp) BEGIN - verify_en_delayed_arr <= (OTHERS => '1'); - -- Skip last blocks that are still in DUT buffer - proc_common_wait_until_value(TO_UINT(c_bsn_init) + g_nof_repeat - g_bsn_latency_max - 1, clk, tb_bsn); - proc_common_wait_until_high(clk, out_sosi_arr(0).eop); - verify_en_delayed_arr <= (OTHERS => '0'); - WAIT; + IF g_tb_diff_delay_max <= c_align_latency_nof_clk THEN + -- Can only verify incrementing sosi data when no blocks get lost + -- Skip sample of first block from verification, because then there is no prev_out_bsn_arr, prev_out_data_arr yet + verify_en_delayed_arr <= (OTHERS => '1'); + IF TO_UINT(out_sosi_exp.bsn) - c_bsn_init >= c_verify_nof_blocks THEN + verify_en_delayed_arr <= (OTHERS => '0'); + END IF; + END IF; END PROCESS; gen_verify_delayed_sosi : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE @@ -298,17 +326,9 @@ 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).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; - IF func_input_delay(I) <= c_align_latency THEN - -- Verify expected input data - 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_exp(I).data)) SEVERITY ERROR; - ELSE - -- Verify expected replacement data for lost input block - ASSERT TO_UINT(out_sosi_arr(I).data) = g_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(g_replacement_value) SEVERITY ERROR; - END IF; + 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_exp(I).data)) SEVERITY ERROR; END IF; END IF; END PROCESS; -- GitLab