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