From 8a5b91d26d9dfc9624db23fb3b16be6de6923e98 Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Mon, 27 Mar 2023 17:21:15 +0200 Subject: [PATCH] Verify dp_rsn_source.vhd in multi tb_tb. --- libraries/base/dp/hdllib.cfg | 2 + libraries/base/dp/src/vhdl/dp_rsn_source.vhd | 62 +++-- .../base/dp/tb/vhdl/tb_dp_rsn_source.vhd | 259 ++++++++++++------ .../base/dp/tb/vhdl/tb_tb_dp_rsn_source.vhd | 4 +- 4 files changed, 207 insertions(+), 120 deletions(-) diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index db256bdb9c..48865ad1db 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -308,6 +308,7 @@ test_bench_files = tb/vhdl/tb_tb_dp_bsn_align.vhd tb/vhdl/tb_tb_dp_bsn_align_v2.vhd tb/vhdl/tb_tb_mmp_dp_bsn_align_v2.vhd + tb/vhdl/tb_tb_dp_rsn_source.vhd tb/vhdl/tb_tb_dp_bsn_source_v2.vhd tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd tb/vhdl/tb_tb_dp_concat.vhd @@ -382,6 +383,7 @@ regression_test_vhdl = tb/vhdl/tb_tb_dp_block_validate_channel.vhd tb/vhdl/tb_tb_dp_bsn_align_v2.vhd tb/vhdl/tb_tb_mmp_dp_bsn_align_v2.vhd + tb/vhdl/tb_tb_dp_rsn_source.vhd tb/vhdl/tb_tb_dp_bsn_source_v2.vhd tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd tb/vhdl/tb_tb_dp_concat.vhd diff --git a/libraries/base/dp/src/vhdl/dp_rsn_source.vhd b/libraries/base/dp/src/vhdl/dp_rsn_source.vhd index 2fe9e62030..61ec23f9df 100644 --- a/libraries/base/dp/src/vhdl/dp_rsn_source.vhd +++ b/libraries/base/dp/src/vhdl/dp_rsn_source.vhd @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------- -- --- Copyright 2022 +-- Copyright 2023 -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -- @@ -32,11 +32,12 @@ -- The bs_sosi can stop and restart. It (re)starts with bs_sosi.sync and -- bs_sosi.sop when bs_sosi.valid becomes '1' and it stops when -- bs_sosi.valid becomes '0' immediately after a bs_sosi.eop. --- The rs_sosi block size is g_block_size. +-- The rs_sosi block size is g_rs_block_size. -- The rs_sosi sync interval has g_nof_clk_per_sync. If g_nof_clk_per_sync --- is not a multiple of g_block_size, then the rs_sosi.sync will occur at +-- is not a multiple of g_rs_block_size, then the rs_sosi.sync will occur at -- the next start of block. --- The initial RSN in rs_sosi.bsn is bs_sosi.bsn * g_block_size. +-- The initial RSN in rs_sosi.bsn is bs_sosi.bsn * g_bs_block_size, where +-- g_bs_block_size is the input block size of bs_sosi. -- The rs_sosi starts when the bs_sosi starts, so when bs_sosi.sync = '1' -- and bs_sosi.valid becomes '1'. -- The rs_sosi ends after the rs_sosi.eop, when the bs_sosi ends. There @@ -56,7 +57,8 @@ USE work.dp_stream_pkg.ALL; ENTITY dp_rsn_source IS GENERIC ( - g_block_size : NATURAL := 256; -- >= 3, see state machine + g_bs_block_size : NATURAL := 256; -- input bs_sosi block size, >= 3, see state machine + g_rs_block_size : NATURAL := 256; -- output rs_sosi block size, >= 3, see state machine g_nof_clk_per_sync : NATURAL := 200 * 10**6; g_bsn_w : NATURAL := 64 ); @@ -69,7 +71,7 @@ ENTITY dp_rsn_source IS -- Output stream sosi control using RSN nof_clk_per_sync : IN STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0) := TO_UVEC(g_nof_clk_per_sync, c_word_w); - rs_sosi : OUT t_dp_sosi; -- output stream using RSN and g_block_size, g_nof_clk_per_sync + rs_sosi : OUT t_dp_sosi; -- output stream using RSN and g_rs_block_size, g_nof_clk_per_sync rs_restart : OUT STD_LOGIC; -- = rs_sosi.sync for first sync after bs_sosi.valid went high rs_new_interval : OUT STD_LOGIC -- = active during first rs_sosi.sync interval ); @@ -78,8 +80,9 @@ END dp_rsn_source; ARCHITECTURE rtl OF dp_rsn_source IS - CONSTANT c_block_size_cnt_w : NATURAL := ceil_log2(g_block_size); - CONSTANT c_rsn_product_w : NATURAL := g_bsn_w + c_block_size_cnt_w; + CONSTANT c_bs_block_size_cnt_w : NATURAL := ceil_log2(g_bs_block_size) + 1; -- +1 because value 2**n requires n + 1 bits + CONSTANT c_rs_block_size_cnt_w : NATURAL := ceil_log2(g_rs_block_size) + 1; -- +1 because value 2**n requires n + 1 bits + CONSTANT c_rsn_product_w : NATURAL := g_bsn_w + c_bs_block_size_cnt_w; TYPE t_state_enum IS (s_off, s_on_sop, s_on, s_on_eop); @@ -91,11 +94,11 @@ ARCHITECTURE rtl OF dp_rsn_source IS SIGNAL nxt_sync : STD_LOGIC; SIGNAL sync : STD_LOGIC; - SIGNAL nxt_sync_size_cnt : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); SIGNAL sync_size_cnt : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL nxt_sync_size_cnt : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); - SIGNAL block_size_cnt : STD_LOGIC_VECTOR(c_block_size_cnt_w-1 DOWNTO 0); - SIGNAL nxt_block_size_cnt : STD_LOGIC_VECTOR(c_block_size_cnt_w-1 DOWNTO 0); + SIGNAL rs_block_size_cnt : STD_LOGIC_VECTOR(c_rs_block_size_cnt_w-1 DOWNTO 0); + SIGNAL nxt_rs_block_size_cnt : STD_LOGIC_VECTOR(c_rs_block_size_cnt_w-1 DOWNTO 0); SIGNAL i_rs_sosi : t_dp_sosi := c_dp_sosi_init; SIGNAL nxt_rs_sosi : t_dp_sosi; @@ -111,11 +114,11 @@ BEGIN rs_restart <= i_rs_restart; rs_new_interval <= i_rs_new_interval; - rsn <= MULT_UVEC(bs_sosi.bsn(g_bsn_w-1 DOWNTO 0), TO_UVEC(g_block_size, c_block_size_cnt_w)); + rsn <= MULT_UVEC(bs_sosi.bsn(g_bsn_w-1 DOWNTO 0), TO_UVEC(g_bs_block_size, c_bs_block_size_cnt_w)); - p_state : PROCESS(bs_sosi, sync, sync_size_cnt, nof_clk_per_sync, + p_state : PROCESS(bs_sosi, nxt_sync, sync, sync_size_cnt, nof_clk_per_sync, state, prev_state, - i_rs_sosi, block_size_cnt, rsn) + i_rs_sosi, rs_block_size_cnt, rsn) BEGIN -- Maintain sync_size_cnt for nof_clk_per_sync -- . nof_clk_per_sync is the number of clk per sync interval and the @@ -131,6 +134,9 @@ BEGIN nxt_sync <= '1'; -- will set rs_sosi.sync on next rs_sosi.sop nxt_sync_size_cnt <= (OTHERS=>'0'); END IF; + IF i_rs_sosi.sync = '1' THEN + nxt_sync <= '0'; -- clear when sync has been applied in rs_sosi + END IF; -- State machine for rs_sosi nxt_state <= state; @@ -139,7 +145,7 @@ BEGIN nxt_rs_sosi.valid <= '0'; nxt_rs_sosi.sop <= '0'; nxt_rs_sosi.eop <= '0'; - nxt_block_size_cnt <= block_size_cnt; + nxt_rs_block_size_cnt <= rs_block_size_cnt; CASE state IS WHEN s_off => @@ -147,7 +153,7 @@ BEGIN nxt_rs_sosi.bsn <= RESIZE_DP_BSN(rsn); -- RSN fits in g_bsn_w nxt_sync <= '0'; nxt_sync_size_cnt <= (OTHERS=>'0'); - nxt_block_size_cnt <= (OTHERS=>'0'); + nxt_rs_block_size_cnt <= (OTHERS=>'0'); IF bs_sosi.sync = '1' THEN nxt_rs_sosi.sync <= '1'; nxt_rs_sosi.sop <= '1'; @@ -156,31 +162,30 @@ BEGIN END IF; -- using separate states s_on_sop and s_on_eop instead of only - -- s_on state and block_size_cnt, cause that g_block_size must be + -- s_on state and rs_block_size_cnt, cause that g_rs_block_size must be -- >= 3, but that is fine. WHEN s_on_sop => -- Start of block nxt_rs_sosi.sop <= '1'; nxt_rs_sosi.valid <= '1'; nxt_state <= s_on; - -- block_size_cnt = 0 at rs_sosi.sop - nxt_block_size_cnt <= (OTHERS=>'0'); + -- rs_block_size_cnt = 0 at rs_sosi.sop + nxt_rs_block_size_cnt <= (OTHERS=>'0'); -- after first block, increment bsn per block IF prev_state = s_on_eop THEN - nxt_rs_sosi.bsn <= INCR_DP_BSN(i_rs_sosi.bsn, g_block_size, g_bsn_w); -- RSN + nxt_rs_sosi.bsn <= INCR_DP_BSN(i_rs_sosi.bsn, g_rs_block_size, g_bsn_w); -- RSN END IF; -- check for pending sync - IF sync = '1' THEN + IF nxt_sync = '1' THEN nxt_rs_sosi.sync <= '1'; - nxt_sync <= '0'; END IF; WHEN s_on => -- During block nxt_rs_sosi.valid <= '1'; - -- block_size_cnt increments to determine end of block - nxt_block_size_cnt <= INCR_UVEC(block_size_cnt, 1); - IF UNSIGNED(block_size_cnt) >= g_block_size - 3 THEN + -- rs_block_size_cnt increments to determine end of block + nxt_rs_block_size_cnt <= INCR_UVEC(rs_block_size_cnt, 1); + IF UNSIGNED(rs_block_size_cnt) >= g_rs_block_size - 3 THEN nxt_state <= s_on_eop; END IF; @@ -189,7 +194,8 @@ BEGIN nxt_rs_sosi.eop <= '1'; nxt_rs_sosi.valid <= '1'; nxt_state <= s_on_sop; - -- block_size_cnt is dont care at at rs_sosi.eop + nxt_rs_block_size_cnt <= INCR_UVEC(rs_block_size_cnt, 1); + -- rs_block_size_cnt is dont care at at rs_sosi.eop -- accept dp_off after eop, to avoid fractional blocks IF bs_sosi.valid = '0' THEN nxt_state <= s_off; @@ -216,7 +222,7 @@ BEGIN i_rs_sosi <= c_dp_sosi_rst; sync_size_cnt <= (OTHERS=>'0'); sync <= '0'; - block_size_cnt <= (OTHERS=>'0'); + rs_block_size_cnt <= (OTHERS=>'0'); i_rs_restart <= '0'; reg_rs_new_interval <= '0'; ELSIF rising_edge(clk) THEN @@ -225,7 +231,7 @@ BEGIN i_rs_sosi <= nxt_rs_sosi; sync_size_cnt <= nxt_sync_size_cnt; sync <= nxt_sync; - block_size_cnt <= nxt_block_size_cnt; + rs_block_size_cnt <= nxt_rs_block_size_cnt; i_rs_restart <= nxt_rs_restart; reg_rs_new_interval <= i_rs_new_interval; END IF; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_rsn_source.vhd b/libraries/base/dp/tb/vhdl/tb_dp_rsn_source.vhd index 774c0fe8f1..b1521fa311 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_rsn_source.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_rsn_source.vhd @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------- -- --- Copyright 2022 +-- Copyright 2023 -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -- @@ -24,7 +24,10 @@ -- Use dp_bsn_source_v2 to create bs_sosi and extending it with dut = -- dp_rsn_source to create and verify rs_sosi. -- Remark: --- * This tb is made based on tb_dp_bsn_source_v2. +-- * This tb is made based on tb_dp_bsn_source_v2. Difference is that bs_sosi +-- has block grid that starts at t_epoch = 0, whereas rs_sosi has block +-- grid that can start at any bs_sosi.sync. Therefore p_exp_grid_rs is +-- needed LIBRARY IEEE, common_lib, dp_lib; USE IEEE.STD_LOGIC_1164.ALL; @@ -36,9 +39,9 @@ USE dp_lib.tb_dp_pkg.ALL; ENTITY tb_dp_rsn_source IS GENERIC ( - g_pps_interval : NATURAL := 16; --101; - g_bs_block_size : NATURAL := 5; --23 - g_rs_block_size : NATURAL := 5 --23 + g_pps_interval : NATURAL := 40; --101; + g_bs_block_size : NATURAL := 10; --23, input BSN block size <= g_pps_interval + g_rs_block_size : NATURAL := 10 --23, output RSN block size <= g_pps_interval ); END tb_dp_rsn_source; @@ -62,7 +65,7 @@ ARCHITECTURE tb OF tb_dp_rsn_source IS -- choose c_nof_pps and c_nof_repeat > c_min_nof_pps_interval, because the -- fractional sync pattern will repeat every c_min_nof_pps_interval number -- of g_pps_intervals. - CONSTANT c_factor : NATURAL := 3; + CONSTANT c_factor : NATURAL := 5; CONSTANT c_nof_pps : NATURAL := c_min_nof_pps_interval * c_factor; CONSTANT c_nof_repeat : NATURAL := c_min_nof_pps_interval * c_factor; @@ -71,7 +74,9 @@ ARCHITECTURE tb OF tb_dp_rsn_source IS CONSTANT c_bsn_time_offset_w : NATURAL := ceil_log2(g_bs_block_size); -- Minimum latency between sync and PPS, due to logic in DUT - CONSTANT c_dut_latency : NATURAL := 3; + CONSTANT c_dp_bsn_latency : NATURAL := 3; + CONSTANT c_dp_rsn_latency : NATURAL := 1; + CONSTANT c_dut_latency : NATURAL := c_dp_bsn_latency + c_dp_rsn_latency; -- The state name tells what kind of test is being done TYPE t_state_enum IS ( @@ -90,45 +95,51 @@ ARCHITECTURE tb OF tb_dp_rsn_source IS eop : STD_LOGIC; -- end of block END RECORD; - CONSTANT c_time_grid_rst : t_time_grid := ('0', 0, 0, '0', '0', '0'); + CONSTANT c_time_grid_rst : t_time_grid := ('0', 0, 0, '0', '0', '0'); -- Reference grid - SIGNAL ref_grid : t_time_grid := c_time_grid_rst; - SIGNAL ssn_eop : STD_LOGIC := '0'; - SIGNAL hold_pps : STD_LOGIC := '0'; - SIGNAL nxt_hold_pps : STD_LOGIC := '0'; + SIGNAL ref_grid_bs : t_time_grid := c_time_grid_rst; + SIGNAL ssn_eop : STD_LOGIC := '0'; + SIGNAL hold_pps : STD_LOGIC := '0'; + SIGNAL nxt_hold_pps : STD_LOGIC := '0'; -- Tb - SIGNAL tb_end : STD_LOGIC := '0'; - SIGNAL rst : STD_LOGIC := '1'; - SIGNAL clk : STD_LOGIC := '1'; - SIGNAL tb_state : t_state_enum := s_disable; + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL rst : STD_LOGIC := '1'; + SIGNAL clk : STD_LOGIC := '1'; + SIGNAL tb_state : t_state_enum := s_disable; -- BSN source - SIGNAL dp_on : STD_LOGIC := '0'; - SIGNAL dp_on_pps : STD_LOGIC := '0'; - SIGNAL dp_on_status : STD_LOGIC; - SIGNAL bs_restart : STD_LOGIC; - SIGNAL bs_new_interval : STD_LOGIC; - SIGNAL tb_new_interval : STD_LOGIC := '0'; - SIGNAL bsn_init : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := (OTHERS=>'0'); - SIGNAL bsn_time_offset : STD_LOGIC_VECTOR(c_bsn_time_offset_w-1 DOWNTO 0) := (OTHERS=>'0'); - SIGNAL bs_sosi : t_dp_sosi; + SIGNAL dp_on : STD_LOGIC := '0'; + SIGNAL dp_on_pps : STD_LOGIC := '0'; + SIGNAL dp_on_status : STD_LOGIC; + SIGNAL bs_restart : STD_LOGIC; + SIGNAL bs_new_interval : STD_LOGIC; + SIGNAL tb_new_interval : STD_LOGIC := '0'; + SIGNAL bsn_init : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL bsn_time_offset : STD_LOGIC_VECTOR(c_bsn_time_offset_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL bs_sosi : t_dp_sosi; + SIGNAL exp_grid_bs : t_time_grid; -- to check with bs_sosi.bsn, sync, sop, eop -- RSN source - SIGNAL rs_restart : STD_LOGIC; - SIGNAL rs_new_interval : STD_LOGIC; - SIGNAL rs_sosi : t_dp_sosi; + SIGNAL rs_restart : STD_LOGIC; + SIGNAL rs_new_interval : STD_LOGIC; + SIGNAL rs_sosi : t_dp_sosi; + SIGNAL exp_grid_rs : t_time_grid; -- to verify rs_sosi.bsn, sync, sop, eop -- Verify - SIGNAL exp_grid : t_time_grid; - SIGNAL unexpected_bs_sync : STD_LOGIC; + SIGNAL exp_rs_start_bsn : NATURAL; + SIGNAL exp_rs_sync_cnt : NATURAL; + SIGNAL exp_rs_block_cnt : NATURAL; + SIGNAL hold_exp_rs_sync : STD_LOGIC := '0'; + + SIGNAL unexpected_rs_sync : STD_LOGIC; SIGNAL sl0 : STD_LOGIC := '0'; SIGNAL verify_en : STD_LOGIC := '0'; SIGNAL verify_sync : STD_LOGIC := '0'; - SIGNAL hold_bs_sop : STD_LOGIC; - SIGNAL prev_bs_valid : STD_LOGIC; - SIGNAL bs_starts_cnt : NATURAL := 0; + SIGNAL hold_rs_sop : STD_LOGIC := '0'; + SIGNAL prev_rs_valid : STD_LOGIC; + SIGNAL rs_starts_cnt : NATURAL := 0; SIGNAL dbg_c_nof_pps : NATURAL := c_nof_pps; SIGNAL dbg_c_nof_repeat : NATURAL := c_nof_repeat; @@ -143,32 +154,32 @@ BEGIN clk <= (NOT clk) OR tb_end AFTER c_clk_period/2; ----------------------------------------------------------------------------- - -- Generate reference time grid + -- Generate reference time grid for bs_sosi ----------------------------------------------------------------------------- - proc_common_gen_pulse(1, g_pps_interval, '1', sl0, clk, ref_grid.pps); - proc_common_gen_pulse(1, g_bs_block_size, '1', sl0, clk, ref_grid.sop); - ref_grid.eop <= ref_grid.sop'DELAYED((g_bs_block_size - 1) * c_clk_period); - ssn_eop <= ref_grid.pps'DELAYED((g_pps_interval - 1) * c_clk_period); - ref_grid.ssn <= ref_grid.ssn + 1 WHEN rising_edge(clk) AND ssn_eop = '1'; - ref_grid.bsn <= ref_grid.bsn + 1 WHEN rising_edge(clk) AND ref_grid.eop = '1'; + proc_common_gen_pulse(1, g_pps_interval, '1', sl0, clk, ref_grid_bs.pps); + proc_common_gen_pulse(1, g_bs_block_size, '1', sl0, clk, ref_grid_bs.sop); + ref_grid_bs.eop <= ref_grid_bs.sop'DELAYED((g_bs_block_size - 1) * c_clk_period); + ssn_eop <= ref_grid_bs.pps'DELAYED((g_pps_interval - 1) * c_clk_period); + ref_grid_bs.ssn <= ref_grid_bs.ssn + 1 WHEN rising_edge(clk) AND ssn_eop = '1'; + ref_grid_bs.bsn <= ref_grid_bs.bsn + 1 WHEN rising_edge(clk) AND ref_grid_bs.eop = '1'; -- Issue sync at start of block - p_ref_grid_sync : PROCESS(ref_grid, hold_pps) + p_ref_grid_bs_sync : PROCESS(ref_grid_bs, hold_pps) BEGIN - ref_grid.sync <= '0'; + ref_grid_bs.sync <= '0'; nxt_hold_pps <= hold_pps; - IF ref_grid.pps = '1' THEN - IF ref_grid.sop = '1' THEN - ref_grid.sync <= '1'; -- immediately issue sync + IF ref_grid_bs.pps = '1' THEN + IF ref_grid_bs.sop = '1' THEN + ref_grid_bs.sync <= '1'; -- immediately issue sync ELSE nxt_hold_pps <= '1'; -- wait until next block END IF; END IF; IF hold_pps = '1' THEN - IF ref_grid.sop = '1' THEN - ref_grid.sync <= '1'; -- issue pending sync + IF ref_grid_bs.sop = '1' THEN + ref_grid_bs.sync <= '1'; -- issue pending sync nxt_hold_pps <= '0'; END IF; END IF; @@ -176,7 +187,71 @@ BEGIN hold_pps <= nxt_hold_pps WHEN rising_edge(clk); - exp_grid <= ref_grid'DELAYED(c_dut_latency * c_clk_period); + exp_grid_bs <= ref_grid_bs'DELAYED(c_dp_bsn_latency * c_clk_period); + + ----------------------------------------------------------------------------- + -- Generate reference time grid for rs_sosi + ----------------------------------------------------------------------------- + + -- using clk process accounts for c_dp_rsn_latency = 1 + p_exp_grid_rs : PROCESS(clk) + VARIABLE v_sop : STD_LOGIC; + BEGIN + IF rising_edge(clk) THEN + v_sop := '0'; + + -- same pps, ssn + exp_grid_rs.pps <= exp_grid_bs.pps; + exp_grid_rs.ssn <= exp_grid_bs.ssn; + exp_grid_rs.sync <= '0'; + exp_grid_rs.sop <= '0'; + exp_grid_rs.eop <= '0'; + + -- bs blocks start at t_epoch = 0, but rs sync and blocks start at + -- bs_restart, so not necessarily at t_epoch = 0 + IF bs_restart = '1' THEN + exp_rs_sync_cnt <= 0; + exp_rs_block_cnt <= 0; + exp_grid_rs.sync <= '1'; + exp_grid_rs.sop <= '1'; + exp_grid_rs.bsn <= exp_grid_bs.bsn * g_bs_block_size; + exp_rs_start_bsn <= exp_grid_bs.bsn * g_bs_block_size; + hold_exp_rs_sync <= '0'; + ELSE + -- expected rs_sosi sop, eop + IF exp_rs_block_cnt < g_rs_block_size-2 THEN + exp_rs_block_cnt <= exp_rs_block_cnt + 1; + ELSIF exp_rs_block_cnt = g_rs_block_size-2 THEN + exp_rs_block_cnt <= exp_rs_block_cnt + 1; + exp_grid_rs.eop <= '1'; + ELSIF exp_rs_block_cnt = g_rs_block_size-1 THEN + v_sop := '1'; + exp_rs_block_cnt <= 0; + exp_grid_rs.sop <= '1'; + exp_grid_rs.bsn <= exp_grid_rs.bsn + g_rs_block_size; + -- check for pending rs_sosi sync + IF hold_exp_rs_sync = '1' THEN + exp_grid_rs.sync <= '1'; + hold_exp_rs_sync <= '0'; + END IF; + END IF; + + -- expected rs_sosi sync + IF exp_rs_sync_cnt < g_pps_interval-1 THEN + exp_rs_sync_cnt <= exp_rs_sync_cnt + 1; + ELSE + exp_rs_sync_cnt <= 0; + IF v_sop = '1' THEN + exp_grid_rs.sync <= '1'; -- issue sync immediately at this exp_grid_rs.sop + ELSE + hold_exp_rs_sync <= '1'; -- pend sync until next exp_grid_rs.sop + END IF; + END IF; + END IF; + + END IF; + END PROCESS; + ----------------------------------------------------------------------------- -- Stimuli @@ -199,7 +274,9 @@ BEGIN tb_state <= s_disable; dp_on <= '0'; dp_on_pps <= '0'; - proc_common_wait_some_cycles(clk, 10); + + -- Wait sufficient until bs_sosi is idle again + proc_common_wait_some_cycles(clk, 5*g_pps_interval); -- Start synchronously by making dp_on and dp_on_pps high verify_en <= '1'; -- verify automatically in test bench @@ -207,17 +284,17 @@ BEGIN FOR I IN 0 TO c_nof_repeat-1 LOOP -- Wait some variable time between tests, to enforce testing different -- bsn_time_offset values - proc_common_wait_some_cycles(clk, 20); + proc_common_wait_some_cycles(clk, 5*g_pps_interval); proc_common_wait_some_cycles(clk, I*g_pps_interval); -- Wait until in the beginning of PPS interval - proc_common_wait_until_hi_lo(clk, ref_grid.pps); - proc_common_wait_some_cycles(clk, c_dut_latency); + proc_common_wait_until_hi_lo(clk, ref_grid_bs.pps); + proc_common_wait_some_cycles(clk, c_dp_bsn_latency); -- Determine bsn_init and bsn_time_offset for BSN source start -- . bsn_init = BSN at sync -- . bsn_time_offset = number of clk that sync occurs after PPS - v_ssn := ref_grid.ssn + 1; -- +1 to prepare start in next PPS interval + v_ssn := ref_grid_bs.ssn + 1; -- +1 to prepare start in next PPS interval v_bsn_init := ceil_div(v_SSN * g_pps_interval, g_bs_block_size); -- Equation 3.6 in [1] v_bsn_time_offset := v_bsn_init * g_bs_block_size - v_SSN * g_pps_interval; -- Equation 3.7 in [1] bsn_init <= TO_UVEC(v_bsn_init, c_bsn_w); -- @@ -233,7 +310,7 @@ BEGIN END LOOP; proc_common_wait_some_cycles(clk, 10); - ASSERT bs_starts_cnt = 1 + c_nof_repeat REPORT "Wrong number of BSN source starts." SEVERITY ERROR; + ASSERT rs_starts_cnt = 1 + c_nof_repeat REPORT "Wrong number of BSN source starts." SEVERITY ERROR; tb_end <= '1'; WAIT; @@ -242,79 +319,80 @@ BEGIN ----------------------------------------------------------------------------- -- Verification - -- . Some aspects of bs_sosi are verified multiple times in different ways, + -- . Some aspects of rs_sosi are verified multiple times in different ways, -- this overlap is fine, because the tb and DUT are rather complicated, so -- using different approaches also helpt to verify the tb itself. ----------------------------------------------------------------------------- - verify_sync <= verify_en AND bs_sosi.valid; + verify_sync <= verify_en AND rs_sosi.valid; - proc_dp_verify_sop_and_eop(clk, bs_sosi.valid, bs_sosi.sop, bs_sosi.eop, hold_bs_sop); -- Verify that sop and eop come in pairs - --proc_dp_verify_sync(clk, verify_sync, bs_sosi.sync, exp_grid.sop, exp_grid.sync); -- Verify sync at sop and at expected_sync + proc_dp_verify_sop_and_eop(clk, rs_sosi.valid, rs_sosi.sop, rs_sosi.eop, hold_rs_sop); -- Verify that sop and eop come in pairs + --proc_dp_verify_sync(clk, verify_sync, rs_sosi.sync, exp_grid_rs.sop, exp_grid_rs.sync); -- Verify sync at sop and at expected_sync -- Verify sync at sop and at expected_sync - proc_dp_verify_sync(0, -- start bsn of PPS grid and BSN grid is 0, see [1] + proc_dp_verify_sync(exp_rs_start_bsn, g_pps_interval, - g_bs_block_size, + g_rs_block_size, + TRUE, -- use BSN as RSN clk, verify_en, - bs_sosi.sync, - bs_sosi.sop, - bs_sosi.bsn, + rs_sosi.sync, + rs_sosi.sop, + rs_sosi.bsn, dbg_nof_blk, dbg_accumulate, dbg_expected_bsn); - -- Verify bs_sosi by comparing with exp_grid, this again verifies bs_sosi.sync, sop and bsn - p_verify_bs_sosi_grid : PROCESS(clk) + -- Verify rs_sosi by comparing with exp_grid_rs, this again verifies rs_sosi.sync, sop and bsn + p_verify_rs_sosi_grid : PROCESS(clk) BEGIN IF rising_edge(clk) THEN - unexpected_bs_sync <= '0'; - IF verify_en = '1' AND bs_sosi.valid = '1' THEN - ASSERT TO_UINT(bs_sosi.bsn) = exp_grid.bsn REPORT "Wrong bs_sosi.bsn /= exp_grid.bsn" SEVERITY ERROR; - ASSERT bs_sosi.sync = exp_grid.sync REPORT "Wrong bs_sosi.sync /= exp_grid.sync" SEVERITY ERROR; - ASSERT bs_sosi.sop = exp_grid.sop REPORT "Wrong bs_sosi.sop /= exp_grid.sop" SEVERITY ERROR; - ASSERT bs_sosi.eop = exp_grid.eop REPORT "Wrong bs_sosi.eop /= exp_grid.eop" SEVERITY ERROR; + unexpected_rs_sync <= '0'; + IF verify_en = '1' AND rs_sosi.valid = '1' THEN + ASSERT TO_UINT(rs_sosi.bsn) = exp_grid_rs.bsn REPORT "Wrong rs_sosi.bsn /= exp_grid_rs.bsn" SEVERITY ERROR; + ASSERT rs_sosi.sync = exp_grid_rs.sync REPORT "Wrong rs_sosi.sync /= exp_grid_rs.sync" SEVERITY ERROR; + ASSERT rs_sosi.sop = exp_grid_rs.sop REPORT "Wrong rs_sosi.sop /= exp_grid_rs.sop" SEVERITY ERROR; + ASSERT rs_sosi.eop = exp_grid_rs.eop REPORT "Wrong rs_sosi.eop /= exp_grid_rs.eop" SEVERITY ERROR; -- Mark error in Wave window - IF bs_sosi.sync = '1' AND bs_sosi.sync /= exp_grid.sync THEN - unexpected_bs_sync <= '1'; + IF rs_sosi.sync = '1' AND rs_sosi.sync /= exp_grid_rs.sync THEN + unexpected_rs_sync <= '1'; END IF; END IF; END IF; END PROCESS; - -- Verify that bs_sosi.valid = '1' did happen after dp_on by verifying bs_start - prev_bs_valid <= bs_sosi.valid WHEN rising_edge(clk); - bs_starts_cnt <= bs_starts_cnt + 1 WHEN rising_edge(clk) AND bs_sosi.valid = '1' AND prev_bs_valid = '0'; + -- Verify that rs_sosi.valid = '1' did happen after dp_on by verifying rs_start + prev_rs_valid <= rs_sosi.valid WHEN rising_edge(clk); + rs_starts_cnt <= rs_starts_cnt + 1 WHEN rising_edge(clk) AND rs_sosi.valid = '1' AND prev_rs_valid = '0'; - p_verify_bs_restart : PROCESS(clk) + p_verify_rs_restart : PROCESS(clk) BEGIN IF rising_edge(clk) THEN - IF bs_restart = '1' THEN - ASSERT bs_sosi.sync = '1' REPORT "Unexpected bs_start while bs_sosi.sync /= 1" SEVERITY ERROR; - ASSERT prev_bs_valid = '0' REPORT "Unexpected bs_start while prev_bs_valid /= 0" SEVERITY ERROR; + IF rs_restart = '1' THEN + ASSERT rs_sosi.sync = '1' REPORT "Unexpected rs_start while rs_sosi.sync /= 1" SEVERITY ERROR; + ASSERT prev_rs_valid = '0' REPORT "Unexpected rs_start while prev_rs_valid /= 0" SEVERITY ERROR; END IF; END IF; END PROCESS; - p_verify_bs_new_interval : PROCESS(clk) + p_verify_rs_new_interval : PROCESS(clk) BEGIN IF rising_edge(clk) THEN - IF bs_restart = '1' THEN - ASSERT bs_new_interval = '1' REPORT "Wrong begin of bs_new_interval" SEVERITY ERROR; + IF rs_restart = '1' THEN + ASSERT rs_new_interval = '1' REPORT "Wrong begin of rs_new_interval" SEVERITY ERROR; tb_new_interval <= '1'; - ELSIF bs_sosi.sync = '1' THEN - ASSERT bs_new_interval = '0' REPORT "Wrong end of bs_new_interval" SEVERITY ERROR; + ELSIF rs_sosi.sync = '1' THEN + ASSERT rs_new_interval = '0' REPORT "Wrong end of rs_new_interval" SEVERITY ERROR; tb_new_interval <= '0'; ELSIF tb_new_interval = '1' THEN - ASSERT bs_new_interval = '1' REPORT "Wrong level during bs_new_interval" SEVERITY ERROR; + ASSERT rs_new_interval = '1' REPORT "Wrong level during rs_new_interval" SEVERITY ERROR; ELSE - ASSERT bs_new_interval = '0' REPORT "Unexpected bs_new_interval" SEVERITY ERROR; + ASSERT rs_new_interval = '0' REPORT "Unexpected rs_new_interval" SEVERITY ERROR; END IF; END IF; END PROCESS; ----------------------------------------------------------------------------- - -- DUT: dp_bsn_source_v2 + -- DUT: dp_bsn_source_v2 --> dp_rsn_source ----------------------------------------------------------------------------- u_bsn : ENTITY work.dp_bsn_source_v2 @@ -327,7 +405,7 @@ BEGIN PORT MAP ( rst => rst, clk => clk, - pps => ref_grid.pps, + pps => ref_grid_bs.pps, -- MM control dp_on => dp_on, dp_on_pps => dp_on_pps, @@ -345,7 +423,8 @@ BEGIN u_rsn : ENTITY work.dp_rsn_source GENERIC MAP ( - g_block_size => g_rs_block_size, + g_bs_block_size => g_bs_block_size, + g_rs_block_size => g_rs_block_size, g_nof_clk_per_sync => g_pps_interval, g_bsn_w => c_bsn_w ) diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_rsn_source.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_rsn_source.vhd index f0afc936e5..377dd47e96 100644 --- a/libraries/base/dp/tb/vhdl/tb_tb_dp_rsn_source.vhd +++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_rsn_source.vhd @@ -52,6 +52,7 @@ BEGIN ----------------------------------------------------------------------------- u_12_3_3 : ENTITY work.tb_dp_rsn_source GENERIC MAP (12, 3, 3); -- smallest block size u_16_8_4 : ENTITY work.tb_dp_rsn_source GENERIC MAP (16, 8, 4); -- integer number of blocks per g_pps_interval + u_25_5 : ENTITY work.tb_dp_rsn_source GENERIC MAP (25, 5, 5); u_29_17_23 : ENTITY work.tb_dp_rsn_source GENERIC MAP (29, 17, 23); -- fractional number of blocks per g_pps_interval u_9_4_5 : ENTITY work.tb_dp_rsn_source GENERIC MAP (9, 4, 5); -- 2 g_bs_block_size < g_pps_interval < 2 g_rs_block_size @@ -60,8 +61,7 @@ BEGIN u_9_9_5 : ENTITY work.tb_dp_rsn_source GENERIC MAP (9, 9, 5); -- 1 g_bs_block_size/g_pps_interval ----------------------------------------------------------------------------- - -- Same tests as with tb_dp_bsn_source_v2 - -- . g_rs_block_size /= g_bs_block_size + -- Same tests as with tb_dp_bsn_source_v2 with g_rs_block_size = g_bs_block_size ----------------------------------------------------------------------------- -- test integer case u_20_10 : ENTITY work.tb_dp_rsn_source GENERIC MAP (20, 10, 10); -- 20 // 10 = 2, 20 MOD 10 = 0, 20/10 = 2 block/sync -- GitLab