From d01b85f34e2300bc4fc840de40ce944f930c6f5e Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Tue, 15 Aug 2023 15:06:32 +0200
Subject: [PATCH] Capture dynamic nof_ch_in and nof_ch_sel when reorder_busy =
 '0'.

---
 .../reorder/src/vhdl/reorder_col_select.vhd   | 120 +++++++++++++-----
 1 file changed, 85 insertions(+), 35 deletions(-)

diff --git a/libraries/base/reorder/src/vhdl/reorder_col_select.vhd b/libraries/base/reorder/src/vhdl/reorder_col_select.vhd
index 0a6626912b..2fd6d8d369 100644
--- a/libraries/base/reorder/src/vhdl/reorder_col_select.vhd
+++ b/libraries/base/reorder/src/vhdl/reorder_col_select.vhd
@@ -22,18 +22,24 @@
 -- Author : R vd Walle
 -- Purpose: Reorder block of data in time
 -- Description:
---   Select nof_ch_sel complex samples from an input block of nof_ch_in
---   (complex) samples using a dual page buffer. The input select map is
---   arbitrary (any order and also duplicates) and can be set via the
---   col_select_mosi/miso MM interface.
---   Maximum size for the dual page buffer is g_nof_ch_in. Default nof_ch_in
+-- . Select nof_ch_sel samples from an input block of nof_ch_in samples using
+--   a dual page buffer. The input select map is arbitrary (any order and also
+--   duplicates) and can be set via the col_select_mosi/miso MM interface.
+-- . Maximum size for the dual page buffer is g_nof_ch_in. Default nof_ch_in
 --   = g_nof_ch_in, but it can used with smaller reorder block sizes.
---   The timing of sync and BSN is passed on in parallel.
+-- . New nof_ch_in and nof_ch_sel are accepted when reorder_busy = '0'. The
+--   output_nof_ch_in and output_nof_ch_sel show the counts that are used.
+-- . The reorder_busy goes high at input_sosi.sop, remains high while either
+--   store_busy and retrieve_busy are active, and goes low after retrieve_busy
+--   goes inactive. In practise this means that reorder_busy goes low after the
+--   last output_sosi.eop, when the input_sosi has created a sufficiently long
+--   interpacket gap.
+-- . The timing of sync and BSN is passed on in parallel.
 -- Remarks:
 -- . The nof_ch_sel <= period size and nof_ch_in <= period size, where period
 --   size is the time between input_sosi.sop, so 1/block rate.
 -- . The nof_ch_in is the number of valid samples from input_sosi.sop to
---   input_sosi.eop. If nof_ch_in is equal to the period size then there are
+--   input_sosi.eop. If nof_ch_in is equal to the period size, then there are
 --   no data invalid input_sosi.valid cycles during a period.
 -- . The nof_ch_sel is the number of valid samples from output_sosi.sop to
 --   output_sosi.eop. If nof_ch_sel is equal to the period size then there are
@@ -64,9 +70,15 @@ entity reorder_col_select is
     dp_rst          : in  std_logic;
     dp_clk          : in  std_logic;
 
-    -- Dynamic reorder block size control
-    nof_ch_in       : in natural range 0 to g_nof_ch_in := g_nof_ch_in;
-    nof_ch_sel      : in natural range 0 to g_nof_ch_sel := g_nof_ch_sel;
+    reorder_busy    : out std_logic;
+
+    -- Dynamic reorder block size control input
+    nof_ch_in       : in  natural range 0 to g_nof_ch_in := g_nof_ch_in;
+    nof_ch_sel      : in  natural range 0 to g_nof_ch_sel := g_nof_ch_sel;
+
+    -- Captured reorder block size control used for output_sosi
+    output_nof_ch_in  : out natural;
+    output_nof_ch_sel : out natural;
 
     -- Memory Mapped
     col_select_mosi : in  t_mem_mosi;  -- channel select control
@@ -91,25 +103,45 @@ architecture str of reorder_col_select is
   constant c_info_nof_pages : natural := 2;  -- fixed, fits the dual page block latency and logic latency of the SS
   constant c_retrieve_lat   : natural := c_store_buf.latency + 1;  -- = 2 rd_latency from waitrequest + store_buf latency
 
