From 987f1bd1f360c14295b9ab17a34b1288f57fea12 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Mon, 24 Oct 2022 17:11:38 +0200
Subject: [PATCH] Only accept new BG ctrl when the BG is (re)started.

---
 .../base/diag/src/vhdl/diag_block_gen.vhd     | 49 ++++++++++---------
 .../base/diag/src/vhdl/mms_diag_block_gen.vhd |  4 +-
 .../base/diag/tb/vhdl/tb_diag_block_gen.vhd   | 39 ++-------------
 3 files changed, 30 insertions(+), 62 deletions(-)

diff --git a/libraries/base/diag/src/vhdl/diag_block_gen.vhd b/libraries/base/diag/src/vhdl/diag_block_gen.vhd
index 148212a21e..0f1104b33b 100644
--- a/libraries/base/diag/src/vhdl/diag_block_gen.vhd
+++ b/libraries/base/diag/src/vhdl/diag_block_gen.vhd
@@ -47,9 +47,10 @@
 --   every blocks_per_sync.
 --
 --   The current block is finished properly after enable gows low, to ensure 
---   that all blocks have the same length. A new ctrl is accepted after a
---   current block has finished, to ensure that no fractional blocks will 
---   enter the stream.
+--   that all blocks have the same length. A new ctrl is accepted only when
+--   the BG is (re)started, to simplify the use of ctrl_hold. The ctrl_hold
+--   holds the active control settings while BG is enabled. Note that
+--   ctrl_hold.enable remains '1' after the BG has been enabled once.
 --
 --   The BG supports block flow control via out_siso.xon. The BG also supports
 --   sample flow control via out_siso.ready.
@@ -81,7 +82,7 @@ entity diag_block_gen is
     buf_rddat    : in  std_logic_vector(g_buf_dat_w-1 downto 0);
     buf_rdval    : in  std_logic;
     ctrl         : in  t_diag_block_gen;
-    ctrl_reg     : out t_diag_block_gen;  -- current active ctrl
+    ctrl_hold    : out t_diag_block_gen;  -- hold current active ctrl
     en_sync      : in  std_logic := '1';
     out_siso     : in  t_dp_siso := c_dp_siso_rdy;
     out_sosi     : out t_dp_sosi
@@ -94,7 +95,7 @@ architecture rtl of diag_block_gen is
   type state_type is (s_idle, s_block, s_gap);
 
   type reg_type is record
-    ctrl_reg    : t_diag_block_gen;  -- capture ctrl
+    ctrl_hold   : t_diag_block_gen;  -- capture ctrl
     blk_en      : std_logic;  -- enable at block level
     blk_xon     : std_logic;  -- siso.xon at block level, the BG continues but the sosi control depend on xon (the BG does not support siso.ready)
     blk_sync    : std_logic;  -- block sync alternative of the pulse sync
@@ -112,10 +113,14 @@ architecture rtl of diag_block_gen is
 
   signal r, rin     : reg_type;
   signal out_sosi_i : t_dp_sosi := c_dp_sosi_rst;  -- Signal used to assign reset values to output
+  signal xon_reg    : std_logic := '0';
   
 begin 
     
-    p_comb : process(r, rst, ctrl, en_sync, out_siso)
+    -- xon is not clk cycle timing critical, so can use register xon to ease timing closure
+    xon_reg <= out_siso.xon when rising_edge(clk);
+
+    p_comb : process(r, rst, ctrl, en_sync, out_siso, xon_reg)
       variable v                    : reg_type;                              
       variable v_samples_per_packet : natural;   
       variable v_gapsize            : natural;   
@@ -124,11 +129,11 @@ begin
       variable v_mem_high_adrs      : natural;
     begin
     
-      v_samples_per_packet := TO_UINT(r.ctrl_reg.samples_per_packet);
-      v_gapsize            := TO_UINT(r.ctrl_reg.gapsize);
-      v_blocks_per_sync    := TO_UINT(r.ctrl_reg.blocks_per_sync); 
-      v_mem_low_adrs       := TO_UINT(r.ctrl_reg.mem_low_adrs); 
-      v_mem_high_adrs      := TO_UINT(r.ctrl_reg.mem_high_adrs);
+      v_samples_per_packet := TO_UINT(r.ctrl_hold.samples_per_packet);
+      v_gapsize            := TO_UINT(r.ctrl_hold.gapsize);
+      v_blocks_per_sync    := TO_UINT(r.ctrl_hold.blocks_per_sync);
+      v_mem_low_adrs       := TO_UINT(r.ctrl_hold.mem_low_adrs);
+      v_mem_high_adrs      := TO_UINT(r.ctrl_hold.mem_high_adrs);
       
       v                   := r;     -- default hold all r fields
       v.pls_sync          := '0';
@@ -158,15 +163,15 @@ begin
       
       case r.state is
         when s_idle => 
-          v.ctrl_reg    := ctrl;        -- accept new control settings
-          v.blk_xon     := out_siso.xon;
+          v.blk_xon     := xon_reg;
           v.blk_sync    := '0';
           v.samples_cnt := 0;
           v.blocks_cnt  := 0;    
