From fadf06530e31a517c277b5f5488ce2fb432c76b4 Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Wed, 4 Aug 2021 16:06:16 +0200 Subject: [PATCH] Fixed out_sosi.sync now starts with long fractional interval. Added fast forward of next output_sync_bsn in case of lost blocks. --- .../base/dp/src/vhdl/dp_bsn_sync_interval.vhd | 84 +++++++++++++------ 1 file changed, 59 insertions(+), 25 deletions(-) diff --git a/libraries/base/dp/src/vhdl/dp_bsn_sync_interval.vhd b/libraries/base/dp/src/vhdl/dp_bsn_sync_interval.vhd index 84ab7eb94b..a3bb5f9c11 100644 --- a/libraries/base/dp/src/vhdl/dp_bsn_sync_interval.vhd +++ b/libraries/base/dp/src/vhdl/dp_bsn_sync_interval.vhd @@ -126,16 +126,19 @@ ARCHITECTURE rtl OF dp_bsn_sync_interval IS blk_cnt : NATURAL; interval_size : NATURAL; start_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + input_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); nof_blk_min : NATURAL; nof_blk_max : NATURAL; - fraction_size : INTEGER RANGE -g_block_size TO g_block_size; + nof_blk : NATURAL; + extra : INTEGER;-- RANGE -g_block_size TO g_block_size; + accumulate : INTEGER;-- RANGE -g_block_size TO g_block_size; hold_eop : STD_LOGIC; update_bsn : STD_LOGIC; output_enable : STD_LOGIC; output_sync_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); END RECORD; - CONSTANT c_reg_rst : t_reg := ('0', '0', 0, 0, (OTHERS=>'0'), 0, 0, 0, '1', '0', '0', (OTHERS=>'0')); + CONSTANT c_reg_rst : t_reg := ('0', '0', 0, 0, (OTHERS=>'0'), (OTHERS=>'0'), 0, 0, 0, 0, 0, '1', '0', '0', (OTHERS=>'0')); -- Local registers SIGNAL r : t_reg; @@ -177,25 +180,33 @@ BEGIN -- Initialization: calculate number of blocks per output sync interval IF r.enable_init = '1' THEN - -- Assume ctrl_start_bsn more than nof_blk block periods is after the - -- ctrl_enable_evt, so there is sufficient time until v.output_enable = - -- '1', to perform the calculation of nof_blk_min and nof_blk_max - -- sequentially. This avoids using division to calculate - -- ctrl_interval_size / g_block_size. + -- Assume ctrl_start_bsn is scheduled more than nof_blk block clk cycles + -- after the ctrl_enable_evt, so there is sufficient time until + -- v.output_enable = '1', to perform the calculation of nof_blk_min and + -- nof_blk_max sequentially. This avoids using division in logic to + -- calculate ctrl_interval_size / g_block_size. v_size := r.blk_cnt * g_block_size; IF v_size = ctrl_interval_size THEN + -- Support integer number of blocks per output sync interval v.interval_size := ctrl_interval_size; -- hold ctrl_interval_size v.start_bsn := ctrl_start_bsn; -- hold ctrl_start_bsn - v.nof_blk_min := r.blk_cnt; -- support integer number of blocks per output sync interval + -- Fixed sync interval control, effectively disable fractional sync interval control: + v.nof_blk_min := r.blk_cnt; v.nof_blk_max := r.blk_cnt; - v.fraction_size := 0; -- = nof_blk_max - nof_blk_min + v.nof_blk := r.blk_cnt; -- nof_blk = nof_blk_max = nof_blk_min + v.extra := 0; + v.accumulate := 0; v.enable_init := '0'; -- enable initialization is done ELSIF v_size > ctrl_interval_size THEN + -- Support fractional number of blocks per output sync interval v.interval_size := ctrl_interval_size; -- hold ctrl_interval_size v.start_bsn := ctrl_start_bsn; -- hold ctrl_start_bsn - v.nof_blk_min := r.blk_cnt - 1; -- support fractional number of blocks per output sync interval + -- Fractional sync interval control: + v.nof_blk_min := r.blk_cnt - 1; v.nof_blk_max := r.blk_cnt; - v.fraction_size := v_size - ctrl_interval_size; -- number of extra samples in nof_blk_max + v.nof_blk := r.blk_cnt; -- start with nof_blk_max sync interval + v.extra := v_size - ctrl_interval_size; -- number of extra samples in nof_blk_max compared to ctrl_interval_size + v.accumulate := v.extra; -- start with nof_blk_max sync interval v.enable_init := '0'; -- enable initialization is done ELSE v.blk_cnt := r.blk_cnt + 1; @@ -211,8 +222,8 @@ BEGIN v.enable := '1'; END IF; - -- Hold eop to detect when input has finished a block and to detect gaps - -- between in_sosi.eop and in_sosi.sop + -- Hold input eop to detect when input has finished a block and to detect + -- gaps between in_sosi.eop and in_sosi.sop IF in_sosi.sop = '1' THEN v.hold_eop := '0'; END IF; @@ -220,16 +231,17 @@ BEGIN v.hold_eop := '1'; END IF; - -- Output enable at sync and disable after in_sosi.eop IF r.enable = '1' THEN + -- Output enable at in_sosi.sop start_bsn IF in_sosi.sop = '1' THEN IF UNSIGNED(in_sosi.bsn) = UNSIGNED(r.start_bsn) THEN v.output_enable := '1'; output_start <= '1'; -- Pulse at start of output enable at start BSN of output sync intervals - v.output_sync_bsn := r.start_bsn; + v.output_sync_bsn := r.start_bsn; -- Initialize output sync at start BSN of output sync intervals END IF; END IF; ELSE + -- Output disable after in_sosi.eop IF r.hold_eop = '1' THEN v.output_enable := '0'; END IF; @@ -252,19 +264,41 @@ BEGIN -- Determine BSN for next output sync IF r.update_bsn = '1' THEN - IF r.fraction_size > 0 THEN - v.output_sync_bsn := ADD_UVEC(r.output_sync_bsn, TO_UVEC(r.nof_blk_min, c_natural_w)); -- next BSN - v_size := r.nof_blk_min * g_block_size; -- next interval size - ELSE - v.output_sync_bsn := ADD_UVEC(r.output_sync_bsn, TO_UVEC(r.nof_blk_max, c_natural_w)); -- next BSN - v_size := r.nof_blk_max * g_block_size; -- next interval size + -- Similar code as in proc_dp_verify_sync(), the difference is that: + -- . Here r.extra is number of extra samples in nof_blk_max compared to + -- ctrl_interval_size, + -- . in proc_dp_verify_sync() r.extra is number of extra samples in + -- ctrl_interval_size compared to nof_blk_min. + -- Both schemes are valid, by using different schemes here and in tb the + -- verification coverage improves. + v.output_sync_bsn := ADD_UVEC(r.output_sync_bsn, TO_UVEC(r.nof_blk, c_natural_w)); -- next BSN + + v.nof_blk := r.nof_blk_max; + v.accumulate := r.accumulate + r.extra; -- account for nof_blk_max + IF v.accumulate >= g_block_size THEN + v.nof_blk := r.nof_blk_min; + v.accumulate := v.accumulate - g_block_size; -- adjust for nof_blk_min END IF; - v.fraction_size := r.fraction_size + v_size - ctrl_interval_size; -- next fraction - -- Assume output_sync_bsn is in future, else next in_sosi.sop will - -- result in a new update_bsn reqest, to catch up for lost input - -- blocks. + -- Assume output_sync_bsn is in future v.update_bsn := '0'; + + -- else last r.input_bsn will be used to keep update_bsn active for + -- more clk cycles to catch up for lost input blocks. + END IF; + + -- Hold input bsn + IF in_sosi.sop = '1' THEN + v.input_bsn := in_sosi.bsn(g_bsn_w-1 DOWNTO 0); + END IF; + + -- Catch up with output_sync_bsn in case of lost input blocks + IF v.output_enable = '1' THEN + IF UNSIGNED(r.input_bsn) > UNSIGNED(v.output_sync_bsn) THEN + -- Missed one or more input blocks, fast forward to look for next + -- output_sync_bsn + v.update_bsn := '1'; + END IF; END IF; nxt_r <= v; -- GitLab