From bb673e6cbf22645249c1e18adcc954b7b9b4fbe7 Mon Sep 17 00:00:00 2001 From: Pepping <pepping> Date: Thu, 25 Jun 2015 10:34:13 +0000 Subject: [PATCH] Svn copy from $UNB --- .../base/reorder/src/vhdl/reorder_col.vhd | 283 ++++++++++++++++++ .../reorder/src/vhdl/reorder_col_wide.vhd | 129 ++++++++ .../base/reorder/src/vhdl/reorder_matrix.vhd | 200 +++++++++++++ .../reorder/src/vhdl/reorder_retreive.vhd | 169 +++++++++++ .../base/reorder/src/vhdl/reorder_store.vhd | 128 ++++++++ 5 files changed, 909 insertions(+) create mode 100644 libraries/base/reorder/src/vhdl/reorder_col.vhd create mode 100644 libraries/base/reorder/src/vhdl/reorder_col_wide.vhd create mode 100644 libraries/base/reorder/src/vhdl/reorder_matrix.vhd create mode 100644 libraries/base/reorder/src/vhdl/reorder_retreive.vhd create mode 100644 libraries/base/reorder/src/vhdl/reorder_store.vhd diff --git a/libraries/base/reorder/src/vhdl/reorder_col.vhd b/libraries/base/reorder/src/vhdl/reorder_col.vhd new file mode 100644 index 0000000000..17e7f250ad --- /dev/null +++ b/libraries/base/reorder/src/vhdl/reorder_col.vhd @@ -0,0 +1,283 @@ +------------------------------------------------------------------------------- +-- +-- 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/>. +-- +------------------------------------------------------------------------------- + +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; + +-- Purpose: Subband select +-- 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 ss_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 SS output with another SS output stream. +-- . The SS streaming sink does not support the input_siso signal, because it +-- is assumed that the SS source is always fast enough. The SS sink could +-- support the input_siso signal, e.g. based on store_done and retrieve_done. + +ENTITY ss IS + GENERIC ( + g_use_output_rl_adapter : BOOLEAN := FALSE; -- 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_dsp_data_w : NATURAL := 18; + 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 ss; + + +ARCHITECTURE str OF ss IS + + 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, + 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 + CONSTANT c_output_rl : NATURAL := sel_a_b(g_use_output_rl_adapter, 1, c_retrieve_lat); -- force SS RL from 2 -> 1 or leave it at 2 + + 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.ss_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.ss_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; + diff --git a/libraries/base/reorder/src/vhdl/reorder_col_wide.vhd b/libraries/base/reorder/src/vhdl/reorder_col_wide.vhd new file mode 100644 index 0000000000..263ea831b6 --- /dev/null +++ b/libraries/base/reorder/src/vhdl/reorder_col_wide.vhd @@ -0,0 +1,129 @@ +------------------------------------------------------------------------------- +-- +-- 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/>. +-- +------------------------------------------------------------------------------- + +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; + +-- Purpose: Select and/or reorder data on multiple streams. +-- +-- Description: +-- Subband select unit that handles a stream that consists of +-- multiple (g_wb_factor) input streams. +-- It assumes that the g_nof_ch_in input channels are equally +-- distributed over the g_wb_factor input streams. +-- +-- +-- Remarks: +-- + +ENTITY ss_wide IS + GENERIC ( + g_wb_factor : NATURAL := 4; + g_dsp_data_w : NATURAL := 18; + g_nof_ch_in : NATURAL := 256; + g_nof_ch_sel : NATURAL := 192; -- g_nof_ch_sel < g_nof_ch_in + g_select_file_prefix : 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_wide_mosi : IN t_mem_mosi; -- channel select control + ram_ss_ss_wide_miso : OUT t_mem_miso; + + -- Streaming + input_sosi_arr : IN t_dp_sosi_arr(g_wb_factor-1 DOWNTO 0); -- complex input + input_siso_arr : OUT t_dp_siso_arr(g_wb_factor-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); -- complex input + + output_sosi_arr : OUT t_dp_sosi_arr(g_wb_factor-1 DOWNTO 0); -- selected complex output with flow control + output_siso_arr : IN t_dp_siso_arr(g_wb_factor-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy) + ); +END ss_wide; + +ARCHITECTURE str OF ss_wide IS + + CONSTANT c_mem_addr_w : NATURAL := ceil_log2(g_nof_ch_sel); + CONSTANT c_nof_ch_in : NATURAL := g_nof_ch_in; + CONSTANT c_nof_ch_sel : NATURAL := g_nof_ch_sel; + + SIGNAL ram_ss_ss_wide_mosi_arr : t_mem_mosi_arr(g_wb_factor-1 DOWNTO 0); + SIGNAL ram_ss_ss_wide_miso_arr : t_mem_miso_arr(g_wb_factor-1 DOWNTO 0) := (OTHERS => c_mem_miso_rst); + +BEGIN + + --------------------------------------------------------------- + -- COMBINE MEMORY MAPPED INTERFACES + --------------------------------------------------------------- + -- Combine the internal array of mm interfaces for the selection + -- memory to one array that is connected to the port of the ss_wide wunit + u_mem_mux_select : entity common_lib.common_mem_mux + generic map ( + g_nof_mosi => g_wb_factor, + g_mult_addr_w => c_mem_addr_w + ) + port map ( + mosi => ram_ss_ss_wide_mosi, + miso => ram_ss_ss_wide_miso, + mosi_arr => ram_ss_ss_wide_mosi_arr, + miso_arr => ram_ss_ss_wide_miso_arr + ); + + --------------------------------------------------------------- + -- INSTANTIATE MULTIPLE SINGLE CHANNEL SUBBAND SELECT UNITS + --------------------------------------------------------------- + gen_ss_singles : FOR I IN 0 TO g_wb_factor-1 GENERATE + u_single_ss : ENTITY work.ss + GENERIC MAP ( + g_dsp_data_w => g_dsp_data_w, + g_nof_ch_in => c_nof_ch_in, + g_nof_ch_sel => c_nof_ch_sel, + g_select_file_name => sel_a_b(g_select_file_prefix="UNUSED", "UNUSED", g_select_file_prefix & "_" & NATURAL'IMAGE(I) & ".hex"), + g_use_complex => g_use_complex + ) + PORT MAP ( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + + -- Memory Mapped + ram_ss_ss_mosi => ram_ss_ss_wide_mosi_arr(I), + ram_ss_ss_miso => ram_ss_ss_wide_miso_arr(I), + + -- Streaming + input_sosi => input_sosi_arr(I), + input_siso => input_siso_arr(I), + + output_sosi => output_sosi_arr(I), + output_siso => output_siso_arr(I) + ); + END GENERATE; + +END str; + diff --git a/libraries/base/reorder/src/vhdl/reorder_matrix.vhd b/libraries/base/reorder/src/vhdl/reorder_matrix.vhd new file mode 100644 index 0000000000..c188e963c4 --- /dev/null +++ b/libraries/base/reorder/src/vhdl/reorder_matrix.vhd @@ -0,0 +1,200 @@ +------------------------------------------------------------------------------- +-- +-- 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/>. +-- +------------------------------------------------------------------------------- + +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; + +-- Purpose: Select a subset of the input data. Reorder the input data. Redistribute data over multiple outputs. +-- +-- Description: This unit creates a parallel set of output streams where each +-- stream can contain data from any input stream. +-- +-- The selection mechanism is based on three stages: +-- +-- 1. Input Reorder Stage +-- 2. Selection Stage +-- 3. Output Reorder Stage +-- +-- 1. The input reorder stage redirects the data (within a frame) of +-- the g_nof_inputs input streams to a set of g_nof_internals +-- streams, based on the settings of the selection buffer. The +-- selection buffer contains a selection setting for every clock +-- cycle of a frame. +-- +-- 2. The selection stage creates output streams that can contain any +-- data in any order from the accordingly input streams. +-- +-- 3. The output reorder stage performs another reordering stage on +-- the output of the selection stage. + +-- +-- Remarks: +-- + +ENTITY ss_parallel IS + GENERIC ( + g_nof_inputs : NATURAL := 24; + g_nof_internals : NATURAL := 64; + g_nof_outputs : NATURAL := 64; + g_dsp_data_w : NATURAL := 8; + g_frame_size_in : NATURAL := 64; + g_frame_size_out : NATURAL := 128; + g_reorder_in_file_name : STRING := "UNUSED"; -- path_to_file.hex + g_ss_wide_file_prefix : STRING := "UNUSED"; -- path_to_file + g_reorder_out_file_name : STRING := "UNUSED" -- path_to_file.hex + ); + 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_in_mosi : IN t_mem_mosi; + ram_ss_reorder_in_miso : OUT t_mem_miso; + ram_ss_reorder_out_mosi : IN t_mem_mosi; + ram_ss_reorder_out_miso : OUT t_mem_miso; + ram_ss_ss_wide_mosi : IN t_mem_mosi; + ram_ss_ss_wide_miso : OUT t_mem_miso; + + -- Streaming + input_sosi_arr : IN t_dp_sosi_arr(g_nof_inputs -1 DOWNTO 0); + input_siso_arr : OUT t_dp_siso_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 ss_parallel; + +ARCHITECTURE str OF ss_parallel IS + + SIGNAL ss_wide_in_sosi_arr : t_dp_sosi_arr(g_nof_internals-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL ss_wide_out_sosi_arr : t_dp_sosi_arr(g_nof_internals-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + +BEGIN + + ----------------------------------------------------------------------------- + -- Throttle the incoming streams so they provide a consistent packet flow + -- (no bursting) by enforcing a minimum period of g_frame_size_out + ----------------------------------------------------------------------------- + gen_dp_throttle_sop : FOR i IN 0 TO g_nof_inputs-1 GENERATE + u_dp_throttle_sop : ENTITY dp_lib.dp_throttle_sop + GENERIC MAP ( + g_period => g_frame_size_out + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + snk_out => input_siso_arr(i), + snk_in => input_sosi_arr(i) + ); + END GENERATE; + + ----------------------------------------------------------------------------- + -- Reorder input streams + ----------------------------------------------------------------------------- + u_input_reorder : ENTITY work.ss_reorder + GENERIC MAP( + g_nof_inputs => g_nof_inputs, + g_nof_outputs => g_nof_internals, + g_dsp_data_w => g_dsp_data_w, + g_frame_size => g_frame_size_in, + g_ram_init_file => g_reorder_in_file_name, + g_pipeline_in => 1, + g_pipeline_in_m => 1, + g_pipeline_out => 1 + ) + PORT MAP( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + + -- Memory Mapped + ram_ss_reorder_mosi => ram_ss_reorder_in_mosi, + ram_ss_reorder_miso => ram_ss_reorder_in_miso, + + -- Streaming + input_sosi_arr => input_sosi_arr, + output_sosi_arr => ss_wide_in_sosi_arr + ); + + ----------------------------------------------------------------------------- + -- Serial word selection per stream + ----------------------------------------------------------------------------- + u_ss_wide : ENTITY work.ss_wide + GENERIC MAP ( + g_wb_factor => g_nof_internals, + g_dsp_data_w => g_dsp_data_w, + g_nof_ch_in => g_frame_size_in, + g_nof_ch_sel => g_frame_size_out, + g_select_file_prefix => g_ss_wide_file_prefix + ) + PORT MAP ( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + + -- Memory Mapped + ram_ss_ss_wide_mosi => ram_ss_ss_wide_mosi, + ram_ss_ss_wide_miso => ram_ss_ss_wide_miso, + + -- Streaming + input_sosi_arr => ss_wide_in_sosi_arr, + input_siso_arr => OPEN, + output_sosi_arr => ss_wide_out_sosi_arr + ); + + ----------------------------------------------------------------------------- + -- Reorder output streams + ----------------------------------------------------------------------------- + u_output_reorder : ENTITY work.ss_reorder + GENERIC MAP( + g_nof_inputs => g_nof_internals, + g_nof_outputs => g_nof_outputs, + g_dsp_data_w => g_dsp_data_w, + g_frame_size => g_frame_size_out, + g_ram_init_file => g_reorder_out_file_name, + g_pipeline_in => 1, + g_pipeline_in_m => 1, + g_pipeline_out => 1 + ) + PORT MAP( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + + -- Memory Mapped + ram_ss_reorder_mosi => ram_ss_reorder_out_mosi, + ram_ss_reorder_miso => ram_ss_reorder_out_miso, + + -- Streaming + input_sosi_arr => ss_wide_out_sosi_arr, + output_sosi_arr => output_sosi_arr + ); + +END str; + diff --git a/libraries/base/reorder/src/vhdl/reorder_retreive.vhd b/libraries/base/reorder/src/vhdl/reorder_retreive.vhd new file mode 100644 index 0000000000..80addc510d --- /dev/null +++ b/libraries/base/reorder/src/vhdl/reorder_retreive.vhd @@ -0,0 +1,169 @@ +------------------------------------------------------------------------------- +-- +-- 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/>. +-- +------------------------------------------------------------------------------- + +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; + +-- Purpose: Retrieve blocks of g_nof_ch_sel complex data words from a dual +-- page data buffer +-- Description: +-- The retrieve control uses a channel select buffer to know the order +-- in which the g_nof_ch_sel complex data words have to be retrieved from the +-- dual page input data buffer. The order is arbitrary and the same channel +-- may be selected multiple times. +-- Remarks: +-- . Typcially output_siso.ready='1'. When g_nof_ch_sel < g_nof_ch_in/2, then a +-- toggling output_siso.ready can be used to multiplex this SS retrieve output +-- with another SS retrieve output stream. +-- . The retrieve_done signal occurs when the last data of the block is read +-- requested, so 1 cycle before the output_sosi.eop. +-- . The timing of the ch_cnt for the retrieve_mosi.address is such that the +-- SS can store a frame and retrieve it immediately in any order, so worst +-- case the last stored data can be retrieved first. + + +ENTITY ss_retrieve IS + GENERIC ( + g_dsp_data_w : NATURAL; + g_nof_ch_in : NATURAL; + g_nof_ch_sel : NATURAL + ); + PORT ( + rst : IN STD_LOGIC; + clk : IN STD_LOGIC; + + -- Timing + store_done : IN STD_LOGIC; + + -- Read databuf control + retrieve_mosi : OUT t_mem_mosi; + retrieve_miso : IN t_mem_miso; + retrieve_done : OUT STD_LOGIC; + + -- Read selectbuf control + select_mosi : OUT t_mem_mosi; + select_miso : IN t_mem_miso; + + -- Streaming + output_sosi : OUT t_dp_sosi; + output_siso : IN t_dp_siso := c_dp_siso_rdy + ); +END ss_retrieve; + + +ARCHITECTURE rtl OF ss_retrieve IS + + CONSTANT c_retrieve_lat : NATURAL := 2; -- fixed 1 for select buf read + 1 for store buf read + + SIGNAL ch_cnt : INTEGER RANGE 0 TO g_nof_ch_sel-1; + SIGNAL nxt_ch_cnt : INTEGER; + + SIGNAL retrieve_en : STD_LOGIC; + SIGNAL prev_retrieve_ready : STD_LOGIC; + SIGNAL retrieve_ready : STD_LOGIC; + SIGNAL nxt_retrieve_done : 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); + +BEGIN + + p_reg : PROCESS (clk, rst) + BEGIN + IF rst = '1' THEN + -- Internal registers. + ch_cnt <= 0; + prev_retrieve_ready <= '0'; + retrieve_sop_dly(1 TO c_retrieve_lat) <= (OTHERS=>'0'); + retrieve_eop_dly(1 TO c_retrieve_lat) <= (OTHERS=>'0'); + -- Output registers. + retrieve_done <= '0'; + ELSIF rising_edge(clk) THEN + -- Internal registers. + ch_cnt <= nxt_ch_cnt; + prev_retrieve_ready <= retrieve_ready; + 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); + -- Output registers. + retrieve_done <= nxt_retrieve_done; + END IF; + END PROCESS; + + + -- 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 ( + g_rst_level => '0', + g_priority_lo => FALSE, -- store_done has priority over nxt_retrieve_done when they occur simultaneously + g_or_high => TRUE, + g_and_low => FALSE + ) + PORT MAP ( + rst => rst, + clk => clk, + switch_high => store_done, + switch_low => nxt_retrieve_done, -- can not use retrieve_done with g_and_low = TRUE, because if retrieve_done occurs after next store_done then that page gets missed + out_level => retrieve_en + ); + + retrieve_ready <= retrieve_en AND output_siso.ready; + + p_ch_cnt : PROCESS (retrieve_ready, ch_cnt) + BEGIN + nxt_retrieve_done <= '0'; + nxt_ch_cnt <= ch_cnt; + + IF retrieve_ready='1' THEN + IF ch_cnt=g_nof_ch_sel-1 THEN + nxt_retrieve_done <= '1'; + 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_ready='1' AND ch_cnt=0 ELSE '0'; + retrieve_eop_dly(0) <= '1' WHEN retrieve_ready='1' AND ch_cnt=g_nof_ch_sel-1 ELSE '0'; + + -- First read store buf address from select buf when the output is ready + select_mosi.rd <= '1'; -- no need to use retrieve_ready here, keep rd active to ease timing closure + select_mosi.address <= TO_MEM_ADDRESS(ch_cnt); + + -- Then use the read select address to read the data from the store buf + retrieve_mosi.rd <= prev_retrieve_ready; + retrieve_mosi.address <= RESIZE_MEM_ADDRESS(select_miso.rddata(ceil_log2(g_nof_ch_in)-1 DOWNTO 0)); + + -- The output_sosi has RL=2, because of the read accesses to the select buf followed by the read access to the store buf, both with read latency is 1, so c_retrieve_lat=2 + output_sosi.re <= RESIZE_DP_DSP_DATA(retrieve_miso.rddata( g_dsp_data_w-1 DOWNTO 0)); + output_sosi.im <= RESIZE_DP_DSP_DATA(retrieve_miso.rddata(c_nof_complex*g_dsp_data_w-1 DOWNTO g_dsp_data_w)); + output_sosi.data <= RESIZE_DP_DATA(retrieve_miso.rddata( c_nof_complex*g_dsp_data_w-1 DOWNTO 0)); + output_sosi.valid <= retrieve_miso.rdval; + output_sosi.sop <= retrieve_sop_dly(c_retrieve_lat); + output_sosi.eop <= retrieve_eop_dly(c_retrieve_lat); + +END rtl; diff --git a/libraries/base/reorder/src/vhdl/reorder_store.vhd b/libraries/base/reorder/src/vhdl/reorder_store.vhd new file mode 100644 index 0000000000..a0d30f165c --- /dev/null +++ b/libraries/base/reorder/src/vhdl/reorder_store.vhd @@ -0,0 +1,128 @@ +------------------------------------------------------------------------------- +-- +-- 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/>. +-- +------------------------------------------------------------------------------- + +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; + +-- Purpose: Controller that store blocks of g_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. +-- Remarks: +-- . The SS stores the complex input data as concatenated data = im & re with +-- data width 2 * g_dsp_data_w. +-- . The SS 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 ss_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. + +ENTITY ss_store IS + GENERIC ( + g_dsp_data_w : NATURAL; -- = width of sosi.im = width of sosi.re + 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 + ); + PORT ( + rst : IN STD_LOGIC; + clk : IN STD_LOGIC; + + -- Streaming + input_sosi : IN t_dp_sosi; + + -- Timing + store_done : OUT STD_LOGIC; + + -- Write databuf control + store_mosi : OUT t_mem_mosi + ); +END ss_store; + + +ARCHITECTURE rtl OF ss_store IS + + SIGNAL ch_cnt : INTEGER RANGE 0 TO g_nof_ch_in-1; + SIGNAL nxt_ch_cnt : INTEGER; + + SIGNAL i_store_mosi : t_mem_mosi; + 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) + BEGIN + IF rst = '1' THEN + -- Internal registers. + ch_cnt <= 0; + -- Output registers. + i_store_mosi <= c_mem_mosi_rst; + store_done <= '0'; + ELSIF rising_edge(clk) THEN + -- Internal registers. + ch_cnt <= nxt_ch_cnt; + -- Output registers. + i_store_mosi <= nxt_store_mosi; + store_done <= nxt_store_done; + END IF; + END PROCESS; + + p_ch_cnt : PROCESS (ch_cnt, input_sosi) + 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 + nxt_store_done <= '1'; + nxt_ch_cnt <= 0; + ELSE + nxt_ch_cnt <= ch_cnt + 1; + END IF; + END IF; + END PROCESS; + + -- store + nxt_store_mosi.wr <= input_sosi.valid; + nxt_store_mosi.address <= TO_MEM_ADDRESS(ch_cnt) WHEN input_sosi.valid='1' ELSE i_store_mosi.address; + + -- 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; + 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; + END GENERATE; + +END rtl; -- GitLab