-          v.bsn_cnt     := ctrl.bsn_init;
           v.mem_cnt     := v_mem_low_adrs; 
-          if r.blk_en = '1' then       -- Wait until enabled
-            if out_siso.xon='1' then   -- Wait until XON is 1
+          if r.blk_en = '1' then  -- Wait until enabled
+            if xon_reg = '1' then   -- Wait until XON is 1
+              v.ctrl_hold   := ctrl;  -- hold new control settings while BG is enabled
+              v.bsn_cnt     := ctrl.bsn_init;
               v.rd_ena      := '1';
               v.state       := s_block;
             end if;
@@ -186,12 +191,10 @@ begin
               v.samples_cnt := v.samples_cnt + 1; 
             elsif r.samples_cnt >= v_samples_per_packet-1 and v_gapsize = 0 and r.blocks_cnt >= v_blocks_per_sync-1 then 
               v.eop         := '1'; 
-              v.ctrl_reg    := ctrl;      -- accept new control settings at end of block when gapsize=0
               v.samples_cnt := 0; 
               v.blocks_cnt  := 0;
             elsif r.samples_cnt >= v_samples_per_packet-1 and v_gapsize = 0 then 
               v.eop         := '1'; 
-              v.ctrl_reg    := ctrl;      -- accept new control settings at end of block when gapsize=0
               v.samples_cnt := 0; 
               v.blocks_cnt  := r.blocks_cnt + 1;
             elsif r.samples_cnt >= v_samples_per_packet-1 then 
@@ -214,20 +217,18 @@ begin
               v.state := s_idle;          -- accept disable after eop, not during block
             end if;
             if r.eop = '1' then
-              v.blk_xon := out_siso.xon;  -- accept XOFF after eop, not during block
+              v.blk_xon := xon_reg;  -- accept XOFF after eop, not during block
             end if;
           
           end if;  -- out_siso.ready='1'
 
         when s_gap => 
           if r.samples_cnt >= v_gapsize-1 and r.blocks_cnt >= v_blocks_per_sync-1 then 
-            v.ctrl_reg    := ctrl;      -- accept new control settings at end of gap
             v.samples_cnt := 0; 
             v.blocks_cnt  := 0;
             v.rd_ena      := '1';
             v.state       := s_block;
           elsif r.samples_cnt >= v_gapsize-1 then 
-            v.ctrl_reg    := ctrl;      -- accept new control settings at end of gap
             v.samples_cnt := 0;             
             v.blocks_cnt  := r.blocks_cnt + 1;
             v.rd_ena      := '1';
@@ -239,7 +240,7 @@ begin
           if r.blk_en = '0' then
             v.state := s_idle;
           end if;
-          v.blk_xon := out_siso.xon;
+          v.blk_xon := xon_reg;
                 
         when others =>
           v.state := s_idle;
@@ -247,7 +248,7 @@ begin
       end case;
       
       if rst = '1' then 
-        v.ctrl_reg    := c_diag_block_gen_rst; 
+        v.ctrl_hold    := c_diag_block_gen_rst;
         v.blk_en      := '0'; 
         v.blk_xon     := '0'; 
         v.blk_sync    := '0'; 
@@ -288,6 +289,6 @@ begin
     buf_addr <= TO_UVEC(r.mem_cnt, g_buf_addr_w);
     buf_rden <= r.rd_ena;
 
-    ctrl_reg <= r.ctrl_reg;
+    ctrl_hold <= r.ctrl_hold;
  
 end rtl;
diff --git a/libraries/base/diag/src/vhdl/mms_diag_block_gen.vhd b/libraries/base/diag/src/vhdl/mms_diag_block_gen.vhd
index f219957f2e..93839197c8 100644
--- a/libraries/base/diag/src/vhdl/mms_diag_block_gen.vhd
+++ b/libraries/base/diag/src/vhdl/mms_diag_block_gen.vhd
@@ -140,7 +140,7 @@ ENTITY mms_diag_block_gen IS
     reg_tx_seq_mosi  : IN  t_mem_mosi := c_mem_mosi_rst;  -- Tx seq control (one per stream because c_reg_tx_seq_broadcast=FALSE)
     reg_tx_seq_miso  : OUT t_mem_miso;
     -- ST interface
-    bg_ctrl_active_arr : OUT t_diag_block_gen_arr(g_nof_streams-1 DOWNTO 0);
+    bg_ctrl_hold_arr : OUT t_diag_block_gen_arr(g_nof_streams-1 DOWNTO 0);
     usr_siso_arr     : OUT t_dp_siso_arr(g_nof_streams-1 DOWNTO 0);  -- connect when g_use_usr_input=TRUE, else leave not connected 
     usr_sosi_arr     : IN  t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_sosi_rst);
     out_siso_arr     : IN  t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);  -- Default xon='1'
@@ -285,7 +285,7 @@ BEGIN
         buf_rddat  => st_rddata_arr(I),       
         buf_rdval  => st_rdval_arr(I),          
         ctrl       => bg_ctrl,  -- same BG control for all streams
