-
Eric Kooistra authoredEric Kooistra authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
reorder_row.vhd 9.89 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: Subband Select Reordering.
--
-- Description: For every clock cycle within a frame a different output
-- configuration can be created, based on the available inputs.
--
-- The selection buffer stores a set of selection words. Each
-- selection word defines the mapping of the inputs to the outputs
-- for a single clock cylce.
--
-- Remarks:
--
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_row is
generic (
g_dsp_data_w : natural := 16;
g_frame_size : natural := 256;
g_nof_inputs : natural := 8;
g_nof_outputs : natural := 16;
g_use_complex : boolean := true;
g_ram_init_file : string := "../../../src/data/select_buf"; -- or "UNUSED"
g_pipeline_in : natural := 1; -- pipeline in_data
g_pipeline_in_m : natural := 1; -- pipeline in_data for M-fold fan out
g_pipeline_out : natural := 1 -- pipeline out_data
);
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_reorder_mosi : in t_mem_mosi;
ram_ss_reorder_miso : out t_mem_miso;
-- Streaming
input_sosi_arr : in t_dp_sosi_arr(g_nof_inputs - 1 downto 0);
output_sosi_arr : out t_dp_sosi_arr(g_nof_outputs - 1 downto 0);
output_siso_arr : in t_dp_siso_arr(g_nof_outputs - 1 downto 0) := (others => c_dp_siso_rdy)
);
end reorder_row;
architecture str of reorder_row is
constant c_sel_buf_read_lat : natural := 1; -- Latency introduced by the counter.
constant c_tot_pipeline : natural := g_pipeline_in + g_pipeline_in_m + g_pipeline_out + c_sel_buf_read_lat;
constant c_select_w : natural := ceil_log2(g_nof_inputs);
constant c_select_word_w : natural := c_select_w * g_nof_outputs;
constant c_select_dat_w_mm : natural := sel_a_b(c_select_word_w <= c_word_w, c_select_word_w, c_word_w);
constant c_nof_mm_regs_per_sel : natural := 2**(true_log2(ceil_div(c_select_word_w, c_word_w)));
constant c_mem_nof_dat_mm : natural := 2**(true_log2(c_nof_mm_regs_per_sel)) * g_frame_size;
constant c_mem_dat_w_mm : natural := 2**(true_log2(c_select_dat_w_mm));
constant c_mem_dat_w_dp : natural := 2**(true_log2(c_select_word_w));
constant c_select_buf_mm : t_c_mem := (latency => 1,
adr_w => ceil_log2(c_mem_nof_dat_mm),
dat_w => c_mem_dat_w_mm,
nof_dat => c_mem_nof_dat_mm,
init_sl => '0');
constant c_select_buf_dp : t_c_mem := (latency => 1,
adr_w => ceil_log2(g_frame_size),
dat_w => c_mem_dat_w_dp,
nof_dat => g_frame_size,
init_sl => '0');
constant c_data_w : natural := g_dsp_data_w * c_nof_complex;
constant c_mem_ratio_w : natural := c_mem_dat_w_dp / c_mem_dat_w_mm;
type t_dp_sosi_2arr is array (integer range <>) of t_dp_sosi_arr(g_nof_inputs - 1 downto 0);
type reg_type is record
pipe_sosi_2arr : t_dp_sosi_2arr(c_tot_pipeline-1 downto 0);
output_sosi_arr : t_dp_sosi_arr(g_nof_outputs - 1 downto 0);
end record;
signal r, rin : reg_type;
signal reorder_in_dat : std_logic_vector(g_nof_inputs * c_data_w - 1 downto 0);
signal reorder_out_dat : std_logic_vector(g_nof_outputs * c_data_w - 1 downto 0);
signal reorder_select : std_logic_vector(c_mem_dat_w_dp - 1 downto 0);
--SIGNAL reorder_select : STD_LOGIC_VECTOR(g_nof_outputs*c_select_w-1 DOWNTO 0);
signal reorder_chan_cnt : std_logic_vector(c_select_buf_dp.adr_w - 1 downto 0);
begin
---------------------------------------------------------------
-- PREPARE THE INPUT DATA.
--
-- Use a delayed version of the input data to correct for the
-- delay that is introduced by the read latency of the
-- selection buffer.
---------------------------------------------------------------
gen_input : for I in g_nof_inputs - 1 downto 0 generate
use_complex : if g_use_complex generate
reorder_in_dat((I + 1) * c_data_w - 1 downto I * c_data_w) <=
r.pipe_sosi_2arr(0)(I).im(g_dsp_data_w - 1 downto 0) &
r.pipe_sosi_2arr(0)(I).re(g_dsp_data_w - 1 downto 0);
end generate;
use_data : if not g_use_complex generate
reorder_in_dat((I + 1) * c_data_w - 1 downto I * c_data_w) <=
r.pipe_sosi_2arr(0)(I).data(c_data_w - 1 downto 0);
end generate;
end generate;
---------------------------------------------------------------
-- EXECUTE SELECTION
--
-- Selection is performed based on the setting of the
-- reorder_select signal.
---------------------------------------------------------------
u_reorder : entity common_lib.common_select_m_symbols
generic map (
g_nof_input => g_nof_inputs,
g_nof_output => g_nof_outputs,
g_symbol_w => c_nof_complex * g_dsp_data_w,
g_pipeline_in => g_pipeline_in,
g_pipeline_in_m => g_pipeline_in_m,
g_pipeline_out => g_pipeline_out
)
port map (
rst => dp_rst,
clk => dp_clk,
in_data => reorder_in_dat,
in_select => reorder_select(g_nof_outputs * c_select_w - 1 downto 0),
out_data => reorder_out_dat
);
---------------------------------------------------------------
-- SELECTION BUFFER
--
-- Buffer containing the selection words for a complete frame.
---------------------------------------------------------------
u_select_buf : entity common_lib.common_ram_crw_crw_ratio
generic map(
g_ram_a => c_select_buf_mm,
g_ram_b => c_select_buf_dp,
g_init_file => g_ram_init_file
)
port map (
rst_a => mm_rst,
clk_a => mm_clk,
wr_en_a => ram_ss_reorder_mosi.wr,
wr_dat_a => ram_ss_reorder_mosi.wrdata(c_select_buf_mm.dat_w - 1 downto 0),
adr_a => ram_ss_reorder_mosi.address(c_select_buf_mm.adr_w - 1 downto 0),
rd_en_a => ram_ss_reorder_mosi.rd,
rd_dat_a => ram_ss_reorder_miso.rddata(c_select_buf_mm.dat_w - 1 downto 0),
rd_val_a => ram_ss_reorder_miso.rdval,
rst_b => dp_rst,
clk_b => dp_clk,
wr_en_b => '0',
wr_dat_b => (others => '0'),
adr_b => reorder_chan_cnt,
rd_dat_b => reorder_select,
rd_val_b => open
);
---------------------------------------------------------------
-- ADDRESS COUNTER
--
-- Counter that addresses the selection buffer
---------------------------------------------------------------
gen_cnt : if g_frame_size > 1 generate
u_adr_chn_cnt : entity common_lib.common_counter
generic map(
g_latency => 1,
g_init => 0,
g_width => c_select_buf_dp.adr_w,
g_max => g_frame_size
)
port map (
rst => dp_rst,
clk => dp_clk,
cnt_en => input_sosi_arr(0).valid,
cnt_clr => input_sosi_arr(0).eop,
count => reorder_chan_cnt
);
end generate;
gen_no_cnt : if g_frame_size = 1 generate
reorder_chan_cnt <= (others => '0');
end generate;
---------------------------------------------------------------
-- REGISTERING AND PIPELINING
--
-- This process takes care of registering the incoming SOSI
-- array and the pipelining for all SOSI control fields.
-- Also the data-output of the select_m_symbols block is merged
-- here with the rest of the pipelined SOSI signals.
---------------------------------------------------------------
comb : process(r, input_sosi_arr, reorder_out_dat)
variable v : reg_type;
-- Use intermediate variables to avoid too long code lines
variable v_re : std_logic_vector(g_dsp_data_w - 1 downto 0);
variable v_im : std_logic_vector(g_dsp_data_w - 1 downto 0);
begin
v := r;
v.pipe_sosi_2arr(0) := input_sosi_arr;
v.pipe_sosi_2arr(c_tot_pipeline-1 downto 1) := r.pipe_sosi_2arr(c_tot_pipeline-2 downto 0);
-- Merge data output to the outgoing SOSI record.
-- Assigning re,im is don't care when g_use_complex is false.
for I in g_nof_outputs - 1 downto 0 loop
v_im := reorder_out_dat((I + 1) * c_data_w - 1 downto I * c_data_w + g_dsp_data_w);
v_re := reorder_out_dat((I + 1) * c_data_w - g_dsp_data_w - 1 downto I * c_data_w);
v.output_sosi_arr(I) := r.pipe_sosi_2arr(c_tot_pipeline-1)(0);
v.output_sosi_arr(I).im := RESIZE_DP_DSP_DATA(v_im);
v.output_sosi_arr(I).re := RESIZE_DP_DSP_DATA(v_re);
end loop;
rin <= v;
end process comb;
regs : process(dp_clk)
begin
if rising_edge(dp_clk) then
r <= rin;
end if;
end process;
output_sosi_arr <= r.output_sosi_arr;
end str;