From ba11989df668b934ffcef99a4184940cbeca18a0 Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Tue, 15 Aug 2023 15:17:31 +0200 Subject: [PATCH] Verify dynamic reorder control. Verify g_inter_valid_gap. --- .../tb/vhdl/tb_reorder_col_select_all.vhd | 258 ++++++++++++++---- .../tb/vhdl/tb_tb_reorder_col_select_all.vhd | 24 +- 2 files changed, 222 insertions(+), 60 deletions(-) diff --git a/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd b/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd index 8701d6a9ca..8b4640ebd3 100644 --- a/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd +++ b/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd @@ -21,13 +21,25 @@ ------------------------------------------------------------------------------- -- Author : E. Kooistra -- Purpose: --- Verify reorder_col_select using two instances and selects all inputdata. +-- Verify reorder_col_select using two instances and select all input data, +-- so that second instance can restore the original input data order. -- Description: -- The second reorder_col_select instances undo's the reordering of the -- first reorder_col_select instance. All data in the input block is used, -- so that the output of the second reorder_col_select instance is equal --- to the tb input data, except for a delay, so that the output data can --- easily be verified. +-- to the tb input data, except for a delay and data valid gaps. +-- The data and info fields are incrementing, so that the out_sosi can be +-- verified with dp_stream_verify. +-- +-- p_comb_transpose p_comb_undo_transpose +-- | | +-- ____v_____ ____v_____ +-- |reorder | |reorder | +-- p_st_stimuli -->|col_select|------->|col_select|--> p_verify +-- |__________| |__________| +-- in_sosi transposed_sosi out_sosi +-- nof_ch_input nof_ch_transposed nof_ch_output +-- -- Remark: -- * Development order from basic functionality to all verifying features: -- . verify reorder 1 packet @@ -38,12 +50,16 @@ -- designs. -- . verify reorder multiple packets with and without interpacket gaps -- . verify g_use_complex --- . verify all sosi fields using proc_dp_verify_sosi_equal() +-- . verify all sosi fields using dp_stream_verify. Cannot use delayed +-- in_sosi and proc_dp_verify_sosi_equal(), because the out_sosi does +-- not have data valid gaps within a packet. -- . add tb_tb_reorder_col_select_all --- . verify dynamic change of nof_blocks_per_packet, nof_data_per_block +-- . verify dynamic change of nof_blocks_per_packet, nof_data_per_block. +-- . only support changing the nof_ch_in and nof_ch_sel when the no +-- reordering is busy. -- -- Usage: --- > as 10 +-- > as 8 -- > run -all -- * The tb is self stopping and self checking, tb_end will stop the simulation -- by stopping the clk and thus all toggling. @@ -61,12 +77,14 @@ use work.reorder_pkg.all; entity tb_reorder_col_select_all is generic( g_dsp_data_w : natural := 16; -- complex data width, = c_data_w / 2 - g_nof_sync : natural := 1; + g_nof_sync : natural := 5; g_nof_packets_per_sync : natural := 3; g_nof_blocks_per_packet : natural := 5; g_nof_data_per_block : natural := 3; - g_inter_packet_gap : natural := 0; - g_use_complex : boolean := false + g_inter_valid_gap : natural := 0; -- nof clk gap in in_sosi.valid + g_inter_packet_gap : natural := 3; -- nof clk gap betweek in_sosi.eop and next in_sosi.sop + g_use_complex : boolean := false; + g_use_dynamic_selection : boolean := false ); end tb_reorder_col_select_all; @@ -76,33 +94,53 @@ architecture tb of tb_reorder_col_select_all is constant c_clk_period : time := 10 ns; constant c_rl : natural := 1; - constant c_use_data : boolean := not g_use_complex; - constant c_data_w : natural := c_nof_complex * g_dsp_data_w; - constant c_nof_ch : natural := g_nof_blocks_per_packet * g_nof_data_per_block; + constant c_use_data : boolean := not g_use_complex; + constant c_data_w : natural := c_nof_complex * g_dsp_data_w; - constant c_nof_blocks_max : natural:= largest(g_nof_blocks_per_packet, g_nof_data_per_block) + 1; - constant c_addr_max : natural := c_nof_ch + c_nof_blocks_max; - constant c_cnt_max : natural := c_nof_blocks_max; + -- Match c_nof_sync with p_nof_ch_stimuli + constant c_nof_sync : natural := sel_a_b(g_use_dynamic_selection, 2, g_nof_sync); + constant c_factor_blk : natural := sel_a_b(g_use_dynamic_selection, 2, 1); -- factor for more blocks per packet + constant c_factor_dat : natural := sel_a_b(g_use_dynamic_selection, 1, 1); -- factor for more data per block + constant c_factor_ch : natural := c_factor_blk * c_factor_dat; -- factor for more data per packet + constant c_nof_ch : natural := g_nof_blocks_per_packet * g_nof_data_per_block; + constant c_nof_ch_long : natural := c_nof_ch * c_factor_ch; + constant c_sel_gap : natural := c_nof_ch_long * 2; -- Total output latency for transpose and undo transpose - constant c_retrieve_lat : natural := 2; -- rd latency of reorder_col_select - constant c_output_lat : natural := (c_nof_ch + c_retrieve_lat) * 2; + constant c_retrieve_lat : natural := 2; -- rd latency of reorder_col_select + constant c_output_lat : natural := (c_nof_ch + c_retrieve_lat) * 2; + constant c_output_lat_long : natural := (c_nof_ch_long + c_retrieve_lat) * 2; signal rst : std_logic; signal clk : std_logic := '1'; signal tb_end : std_logic := '0'; + signal verify_en_sosi : t_dp_sosi_sl; + signal verify_en_out_sosi : t_dp_sosi_sl; + signal verify_en_out_sosi_long : t_dp_sosi_sl; + -- Data signal in_en : std_logic := '1'; signal in_sosi : t_dp_sosi := c_dp_sosi_rst; signal in_siso : t_dp_siso := c_dp_siso_rdy; -- used for proc_dp_gen_block_data signal transposed_sosi : t_dp_sosi; signal out_sosi : t_dp_sosi; - signal in_sosi_dly : t_dp_sosi := c_dp_sosi_rst; - signal expected_sosi : t_dp_sosi := c_dp_sosi_rst; - -- Reorder and undo reorder control - signal nof_ch : natural range 0 to c_nof_ch := c_nof_ch; + -- Reorder control for transpose and undo transpose + signal sel_long : boolean := false; + signal reorder_busy_transposed : std_logic; + signal reorder_busy_output : std_logic; + signal reorder_busy : std_logic; + signal nof_ch_input : natural := c_nof_ch; + signal nof_ch_transposed : natural; + signal nof_ch_output : natural; + signal nof_blocks_per_packet_input : natural := g_nof_blocks_per_packet; + signal nof_blocks_per_packet_transposed : natural; + signal nof_blocks_per_packet_output : natural; + signal nof_data_per_block_input : natural := g_nof_data_per_block; + signal nof_data_per_block_transposed : natural; + signal nof_data_per_block_output : natural; + signal select_cipo : t_mem_cipo; signal undo_select_cipo : t_mem_cipo; signal r_transpose : t_reorder_transpose; @@ -115,11 +153,20 @@ begin clk <= (not clk) or tb_end after c_clk_period / 2; rst <= '1', '0' after c_clk_period * 7; + -- Pulse in_en to control in_sosi.valid + proc_common_gen_pulse(1, 1 + g_inter_valid_gap, '1', rst, clk, in_en); + + -- Dynamic reorder control + nof_ch_input <= sel_a_b(sel_long, c_nof_ch_long, c_nof_ch); + -- Input data packets stimuli p_st_stimuli : process - variable v_bsn : std_logic_vector(31 downto 0) := (others => '0'); - variable v_data : natural := 0; + variable v_nof_ch : natural := c_nof_ch; + variable v_bsn : std_logic_vector(31 downto 0) := (others => '0'); + variable v_info : natural := 0; + variable v_data : natural := 0; begin + sel_long <= false; proc_common_wait_until_low(clk, rst); proc_common_wait_some_cycles(clk, 5); @@ -141,8 +188,9 @@ begin -- 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); - for I in 0 to g_nof_sync - 1 loop + for I in 0 to c_nof_sync - 1 loop -- First packet in sync interval + v_nof_ch := nof_ch_input; proc_dp_gen_block_data(c_rl, c_use_data, g_dsp_data_w, @@ -150,9 +198,9 @@ begin v_data, -- data v_data, -- re v_data + 1, -- im - c_nof_ch, - v_data + 2, -- channel - v_data + 3, -- error + v_nof_ch, + v_info + 2, -- channel + v_info + 3, -- error '1', -- with sync v_bsn, -- bsn clk, @@ -162,8 +210,10 @@ begin proc_common_wait_some_cycles(clk, g_inter_packet_gap); for J in 0 to g_nof_packets_per_sync - 2 loop -- Next packets in sync interval + v_nof_ch := nof_ch_input; v_bsn := INCR_UVEC(v_bsn, 1); - v_data := v_data + c_nof_ch; + v_info := v_info + 1; + v_data := v_data + v_nof_ch; proc_dp_gen_block_data(c_rl, c_use_data, g_dsp_data_w, @@ -171,9 +221,9 @@ begin v_data, -- data v_data, -- re v_data + 1, -- im - c_nof_ch, - v_data + 2, -- channel - v_data + 3, -- error + v_nof_ch, + v_info + 2, -- channel + v_info + 3, -- error '0', -- no sync v_bsn, -- bsn clk, @@ -182,9 +232,19 @@ begin in_sosi); proc_common_wait_some_cycles(clk, g_inter_packet_gap); end loop; + v_bsn := INCR_UVEC(v_bsn, 1); + v_info := v_info + 1; + v_data := v_data + v_nof_ch; + + if g_use_dynamic_selection then + -- Toggle dynamic reorder control + proc_common_wait_until_low(clk, reorder_busy); + sel_long <= not sel_long; + proc_common_wait_some_cycles(clk, 1); + end if; end loop; in_sosi <= c_dp_sosi_rst; - proc_common_wait_some_cycles(clk, c_nof_ch * 2); + proc_common_wait_some_cycles(clk, c_nof_ch_long * 2); proc_common_wait_some_cycles(clk, 10); tb_end <= '1'; wait; @@ -194,31 +254,104 @@ begin -- Verification ------------------------------------------------------------------------------ - in_sosi_dly <= transport in_sosi after c_output_lat * c_clk_period; - expected_sosi <= in_sosi_dly when rising_edge(clk); - - p_verify : process(rst, clk) + p_verify_en_sosi : process begin - if rst = '1' then - elsif rising_edge(clk) then - proc_dp_verify_sosi_equal(g_use_complex, out_sosi, expected_sosi); + verify_en_sosi <= c_dp_sosi_sl_rst; + proc_common_wait_until_low(clk, rst); + + -- Verify all sosi fields, except for some + verify_en_sosi <= c_dp_sosi_sl_ones; + if g_use_complex then + verify_en_sosi.data <= '0'; + else + verify_en_sosi.re <= '0'; + verify_en_sosi.im <= '0'; end if; + verify_en_sosi.empty <= '0'; + wait; end process; + verify_en_out_sosi <= verify_en_sosi when sel_long = false else c_dp_sosi_sl_rst; + verify_en_out_sosi_long <= verify_en_sosi when sel_long = true else c_dp_sosi_sl_rst; + + u_verify_out_sosi : entity dp_lib.dp_stream_verify + generic map ( + -- initializations + g_sync_period => g_nof_packets_per_sync, -- BSN increment per sync interval + g_sync_offset => 0, -- first BSN + -- specific + g_in_dat_w => c_data_w, + g_pkt_len => c_nof_ch + ) + port map ( + rst => rst, + clk => clk, + -- Verify data + snk_in => out_sosi, + -- During stimuli + verify_snk_in_enable => verify_en_out_sosi, + + -- End of stimuli + expected_snk_in => c_dp_sosi_rst, + verify_expected_snk_in_evt => c_dp_sosi_sl_rst + ); + + -- When g_use_dynamic_selection = true then c_nof_sync = 2 and second sync interval + -- will contain the long packets. All sync intervals have g_nof_packets_per_sync. + -- The first sync interval will start with BSN = g_sync_offset = 0, so the second + -- sync interval with the long packets, will start with BSN = g_sync_offset = + -- g_nof_packets_per_sync. + u_verify_out_sosi_long : entity dp_lib.dp_stream_verify + generic map ( + -- initializations + g_sync_period => g_nof_packets_per_sync, + g_sync_offset => g_nof_packets_per_sync, + -- specific + g_in_dat_w => c_data_w, + g_pkt_len => c_nof_ch_long + ) + port map ( + rst => rst, + clk => clk, + -- Verify data + snk_in => out_sosi, + -- During stimuli + verify_snk_in_enable => verify_en_out_sosi_long, + + -- End of stimuli + expected_snk_in => c_dp_sosi_rst, + verify_expected_snk_in_evt => c_dp_sosi_sl_rst + ); + ------------------------------------------------------------------------------ -- DUT ------------------------------------------------------------------------------ - r_transpose <= d_transpose when rising_edge(clk); - r_undo_transpose <= d_undo_transpose when rising_edge(clk); + + p_clk : process(rst, clk) + begin + if rst = '1' then + r_transpose <= c_reorder_transpose_rst; + r_undo_transpose <= c_reorder_transpose_rst; + elsif rising_edge(clk) then + r_transpose <= d_transpose; + r_undo_transpose <= d_undo_transpose; + end if; + end process; -- The p_comb_transpose and p_comb_undo_transpose can both use -- func_reorder_transpose(), by swapping the transpose dimensions. + + nof_blocks_per_packet_input <= g_nof_blocks_per_packet when nof_ch_input = c_nof_ch else + g_nof_blocks_per_packet * c_factor_blk; + nof_data_per_block_input <= g_nof_data_per_block when nof_ch_input = c_nof_ch else + g_nof_data_per_block * c_factor_dat; + p_comb_transpose : process(rst, r_transpose, select_cipo) variable v : t_reorder_transpose; begin if select_cipo.waitrequest = '0' then -- Read from reorder_col_select page - v := func_reorder_transpose(g_nof_data_per_block, g_nof_blocks_per_packet, r_transpose); + v := func_reorder_transpose(nof_data_per_block_input, nof_blocks_per_packet_input, r_transpose); else -- No read, new reorder_col_select page not available yet v := c_reorder_transpose_rst; @@ -230,12 +363,17 @@ begin d_transpose <= v; end process; + nof_blocks_per_packet_transposed <= g_nof_blocks_per_packet when nof_ch_transposed = c_nof_ch else + g_nof_blocks_per_packet * c_factor_blk; + nof_data_per_block_transposed <= g_nof_data_per_block when nof_ch_transposed = c_nof_ch else + g_nof_data_per_block * c_factor_dat; + p_comb_undo_transpose : process(rst, r_undo_transpose, undo_select_cipo) variable v : t_reorder_transpose; begin if undo_select_cipo.waitrequest = '0' then -- Read from reorder_col_select page - v := func_reorder_transpose(g_nof_blocks_per_packet, g_nof_data_per_block, r_undo_transpose); + v := func_reorder_transpose(nof_blocks_per_packet_transposed, nof_data_per_block_transposed, r_undo_transpose); else -- No read, new reorder_col_select page not available yet v := c_reorder_transpose_rst; @@ -247,20 +385,31 @@ begin d_undo_transpose <= v; end process; + nof_blocks_per_packet_output <= g_nof_blocks_per_packet when nof_ch_output = c_nof_ch else + g_nof_blocks_per_packet * c_factor_blk; + nof_data_per_block_output <= g_nof_data_per_block when nof_ch_output = c_nof_ch else + g_nof_data_per_block * c_factor_dat; + u_transpose : entity work.reorder_col_select generic map ( g_dsp_data_w => g_dsp_data_w, - g_nof_ch_in => c_nof_ch, - g_nof_ch_sel => c_nof_ch, + g_nof_ch_in => c_nof_ch_long, + g_nof_ch_sel => c_nof_ch_long, g_use_complex => g_use_complex ) port map ( dp_rst => rst, dp_clk => clk, + reorder_busy => reorder_busy_transposed, + -- Dynamic reorder block size control - nof_ch_in => nof_ch, - nof_ch_sel => nof_ch, + nof_ch_in => nof_ch_input, + nof_ch_sel => nof_ch_input, + + -- Captured reorder block size control used for output_sosi + output_nof_ch_in => nof_ch_transposed, + output_nof_ch_sel => open, -- Memory Mapped col_select_mosi => r_transpose.select_copi, @@ -274,17 +423,23 @@ begin u_undo_transpose : entity work.reorder_col_select generic map ( g_dsp_data_w => g_dsp_data_w, - g_nof_ch_in => c_nof_ch, - g_nof_ch_sel => c_nof_ch, + g_nof_ch_in => c_nof_ch_long, + g_nof_ch_sel => c_nof_ch_long, g_use_complex => g_use_complex ) port map ( dp_rst => rst, dp_clk => clk, + reorder_busy => reorder_busy_output, + -- Dynamic reorder block size control - nof_ch_in => nof_ch, - nof_ch_sel => nof_ch, + nof_ch_in => nof_ch_transposed, + nof_ch_sel => nof_ch_transposed, + + -- Captured reorder block size control used for output_sosi + output_nof_ch_in => nof_ch_output, + output_nof_ch_sel => open, -- Memory Mapped col_select_mosi => r_undo_transpose.select_copi, @@ -295,4 +450,5 @@ begin output_sosi => out_sosi ); + reorder_busy <= reorder_busy_transposed or reorder_busy_output; end tb; diff --git a/libraries/base/reorder/tb/vhdl/tb_tb_reorder_col_select_all.vhd b/libraries/base/reorder/tb/vhdl/tb_tb_reorder_col_select_all.vhd index 7f25104d31..bd66fd81f0 100644 --- a/libraries/base/reorder/tb/vhdl/tb_tb_reorder_col_select_all.vhd +++ b/libraries/base/reorder/tb/vhdl/tb_tb_reorder_col_select_all.vhd @@ -38,17 +38,23 @@ architecture tb of tb_tb_reorder_col_select_all is begin -- g_dsp_data_w : natural := 16; -- complex data width, = c_data_w / 2 --- g_nof_sync : natural := 1; +-- g_nof_sync : natural := 2; -- g_nof_packets_per_sync : natural := 3; -- g_nof_blocks_per_packet : natural := 5; -- g_nof_data_per_block : natural := 3; --- g_inter_packet_gap : natural := 0; --- g_use_complex : boolean := false - - u_complex_5_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 2, 5, 3, 0, true); - u_data_5_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 3, 5, 3, 0, false); - u_data_5_1_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 4, 5, 1, 0, false); - u_data_1_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 5, 1, 3, 0, false); - u_data_3_5_gap_1 : entity work.tb_reorder_col_select_all generic map(16, 3, 6, 3, 5, 1, false); +-- g_inter_valid_gap : natural := 5; -- nof clk gap in in_sosi.valid +-- g_inter_packet_gap : natural := 0; -- nof clk gap between in_sosi.eop and next in_sosi.sop +-- g_use_complex : boolean := false; +-- g_use_dynamic_selection : boolean := true + + u_complex_5_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 2, 5, 3, 0, 0, true, false); + u_data_5_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 3, 5, 3, 0, 0, false, false); + u_data_5_1_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 4, 5, 1, 0, 0, false, false); + u_data_1_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 5, 1, 3, 0, 0, false, false); + u_data_3_5_pkt_gap_1 : entity work.tb_reorder_col_select_all generic map(16, 3, 6, 3, 5, 0, 1, false, false); + u_data_3_5_valid_gap_1 : entity work.tb_reorder_col_select_all generic map(16, 3, 6, 3, 5, 1, 0, false, false); + + u_dynamic_data_5_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 3, 5, 3, 0, 0, false, true); + u_dynamic_data_5_3_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 3, 5, 3,10,100, false, true); end tb; -- GitLab