-  signal info_sop_wr_en   : std_logic_vector(c_info_nof_pages - 1 downto 0);
-  signal info_eop_wr_en   : std_logic_vector(c_info_nof_pages - 1 downto 0);
-  signal info_sosi_paged  : t_dp_sosi;
-  signal info_sosi        : t_dp_sosi;
+  signal input_sosi_reg     : t_dp_sosi := c_dp_sosi_rst;  -- register input_sosi to ease timing closure for reorder_busy
+
+  signal info_sop_wr_en     : std_logic_vector(c_info_nof_pages - 1 downto 0);
+  signal info_eop_wr_en     : std_logic_vector(c_info_nof_pages - 1 downto 0);
+  signal info_sosi_paged    : t_dp_sosi;
+  signal info_sosi          : t_dp_sosi := c_dp_sosi_rst;
 
-  signal store_mosi       : t_mem_mosi;
-  signal store_done       : std_logic;
+  signal store_mosi         : t_mem_mosi;
+  signal store_done         : std_logic;
 
   signal i_col_select_miso  : t_mem_miso := c_mem_miso_rst;
 
-  signal ch_cnt           : integer range 0 to g_nof_ch_sel - 1;
-  signal nxt_ch_cnt       : integer;
-  signal retrieve_sosi    : t_dp_sosi;
-  signal retrieve_en      : std_logic;
-  signal retrieve_sop_dly : std_logic_vector(0 to c_retrieve_lat);
-  signal retrieve_eop_dly : std_logic_vector(0 to c_retrieve_lat);
+  signal ch_cnt             : integer range 0 to g_nof_ch_sel - 1;
+  signal nxt_ch_cnt         : integer;
+  signal retrieve_sosi      : t_dp_sosi;
+  signal retrieve_en        : std_logic;
+  signal retrieve_sop_dly   : std_logic_vector(0 to c_retrieve_lat);
+  signal retrieve_eop_dly   : std_logic_vector(0 to c_retrieve_lat);
+
+  signal store_busy         : std_logic;
+  signal retrieve_busy      : std_logic;
+  signal retrieve_busy_reg  : std_logic;
+  signal nxt_retrieve_busy  : std_logic;
+  signal i_reorder_busy     : std_logic;
+  signal reorder_busy_reg   : std_logic;
+  signal nxt_reorder_busy   : std_logic;
+
+  signal nof_ch_in_reg      : natural;
+  signal nof_ch_sel_reg     : natural;
 
 begin
 
+  reorder_busy   <= i_reorder_busy;
+  nof_ch_in_reg  <= nof_ch_in  when rising_edge(dp_clk) and i_reorder_busy = '0';
+  nof_ch_sel_reg <= nof_ch_sel when rising_edge(dp_clk) and i_reorder_busy = '0';
+
+  output_nof_ch_in  <= nof_ch_in_reg;
+  output_nof_ch_sel <= nof_ch_sel_reg;
+
   u_store : entity work.reorder_store
   generic map (
     g_dsp_data_w  => g_dsp_data_w,
@@ -120,10 +152,11 @@ begin
     rst           => dp_rst,
     clk           => dp_clk,
     -- Dynamic reorder block size control
-    nof_ch_in     => nof_ch_in,
+    nof_ch_in     => nof_ch_in_reg,
     -- Streaming
-    input_sosi    => input_sosi,
+    input_sosi    => input_sosi_reg,
     -- Timing
+    store_busy    => store_busy,
     store_done    => store_done,
     -- Write store buffer control
     store_mosi    => store_mosi
@@ -169,6 +202,16 @@ begin
     out_level   => retrieve_en
   );
 
+  -- Determine reorder_busy
+  nxt_retrieve_busy <= '0' when ch_cnt = 0 and retrieve_en = '0' else '1';
+
+  retrieve_busy <= nxt_retrieve_busy or retrieve_busy_reg;
+
+  nxt_reorder_busy <= store_busy or retrieve_busy;
+
+  i_reorder_busy <= input_sosi.valid or nxt_reorder_busy or reorder_busy_reg;  -- using input_sosi.valid or sop is equivalent here
+
+  -- Registers
   p_reg : process (dp_clk, dp_rst)
   begin
     if dp_rst = '1' then
@@ -176,22 +219,29 @@ begin
       ch_cnt                                 <= 0;
       retrieve_sop_dly(1 to c_retrieve_lat)  <= (others => '0');
       retrieve_eop_dly(1 to c_retrieve_lat)  <= (others => '0');
