From 6ba1e7b555ed9881623da3d4eca24edd4507229c Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Wed, 9 Aug 2023 15:25:05 +0200 Subject: [PATCH] Support dynamic reorder block size control. --- .../reorder/src/vhdl/reorder_col_select.vhd | 69 ++++++++++--------- .../src/vhdl/reorder_col_wide_select.vhd | 25 ++++--- .../base/reorder/src/vhdl/reorder_store.vhd | 55 +++++++-------- 3 files changed, 81 insertions(+), 68 deletions(-) diff --git a/libraries/base/reorder/src/vhdl/reorder_col_select.vhd b/libraries/base/reorder/src/vhdl/reorder_col_select.vhd index 5e69d2e04f..dc2c4dcf33 100644 --- a/libraries/base/reorder/src/vhdl/reorder_col_select.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_col_select.vhd @@ -22,18 +22,27 @@ -- Author : R vd Walle -- Purpose: Reorder block of data in time -- Description: --- Select g_nof_ch_sel complex samples from an input block of g_nof_ch_in --- complex samples. The subband select map is arbitrary (any order and also --- duplicates) and can be set via the MM interface. +-- 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 +-- = g_nof_ch_in, but it can used with smaller reorder block sizes. -- The timing of sync and BSN is passed on in parallel. -- Remarks: --- . The g_nof_ch_sel can be <= g_nof_ch_in <= period size, where g_nof_ch_in --- is the number of valid samples from sop to eop. If g_nof_ch_in is equal to --- the period size then there are no data invalid cycles during a period. --- Note that if g_nof_ch_in is less than the period size, then g_nof_ch_sel --- can be larger than g_nof_ch_in to select channels multiple times. --- . The g_nof_ch_in defines the number of complex input data words in a data --- period, so 1 complex sample via sosi.im and sosi.re. +-- . 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 +-- 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 +-- no data invalid output_sosi.valid cycles during a period. +-- Note that if nof_ch_in is less than the period size, then nof_ch_sel +-- can be larger than nof_ch_in to select some channels multiple times. +-- . The nof_ch_in defines the number of (complex) input data words in a +-- data period, so 1 sample via sosi.data or via sosi.im and sosi.re, +-- dependent on g_use_complex. -- . Verified in tb_reorder_col_wide_row_select.vhd via reorder_col_wide_select -- that has g_nof_inputs instances of reorder_col_select. @@ -48,36 +57,38 @@ use technology_lib.technology_select_pkg.all; entity reorder_col_select is generic ( g_technology : natural := c_tech_select_default; - g_dsp_data_w : natural := 18; + g_dsp_data_w : natural := 18; -- complex data width, = c_data_w / 2 g_nof_ch_in : natural := 1024; - g_nof_ch_sel : natural := 12; -- g_nof_ch_sel < g_nof_ch_in + g_nof_ch_sel : natural := 12; g_use_complex : boolean := true ); port ( 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; + -- Memory Mapped - col_select_mosi : in t_mem_mosi; -- channel select control on DP clk - col_select_miso : out t_mem_miso := c_mem_miso_rst; -- only waitrequest is used + col_select_mosi : in t_mem_mosi; -- channel select control + col_select_miso : out t_mem_miso := c_mem_miso_rst; -- only used for waitrequest -- Streaming - input_sosi : in t_dp_sosi; -- complex input - - output_sosi : out t_dp_sosi -- selected complex output with flow control + input_sosi : in t_dp_sosi; + output_sosi : out t_dp_sosi ); end reorder_col_select; - architecture str of reorder_col_select is + constant c_data_w : natural := c_nof_complex * g_dsp_data_w; constant c_store_buf : t_c_mem := (latency => 1, adr_w => ceil_log2(g_nof_ch_in), - dat_w => c_nof_complex * g_dsp_data_w, + dat_w => c_data_w, nof_dat => g_nof_ch_in, init_sl => '0'); -- ST side : stat_mosi - constant c_data_nof_pages : natural := 2; -- fixed dual page SS 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 @@ -98,7 +109,6 @@ architecture str of reorder_col_select is signal retrieve_sop_dly : std_logic_vector(0 to c_retrieve_lat); signal retrieve_eop_dly : std_logic_vector(0 to c_retrieve_lat); - begin u_store : entity work.reorder_store @@ -110,13 +120,12 @@ begin port map ( rst => dp_rst, clk => dp_clk, - + -- Dynamic reorder block size control + nof_ch_in => nof_ch_in, -- Streaming input_sosi => input_sosi, - -- Timing store_done => store_done, - -- Write store buffer control store_mosi => store_mosi ); @@ -146,7 +155,6 @@ begin rd_val => i_col_select_miso.rdval ); - -- Enable retrieve when a block has been stored, disable retrieve when the block has been output u_retrieve_en : entity common_lib.common_switch generic map ( @@ -178,29 +186,28 @@ begin end if; end process; - p_ch_cnt : process (retrieve_en, ch_cnt) + p_ch_cnt : process (retrieve_en, ch_cnt, nof_ch_sel) begin nxt_ch_cnt <= ch_cnt; col_select_miso.waitrequest <= '1'; if retrieve_en = '1' then col_select_miso.waitrequest <= '0'; - if ch_cnt = g_nof_ch_sel - 1 then + if ch_cnt = nof_ch_sel - 1 then nxt_ch_cnt <= 0; else nxt_ch_cnt <= ch_cnt + 1; end if; end if; - 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 = g_nof_ch_sel - 1 else '0'; + retrieve_eop_dly(0) <= '1' when retrieve_en = '1' and ch_cnt = nof_ch_sel - 1 else '0'; - retrieve_sosi.re <= RESIZE_DP_DSP_DATA(i_col_select_miso.rddata( g_dsp_data_w - 1 downto 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)); - retrieve_sosi.data <= RESIZE_DP_DATA(i_col_select_miso.rddata( c_nof_complex * g_dsp_data_w - 1 downto 0)); + retrieve_sosi.data <= RESIZE_DP_DATA(i_col_select_miso.rddata(c_data_w - 1 downto 0)); retrieve_sosi.valid <= i_col_select_miso.rdval; retrieve_sosi.sop <= retrieve_sop_dly(c_retrieve_lat) and i_col_select_miso.rdval; -- Only set sop/eop when valid. retrieve_sosi.eop <= retrieve_eop_dly(c_retrieve_lat) and i_col_select_miso.rdval; diff --git a/libraries/base/reorder/src/vhdl/reorder_col_wide_select.vhd b/libraries/base/reorder/src/vhdl/reorder_col_wide_select.vhd index bb76367782..5184a494b5 100644 --- a/libraries/base/reorder/src/vhdl/reorder_col_wide_select.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_col_wide_select.vhd @@ -23,7 +23,7 @@ -- Purpose: Select and/or reorder data on multiple streams. -- -- Description: --- Array of reorder_col_select instances +-- Array of reorder_col_select instances. -- -- Remarks: -- @@ -40,7 +40,7 @@ entity reorder_col_wide_select is generic ( g_technology : natural := c_tech_select_default; g_nof_inputs : natural := 6; - g_dsp_data_w : natural := 18; + g_dsp_data_w : natural := 18; -- complex data width, = c_data_w / 2 g_nof_ch_in : natural := 1024; g_nof_ch_sel : natural := 12; -- g_nof_ch_sel < g_nof_ch_in g_use_complex : boolean := true @@ -49,15 +49,17 @@ entity reorder_col_wide_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; + -- Memory Mapped col_select_mosi : in t_mem_mosi; -- channel select control col_select_miso : out t_mem_miso; -- only used for waitrequest -- Streaming - input_sosi_arr : in t_dp_sosi_arr(g_nof_inputs - 1 downto 0); -- complex input - input_siso_arr : out t_dp_siso_arr(g_nof_inputs - 1 downto 0) := (others => c_dp_siso_rdy); -- complex input - - output_sosi_arr : out t_dp_sosi_arr(g_nof_inputs - 1 downto 0) -- selected complex output with flow control + input_sosi_arr : in t_dp_sosi_arr(g_nof_inputs - 1 downto 0); + output_sosi_arr : out t_dp_sosi_arr(g_nof_inputs - 1 downto 0) ); end reorder_col_wide_select; @@ -69,9 +71,9 @@ begin col_select_miso <= col_select_miso_arr(0); -- All inputs have the same mosi/miso - --------------------------------------------------------------- - -- INSTANTIATE MULTIPLE SINGLE CHANNEL SUBBAND SELECT UNITS - --------------------------------------------------------------- + -- Instantiate reorder_col_select for multiple streams in parallel, to + -- reorder blocks in each stream in time. The same reordering is applied + -- by col_select_mosi to each stream. gen_nof_input : for I in 0 to g_nof_inputs - 1 generate u_reorder_col_select : entity work.reorder_col_select generic map ( @@ -85,13 +87,16 @@ begin dp_rst => dp_rst, dp_clk => dp_clk, + -- Dynamic reorder block size control, same for all streams + nof_ch_in => nof_ch_in, + nof_ch_sel => nof_ch_sel, + -- Memory Mapped col_select_mosi => col_select_mosi, col_select_miso => col_select_miso_arr(I), -- Streaming input_sosi => input_sosi_arr(I), - output_sosi => output_sosi_arr(I) ); end generate; diff --git a/libraries/base/reorder/src/vhdl/reorder_store.vhd b/libraries/base/reorder/src/vhdl/reorder_store.vhd index 63a3f263bd..924bfb69b3 100644 --- a/libraries/base/reorder/src/vhdl/reorder_store.vhd +++ b/libraries/base/reorder/src/vhdl/reorder_store.vhd @@ -26,46 +26,50 @@ use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use dp_lib.dp_stream_pkg.all; --- Purpose: Controller that store blocks of g_nof_ch_in complex input data +-- Purpose: Controller that store blocks of nof_ch_in (complex) input data -- words in a dual page data buffer -- Description: --- Write databuf control for g_nof_ch_in complex input data words and pulse --- store_done for each g_nof_ch_in data words that have been written. +-- Write databuf control for nof_ch_in (complex) input data words and pulse +-- store_done for each nof_ch_in data words that have been written. +-- Maximum size for the dual page buffer is g_nof_ch_in. Default nof_ch_in +-- = g_nof_ch_in, but it can be used with smaller reorder block sizes. -- Remarks: --- . The SS stores the complex input data as concatenated data = im & re with --- data width 2 * g_dsp_data_w. --- . The reorder_col does not use input sop and eop, because it uses a ch_cnt. Hence --- the input_sosi only needs to carry im, re and valid, the sop and eop are --- ignored. The ch_cnt is needed anyway to set the store_mosi.address. The --- g_nof_ch_in defines the number of valid per input block, so from sop to --- eop. The reorder_store assumes that the first valid corresponds to a sop. The --- ch_cnt restarts at the and of a block, so when ch_cnt = g_nof_ch_in-1. --- . The store_done signal occurs when the last data of the block is being --- written, so 1 cycle after the input_sosi.eop. +-- . The reorder_store stores the complex input_sosi.re,im as concatenated +-- data = im & re with data width c_data_w, when g_use_complex = true. When +-- g_use_complex = false it stores c_data_w width of the input_sosi.data. +-- . The reorder_col does not use input_sosi.sop and eop, because it uses a +-- ch_cnt. Hence the input_sosi only needs to carry data, im, re and valid, +-- the input_sosi.sop and eop are ignored. The ch_cnt is needed anyway to +-- set the store_mosi.address. The nof_ch_in defines the number of valid +-- per input block, so from input_sosi.sop to input_sosi.eop. The +-- reorder_store assumes that the first input_sosi.valid corresponds to a +-- input_sosi.sop. The ch_cnt restarts at the and of a block, so when +-- ch_cnt = nof_ch_in-1. +-- . The store_done signal occurs when the last data of the input_sosi block +-- is being written, so 1 cycle after the input_sosi.eop. entity reorder_store is generic ( - g_dsp_data_w : natural; -- = width of sosi.im = width of sosi.re + g_dsp_data_w : natural; -- complex data width, = c_data_w / 2 g_nof_ch_in : natural; -- = nof valid per input block (sop to eop) - g_use_complex : boolean := true -- = TRUE --> use RE and IM field. FALSE = use DATA field + g_use_complex : boolean := true -- use input_sosi.re, im when true, else input_sosi.data ); port ( rst : in std_logic; 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; -- Streaming input_sosi : in t_dp_sosi; - -- Timing store_done : out std_logic; - -- Write databuf control store_mosi : out t_mem_mosi ); end reorder_store; - architecture rtl of reorder_store is + constant c_data_w : natural := c_nof_complex * g_dsp_data_w; signal ch_cnt : integer range 0 to g_nof_ch_in - 1; signal nxt_ch_cnt : integer; @@ -74,9 +78,7 @@ architecture rtl of reorder_store is signal nxt_store_mosi : t_mem_mosi := c_mem_mosi_rst; signal nxt_store_done : std_logic; - begin - store_mosi <= i_store_mosi; p_reg : process (clk, rst) @@ -96,13 +98,13 @@ begin end if; end process; - p_ch_cnt : process (ch_cnt, input_sosi) + p_ch_cnt : process (ch_cnt, input_sosi, nof_ch_in) begin nxt_store_done <= '0'; nxt_ch_cnt <= ch_cnt; if input_sosi.valid = '1' then - if ch_cnt = g_nof_ch_in - 1 then + if ch_cnt = nof_ch_in - 1 then nxt_store_done <= '1'; nxt_ch_cnt <= 0; else @@ -117,12 +119,11 @@ begin -- Use complex data fields gen_complex : if g_use_complex generate - nxt_store_mosi.wrdata <= RESIZE_MEM_DATA(input_sosi.im(g_dsp_data_w - 1 downto 0) & input_sosi.re(g_dsp_data_w - 1 downto 0)) when input_sosi.valid = '1' else i_store_mosi.wrdata; + nxt_store_mosi.wrdata <= RESIZE_MEM_DATA(input_sosi.im(g_dsp_data_w - 1 downto 0) & input_sosi.re(g_dsp_data_w - 1 downto 0)) when input_sosi.valid = '1' else i_store_mosi.wrdata; end generate; -- Use regular data field - gen_non_complex : if not(g_use_complex) generate - nxt_store_mosi.wrdata <= RESIZE_MEM_DATA(input_sosi.data(c_nof_complex * g_dsp_data_w - 1 downto 0)) when input_sosi.valid = '1' else i_store_mosi.wrdata; + gen_data : if not(g_use_complex) generate + nxt_store_mosi.wrdata <= RESIZE_MEM_DATA(input_sosi.data(c_data_w - 1 downto 0)) when input_sosi.valid = '1' else i_store_mosi.wrdata; end generate; - end rtl; -- GitLab