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

Use g_tb_nof_restart. Added verify_en_delayed_arr using out_sosi_arr_exp....

Use g_tb_nof_restart. Added verify_en_delayed_arr using out_sosi_arr_exp. Improved out_sosi_arr_exp.
parent 70eb1406
No related branches found
No related tags found
1 merge request!156Added first version of dp_bsn_align_v2.vhd with mmp and tb. This was...
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment