Skip to content
Snippets Groups Projects
Commit 6ba1e7b5 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Support dynamic reorder block size control.

parent 7cc85ba6
No related branches found
No related tags found
1 merge request!339Resolve L2SDP-959
Pipeline #55485 passed
......@@ -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.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;
......
......@@ -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;
......
......@@ -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
......@@ -121,8 +123,7 @@ begin
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;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment