-
Eric Kooistra authoredEric Kooistra authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
reorder_col.vhd 10.65 KiB
-------------------------------------------------------------------------------
--
-- Copyright (C) 2011
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
-- Purpose: Reorder packet
-- 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.
-- 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. In LOFAR a subband sample was defined as a dual pol subband, so a
-- pair of complex samples, but here instead the subband is defined as a
-- single signal path sample, so 1 complex sample via sosi.im and sosi.re.
-- . In LOFAR the channel select buffer was dual page, to ensure that the page
-- switch happens aligned with the sync. However typically the select buffer
-- only needs to be set once and remains fixed during a measurement.
-- Therefore the channel select buffer can be a single page memory.
-- . In LOFAR the selected channels were also output time multiplexed. This
-- was possible because g_nof_ch_sel <= g_nof_ch_in/2. Here the output is not
-- time multiplexed. If time multiplexing is needed then a separate component
-- needs to be used for this. For this purpose the reorder_retrieve streaming
-- source supports the ready signal. Typically output_siso.ready='1', but
-- when g_nof_ch_sel < g_nof_ch_in/2, then a toggling output_siso.ready can
-- be used to multiplex this reorder_col output with another reorder_col output stream.
-- . The reorder_col streaming sink does not support the input_siso signal, because it
-- is assumed that the reorder_col source is always fast enough. The reorder_col sink could
-- support the input_siso signal, e.g. based on store_done and retrieve_done.
library IEEE, common_lib, dp_lib;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use common_lib.common_pkg.all;
use common_lib.common_mem_pkg.all;
use dp_lib.dp_stream_pkg.all;
entity reorder_col is
generic (
-- when true adapt output RL to 1 else the output RL is equal to c_retrieve_lat=2 which
-- is fine if no flow control is needed.
g_use_output_rl_adapter : boolean := false;
g_dsp_data_w : natural := 18; -- complex data width, = c_data_w / 2
g_nof_ch_in : natural := 512;
g_nof_ch_sel : natural := 252; -- g_nof_ch_sel < g_nof_ch_in
g_select_file_name : string := "UNUSED";
g_use_complex : boolean := true
);
port (
mm_rst : in std_logic;
mm_clk : in std_logic;
dp_rst : in std_logic;
dp_clk : in std_logic;
-- Memory Mapped
ram_ss_ss_mosi : in t_mem_mosi; -- channel select control
ram_ss_ss_miso : out t_mem_miso;
-- Streaming
input_sosi : in t_dp_sosi; -- complex input
input_siso : out t_dp_siso; -- complex input
output_sosi : out t_dp_sosi; -- selected complex output with flow control
output_siso : in t_dp_siso := c_dp_siso_rdy
);
end reorder_col;
architecture str of reorder_col 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_data_w,
nof_dat => g_nof_ch_in,
init_sl => '0'); -- ST side : stat_mosi
constant c_select_buf : t_c_mem := (latency => 1,
adr_w => ceil_log2(g_nof_ch_sel),
dat_w => ceil_log2(g_nof_ch_in),
nof_dat => g_nof_ch_sel,
init_sl => '0');
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_select_buf.latency + c_store_buf.latency; -- = 2
-- force output ready latency (RL) from 2 -> 1 or leave it at 2
constant c_output_rl : natural := sel_a_b(g_use_output_rl_adapter, 1, c_retrieve_lat);
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 : t_dp_sosi;
signal store_mosi : t_mem_mosi;
signal store_done : std_logic;
signal retrieve_mosi : t_mem_mosi := c_mem_mosi_rst;
signal retrieve_miso : t_mem_miso := c_mem_miso_rst;
signal retrieve_done : std_logic;
signal select_mosi : t_mem_mosi := c_mem_mosi_rst;
signal select_miso : t_mem_miso := c_mem_miso_rst;
signal retrieve_sosi : t_dp_sosi;
signal retrieve_siso : t_dp_siso;
signal ss_sosi : t_dp_sosi;
signal ss_siso : t_dp_siso;
begin
-----------------------------------------------------------------------------
-- Throttle the incoming streams so they provide a consistent packet flow
-- (no bursting) by enforcing a minimum period of g_nof_ch_sel
-----------------------------------------------------------------------------
u_dp_throttle_sop : entity dp_lib.dp_throttle_sop
generic map (
g_period => g_nof_ch_sel
)
port map (
rst => dp_rst,
clk => dp_clk,
snk_out => input_siso,
snk_in => input_sosi
);
u_store : entity work.reorder_store
generic map (
g_dsp_data_w => g_dsp_data_w,
g_nof_ch_in => g_nof_ch_in,
g_use_complex => g_use_complex
)
port map (
rst => dp_rst,
clk => dp_clk,
-- Streaming
input_sosi => input_sosi,
-- Timing
store_done => store_done,
-- Write store buffer control
store_mosi => store_mosi
);
u_store_buf : entity common_lib.common_paged_ram_r_w
generic map (
g_str => "use_adr",
g_data_w => c_store_buf.dat_w,
g_nof_pages => c_data_nof_pages,
g_page_sz => c_store_buf.nof_dat,
g_wr_start_page => 0,
g_rd_start_page => 0,
g_rd_latency => 1
)
port map (
rst => dp_rst,
clk => dp_clk,
wr_next_page => store_done,
wr_adr => store_mosi.address(c_store_buf.adr_w - 1 downto 0),
wr_en => store_mosi.wr,
wr_dat => store_mosi.wrdata(c_store_buf.dat_w - 1 downto 0),
rd_next_page => retrieve_done,
rd_adr => retrieve_mosi.address(c_store_buf.adr_w - 1 downto 0),
rd_en => retrieve_mosi.rd,
rd_dat => retrieve_miso.rddata(c_store_buf.dat_w - 1 downto 0),
rd_val => retrieve_miso.rdval
);
u_select_buf : entity common_lib.common_ram_crw_crw
generic map (
g_ram => c_select_buf,
g_init_file => g_select_file_name
)
port map (
-- MM side
rst_a => mm_rst,
clk_a => mm_clk,
wr_en_a => ram_ss_ss_mosi.wr,
wr_dat_a => ram_ss_ss_mosi.wrdata(c_select_buf.dat_w - 1 downto 0),
adr_a => ram_ss_ss_mosi.address(c_select_buf.adr_w - 1 downto 0),
rd_en_a => ram_ss_ss_mosi.rd,
rd_dat_a => ram_ss_ss_miso.rddata(c_select_buf.dat_w - 1 downto 0),
rd_val_a => ram_ss_ss_miso.rdval,
-- ST side
rst_b => dp_rst,
clk_b => dp_clk,
wr_en_b => select_mosi.wr,
wr_dat_b => select_mosi.wrdata(c_select_buf.dat_w - 1 downto 0),
adr_b => select_mosi.address(c_select_buf.adr_w - 1 downto 0),
rd_en_b => select_mosi.rd,
rd_dat_b => select_miso.rddata(c_select_buf.dat_w - 1 downto 0),
rd_val_b => select_miso.rdval
);
u_retrieve : entity work.reorder_retrieve
generic map (
g_dsp_data_w => g_dsp_data_w,
g_nof_ch_in => g_nof_ch_in,
g_nof_ch_sel => g_nof_ch_sel
)
port map (
rst => dp_rst,
clk => dp_clk,
-- Timing
store_done => store_done,
-- Read store_buf control
retrieve_mosi => retrieve_mosi,
retrieve_miso => retrieve_miso,
retrieve_done => retrieve_done,
-- Read select_buf control
select_mosi => select_mosi,
select_miso => select_miso,
-- Streaming
output_sosi => retrieve_sosi,
output_siso => retrieve_siso
);
u_rl : entity dp_lib.dp_latency_adapter -- defaults to wires when c_output_rl = c_retrieve_lat
generic map (
g_in_latency => c_retrieve_lat,
g_out_latency => c_output_rl
)
port map (
rst => dp_rst,
clk => dp_clk,
-- ST sink
snk_out => retrieve_siso,
snk_in => retrieve_sosi,
-- ST source
src_in => ss_siso,
src_out => ss_sosi
);
-- 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;
u_info_sosi : entity dp_lib.dp_paged_sop_eop_reg
generic map (
g_nof_pages => c_info_nof_pages
)
port map (
rst => dp_rst,
clk => dp_clk,
-- page write enable ctrl
sop_wr_en => info_sop_wr_en,
eop_wr_en => info_eop_wr_en,
-- ST sink
snk_in => input_sosi,
-- ST source
src_out => info_sosi
);
output_sosi <= func_dp_stream_combine_info_and_data(info_sosi, ss_sosi);
ss_siso <= output_siso;
end str;