-        ctrl_reg   => bg_ctrl_active_arr(I),  -- active BG control can differ in time per stream
+        ctrl_hold  => bg_ctrl_hold_arr(I),  -- active BG control can differ in time per stream
         en_sync    => en_sync,
         out_siso   => bg_src_in_arr(I),
         out_sosi   => bg_src_out_arr(I)
diff --git a/libraries/base/diag/tb/vhdl/tb_diag_block_gen.vhd b/libraries/base/diag/tb/vhdl/tb_diag_block_gen.vhd
index af2edf0402..c54f89ca2b 100644
--- a/libraries/base/diag/tb/vhdl/tb_diag_block_gen.vhd
+++ b/libraries/base/diag/tb/vhdl/tb_diag_block_gen.vhd
@@ -134,7 +134,8 @@ ARCHITECTURE tb OF tb_diag_block_gen IS
   SIGNAL bg_buf_miso    : t_mem_miso;
   
   SIGNAL bg_ctrl        : t_diag_block_gen;
-                                                                            
+  SIGNAL bg_ctrl_hold   : t_diag_block_gen;
+
   SIGNAL random         : STD_LOGIC_VECTOR(14 DOWNTO 0) := (OTHERS=>'0');  -- use different lengths to have different random sequences
   SIGNAL toggle         : STD_LOGIC := '0';
   SIGNAL out_siso_bg    : t_dp_siso := c_dp_siso_rdy;
@@ -187,42 +188,7 @@ BEGIN
     bg_ctrl.mem_high_adrs <= TO_UVEC(c_alternative_mem_high_adrs, c_diag_bg_mem_high_adrs_w);
     bg_ctrl.enable <= '1';
     proc_dp_verify_run_some_cycles(5, c_runtime, 0, clk, verify_en);
-    
-    -- Run and change bg_ctrl dynamically
-    bg_ctrl.enable <= '0';
-    proc_common_wait_some_cycles(clk, c_offtime); 
-    bg_ctrl <= c_bg_ctrl;
-    bg_ctrl.enable <= '1';
-    proc_dp_verify_run_some_cycles(5, c_runtime, 0, clk, verify_en);
-    
-    -- . change gapsize dynamically
-    bg_ctrl.gapsize <= TO_UVEC(0, c_diag_bg_gapsize_w);
-    proc_dp_verify_run_some_cycles(0, c_runtime, 0, clk, verify_en);
 
-    bg_ctrl.gapsize <= c_bg_ctrl.gapsize;
-    proc_dp_verify_run_some_cycles(0, c_runtime, 0, clk, verify_en);
-    
-    -- . change mem_high_adrs dynamically
-    proc_common_wait_until_high(c_timeout, clk, out_sosi.eop);
-    bg_ctrl.mem_low_adrs <= TO_UVEC(c_alternative_mem_low_adrs, c_diag_bg_mem_low_adrs_w);
-    bg_ctrl.mem_high_adrs <= TO_UVEC(c_alternative_mem_high_adrs, c_diag_bg_mem_high_adrs_w);
-    proc_dp_verify_run_some_cycles(5, c_runtime, 0, clk, verify_en);
-    
-    bg_ctrl.mem_high_adrs <= c_bg_ctrl.mem_high_adrs;
-    proc_dp_verify_run_some_cycles(0, c_runtime, 0, clk, verify_en);
-        
-    -- . change samples_per_packet dynamically
-    proc_common_wait_until_high(c_timeout, clk, out_sosi.sop);
-    proc_common_wait_some_cycles(clk, 10);
-    bg_ctrl.samples_per_packet <= TO_UVEC(c_more_samples_per_packet, c_diag_bg_samples_per_packet_w);   -- increase
-    proc_dp_verify_run_some_cycles(0, c_runtime, 0, clk, verify_en);
-    
-    -- . change samples_per_packet dynamically
-    proc_common_wait_until_high(c_timeout, clk, out_sosi.sop);
-    proc_common_wait_some_cycles(clk, c_less_samples_per_packet*2);
-    bg_ctrl.samples_per_packet <= TO_UVEC(c_less_samples_per_packet, c_diag_bg_samples_per_packet_w);   -- decrease, could yield proc_dp_verify_block_size() error if it occurs during a packet
-    proc_dp_verify_run_some_cycles(0, c_runtime, 0, clk, verify_en);
-    
     -- Run with XON flow control (verified by proc_dp_verify_block_size)
     bg_ctrl.enable <= '0';
     proc_common_wait_some_cycles(clk, c_offtime); 
@@ -300,6 +266,7 @@ BEGIN
     buf_rddat   => bg_buf_miso.rddata(c_buf.dat_w-1 DOWNTO 0),   
     buf_rdval   => bg_buf_miso.rdval,   
     ctrl        => bg_ctrl,
+    ctrl_hold   => bg_ctrl_hold,
     out_siso    => out_siso_bg,
     out_sosi    => out_sosi
   );
-- 
GitLab