+      retrieve_busy_reg                      <= '0';
+      reorder_busy_reg                       <= '0';
     elsif rising_edge(dp_clk) then
       -- Internal registers.
+      input_sosi_reg                         <= input_sosi;
+      info_sosi                              <= info_sosi_paged;
       ch_cnt                                 <= nxt_ch_cnt;
       retrieve_sop_dly(1 to c_retrieve_lat)  <= retrieve_sop_dly(0 to c_retrieve_lat - 1);
       retrieve_eop_dly(1 to c_retrieve_lat)  <= retrieve_eop_dly(0 to c_retrieve_lat - 1);
+      retrieve_busy_reg                      <= nxt_retrieve_busy;
+      reorder_busy_reg                       <= nxt_reorder_busy;
     end if;
   end process;
 
-  p_ch_cnt : process (retrieve_en, ch_cnt, nof_ch_sel)
+  -- Count nof_ch_sel clk cycles per output packet, to control col_select_miso.waitrequest
+  p_ch_cnt : process (retrieve_en, ch_cnt, nof_ch_sel_reg)
   begin
     nxt_ch_cnt <= ch_cnt;
     col_select_miso.waitrequest <= '1';
 
     if retrieve_en = '1' then
       col_select_miso.waitrequest <= '0';
-      if ch_cnt = nof_ch_sel - 1 then
+      if ch_cnt = nof_ch_sel_reg - 1 then
         nxt_ch_cnt <= 0;
       else
         nxt_ch_cnt <= ch_cnt + 1;
@@ -200,8 +250,8 @@ begin
   end process;
 
   -- Optional SS output frame control
-  retrieve_sop_dly(0) <= '1' when retrieve_en = '1' and ch_cnt = 0              else '0';
-  retrieve_eop_dly(0) <= '1' when retrieve_en = '1' and ch_cnt = nof_ch_sel - 1 else '0';
+  retrieve_sop_dly(0) <= '1' when retrieve_en = '1' and ch_cnt = 0                  else '0';
+  retrieve_eop_dly(0) <= '1' when retrieve_en = '1' and ch_cnt = nof_ch_sel_reg - 1 else '0';
 
   retrieve_sosi.re    <= RESIZE_DP_DSP_DATA(i_col_select_miso.rddata(                g_dsp_data_w - 1 downto 0));
   retrieve_sosi.im    <= RESIZE_DP_DSP_DATA(i_col_select_miso.rddata(c_nof_complex * g_dsp_data_w - 1 downto g_dsp_data_w));
@@ -210,14 +260,15 @@ begin
   -- Only set sop/eop when valid.
   retrieve_sosi.sop   <= retrieve_sop_dly(c_retrieve_lat) and i_col_select_miso.rdval;
   retrieve_sosi.eop   <= retrieve_eop_dly(c_retrieve_lat) and i_col_select_miso.rdval;
-  -- Page delay the input_sosi info (sync, BSN, channel at sop and err, empty at eop) and combine
-  -- it with the retrieved SS data to get the output_sosi
-  info_sop_wr_en <= input_sosi.sop & store_done;
-  info_eop_wr_en <= input_sosi.eop & store_done;
+
+  -- Page delay the input_sosi_reg info (sync, BSN, channel at sop and err, empty at eop) and
+  -- combine it with the retrieved SS data to get the output_sosi
+  info_sop_wr_en <= input_sosi_reg.sop & store_done;
+  info_eop_wr_en <= input_sosi_reg.eop & store_done;
 
   u_info_sosi : entity dp_lib.dp_paged_sop_eop_reg
   generic map (
-    g_nof_pages  => c_info_nof_pages
+    g_nof_pages => c_info_nof_pages
   )
   port map (
     rst         => dp_rst,
@@ -226,14 +277,13 @@ begin
     sop_wr_en   => info_sop_wr_en,
     eop_wr_en   => info_eop_wr_en,
     -- ST sink
-    snk_in      => input_sosi,
+    snk_in      => input_sosi_reg,
     -- ST source
     src_out     => info_sosi_paged
   );
 
   -- Account for retrieve rd latency is 1, for sop related info it is not
   -- critical that it arrives early, but for eop related info it is.
-  info_sosi <= info_sosi_paged when rising_edge(dp_clk);
   output_sosi <= func_dp_stream_combine_info_and_data(info_sosi, retrieve_sosi);
 
 end str;
-- 
GitLab