Skip to content
Snippets Groups Projects

Resolve L2SDP-285

Merged Reinier van der Walle requested to merge L2SDP-285 into master
Files
5
-------------------------------------------------------------------------------
--
-- Copyright 2021
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--
-- Author: R. van der Walle
-- Purpose:
-- Select subbands from incoming blocks
-- Description:
-- The Crosslet subband select selects N_crosslets from each incoming block. Per
-- crosslet there are S_pn = 12 subbands, one from each signal input of the PN.
-- Remark:
-- . See L5 SDPFW Design Document: Subband Correlator
-- Link: https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=L2M&title=L5+SDPFW+Design+Document%3A+Subband+Correlator
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, dp_lib, reorder_lib, st_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_network_layers_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE work.sdp_pkg.ALL;
ENTITY sdp_crosslets_subband_select IS
GENERIC (
g_N_crosslets : NATURAL := c_sdp_N_crosslets
);
PORT (
dp_clk : IN STD_LOGIC;
dp_rst : IN STD_LOGIC;
in_sosi_arr : IN t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0);
out_sosi : OUT t_dp_sosi;
mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC;
reg_crosslets_info_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_crosslets_info_miso : OUT t_mem_miso := c_mem_miso_rst;
reg_bsn_scheduler_xsub_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_bsn_scheduler_xsub_miso : OUT t_mem_miso := c_mem_miso_rst;
out_crosslets_info : OUT STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0)
);
END sdp_crosslets_subband_select;
ARCHITECTURE str OF sdp_crosslets_subband_select IS
CONSTANT c_crosslets_info_dly : NATURAL := 1;
CONSTANT c_row_select_slv_w : NATURAL := ceil_log2(c_sdp_P_pfb);
CONSTANT c_row_select_pipeline : NATURAL := 1;
CONSTANT c_out_sosi_pipeline : NATURAL := 1;
TYPE t_crosslets_control_reg IS RECORD -- local registers
offset_index : NATURAL;
row_index : NATURAL;
col_index : NATURAL;
step : NATURAL RANGE 0 TO c_sdp_N_sub-1;
offsets : t_natural_arr(g_N_crosslets-1 DOWNTO 0);
started : STD_LOGIC;
row_select_slv : STD_LOGIC_VECTOR(c_row_select_slv_w-1 DOWNTO 0);
col_select_mosi : t_mem_mosi;
sync_detected : STD_LOGIC;
END RECORD;
CONSTANT c_reg_rst : t_crosslets_control_reg := ( 0, 0, 0, 0, (OTHERS => 0), '0', (OTHERS => '0'), c_mem_mosi_rst, '0');
-- Define the local registers in t_crosslets_control_reg record
SIGNAL r : t_crosslets_control_reg;
SIGNAL nxt_r : t_crosslets_control_reg;
SIGNAL start_trigger : STD_LOGIC := '0';
SIGNAL col_select_mosi : t_mem_mosi := c_mem_mosi_rst;
SIGNAL col_select_miso : t_mem_miso := c_mem_miso_rst;
SIGNAL row_select_slv : STD_LOGIC_VECTOR(c_row_select_slv_w-1 DOWNTO 0);
SIGNAL col_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0);
SIGNAL row_sosi : t_dp_sosi;
SIGNAL crosslets_info_reg : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS=>'0');
SIGNAL active_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0');
BEGIN
---------------------------------------------------------------
-- BSN scheduler
---------------------------------------------------------------
u_bsn_scheduler : ENTITY dp_lib.mms_dp_bsn_scheduler
GENERIC MAP (
g_cross_clock_domain => TRUE,
g_bsn_w => c_dp_stream_bsn_w
)
PORT MAP (
-- Memory-mapped clock domain
mm_rst => mm_rst,
mm_clk => mm_clk,
reg_mosi => reg_bsn_scheduler_xsub_mosi,
reg_miso => reg_bsn_scheduler_xsub_miso,
-- Streaming clock domain
dp_rst => dp_rst,
dp_clk => dp_clk,
snk_in => in_sosi_arr(0), -- only uses eop (= block sync), bsn[]
trigger_out => start_trigger
);
---------------------------------------------------------------
-- Crosslets info
---------------------------------------------------------------
u_crosslets_info : ENTITY common_lib.mms_common_reg
GENERIC MAP(
g_mm_reg => c_sdp_mm_reg_crosslets_info
)
PORT MAP(
-- Clocks and reset
mm_rst => mm_rst,
mm_clk => mm_clk,
st_rst => dp_rst,
st_clk => dp_clk,
-- MM bus access in memory-mapped clock domain
reg_mosi => reg_crosslets_info_mosi,
reg_miso => reg_crosslets_info_miso,
in_reg => crosslets_info_reg,
out_reg => crosslets_info_reg
);
---------------------------------------------------------------
-- Crosslets control process
---------------------------------------------------------------
p_regs_crosslets_control : PROCESS(dp_rst, dp_clk)
BEGIN
IF dp_rst='1' THEN
r <= c_reg_rst;
ELSIF rising_edge(dp_clk) THEN
r <= nxt_r;
END IF;
END PROCESS;
p_comb_crosslets_control : PROCESS(r, start_trigger, crosslets_info_reg, in_sosi_arr, col_select_miso)
VARIABLE v : t_crosslets_control_reg;
VARIABLE v_offsets : t_natural_arr(g_N_crosslets-1 DOWNTO 0); -- Use extra variable to simplify col_select_mosi address selection
BEGIN
v := r;
v.col_select_mosi := c_mem_mosi_rst;
-- start/restart
IF start_trigger = '1' THEN
v.started := '1';
v.offset_index := 0;
v.row_index := 0;
v.col_index := 0;
v.sync_detected := '0';
v.step := TO_UINT(crosslets_info_reg(c_sdp_crosslets_info_reg_w-1 DOWNTO c_sdp_crosslets_info_reg_w - c_sdp_crosslets_index_w));
FOR I IN 0 TO g_N_crosslets-1 LOOP
v_offsets(I) := TO_UINT(crosslets_info_reg((I+1)*c_sdp_crosslets_index_w-1 DOWNTO I*c_sdp_crosslets_index_w));
END LOOP;
END IF;
IF in_sosi_arr(0).sync = '1' AND start_trigger = '0' THEN
v.sync_detected := '1';
END IF;
IF r.started = '1' THEN
-- add step to offsets
IF in_sosi_arr(0).eop = '1' AND r.sync_detected = '1' THEN -- change offsets 1 packet after the sync due to the buffered packet in reorder_col_wide_select
v.sync_detected := '0';
FOR I IN 0 TO g_N_crosslets-1 LOOP
v_offsets(I) := r.offsets(I) + TO_UINT(crosslets_info_reg(c_sdp_crosslets_info_reg_w-1 DOWNTO c_sdp_crosslets_info_reg_w - c_sdp_crosslets_index_w));
END LOOP;
END IF;
-- Make col/row selection
IF col_select_miso.waitrequest = '0' THEN
IF r.col_index >= c_sdp_Q_fft-1 THEN
v.col_index := 0;
IF r.row_index >= c_sdp_P_pfb-1 THEN
v.row_index := 0;
IF r.offset_index >= g_N_crosslets-1 THEN
v.offset_index := 0;
ELSE
v.offset_index := r.offset_index+1;
END IF;
ELSE
v.row_index := r.row_index+1;
END IF;
ELSE
v.col_index := r.col_index+1;
END IF;
v.col_select_mosi.rd := '1';
v.col_select_mosi.address(c_sdp_crosslets_index_w-1 DOWNTO 0) := TO_UVEC(c_sdp_Q_fft*v_offsets(r.offset_index) + r.col_index, c_sdp_crosslets_index_w);
v.row_select_slv := TO_UVEC(r.row_index, c_row_select_slv_w);
END IF;
END IF;
v.offsets := v_offsets;
nxt_r <= v;
END PROCESS;
col_select_mosi <= r.col_select_mosi;
-- pipeline to time row select
u_pipe_row_select : ENTITY common_lib.common_pipeline
GENERIC MAP(
g_pipeline => c_row_select_pipeline,
g_in_dat_w => c_row_select_slv_w,
g_out_dat_w => c_row_select_slv_w
)
PORT MAP(
rst => dp_rst,
clk => dp_clk,
in_dat => r.row_select_slv,
out_dat => row_select_slv
);
active_crosslets_info(c_sdp_crosslets_info_reg_w-1 DOWNTO c_sdp_crosslets_info_reg_w - c_sdp_crosslets_index_w) <= TO_UVEC(r.step, c_sdp_crosslets_index_w);
gen_crosslets_info : FOR I IN 0 TO g_N_crosslets-1 GENERATE
active_crosslets_info((I+1)*c_sdp_crosslets_index_w-1 DOWNTO I*c_sdp_crosslets_index_w) <= TO_UVEC(r.offsets(I), c_sdp_crosslets_index_w);
END GENERATE;
---------------------------------------------------------------
-- Crosslet Select
---------------------------------------------------------------
u_reorder_col_wide_select : ENTITY reorder_lib.reorder_col_wide_select
GENERIC MAP (
g_nof_inputs => c_sdp_P_pfb,
g_dsp_data_w => c_sdp_W_subband,
g_nof_ch_in => c_sdp_N_sub * c_sdp_Q_fft,
g_nof_ch_sel => g_N_crosslets * c_sdp_S_pn
)
PORT MAP (
dp_rst => dp_rst,
dp_clk => dp_clk,
-- Memory Mapped
col_select_mosi => col_select_mosi,
col_select_miso => col_select_miso,
-- Streaming
input_sosi_arr => in_sosi_arr,
output_sosi_arr => col_sosi_arr
);
u_reorder_row_select : ENTITY reorder_lib.reorder_row_select
GENERIC MAP (
g_dsp_data_w => c_sdp_W_subband,
g_nof_inputs => c_sdp_P_pfb,
g_nof_outputs => 1,
g_pipeline_in => 0,
g_pipeline_in_m => 1,
g_pipeline_out => 1
)
PORT MAP (
dp_rst => dp_rst,
dp_clk => dp_clk,
in_select => row_select_slv,
-- Streaming
input_sosi_arr => col_sosi_arr,
output_sosi_arr(0) => row_sosi
);
---------------------------------------------------------------
-- Out Crosslet info pipeline
---------------------------------------------------------------
-- pipeline for alignment with sync
u_common_pipeline : ENTITY common_lib.common_pipeline
GENERIC MAP(
g_pipeline => c_crosslets_info_dly,
g_in_dat_w => c_sdp_crosslets_info_reg_w,
g_out_dat_w => c_sdp_crosslets_info_reg_w
)
PORT MAP(
rst => dp_rst,
clk => dp_clk,
in_en => row_sosi.sync,
in_dat => active_crosslets_info,
out_dat => out_crosslets_info
);
---------------------------------------------------------------
-- Out sosi pipeline
---------------------------------------------------------------
u_dp_pipeline : ENTITY dp_lib.dp_pipeline
GENERIC MAP (
g_pipeline => c_out_sosi_pipeline
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
-- ST sink
snk_in => row_sosi,
-- ST source
src_out => out_sosi
);
END str;
Loading