-
Eric Kooistra authoredEric Kooistra authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
sdp_subband_equalizer.vhd 7.76 KiB
-------------------------------------------------------------------------------
--
-- Copyright 2020
-- 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:
-- . Implements the functionality of the subband equalizer in the subband
-- filterbank (Fsub) of the LOFAR2 SDPFW design.
-- Description:
-- . The sdp_subband_equalizer.vhd consists of mms_dp_gain_serial_arr.vhd and
-- some address counter logic to select the address of the subband weight
-- and a dp_requantize.vhd component.
-- . Subband widths:
-- - raw_sosi : g_raw_dat_w bits
-- - quant_sosi : c_quant_dat_w = g_raw_dat_w - g_raw_fraction_w bits
-- Remark:
--
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, dp_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE work.sdp_pkg.ALL;
ENTITY sdp_subband_equalizer IS
GENERIC (
g_gains_file_name : STRING := "UNUSED";
g_nof_streams : NATURAL := c_sdp_P_pfb;
g_raw_dat_w : NATURAL := c_sdp_W_subband;
g_raw_fraction_w : NATURAL := 0
);
PORT (
dp_clk : IN STD_LOGIC;
dp_rst : IN STD_LOGIC;
in_raw_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
out_raw_sosi_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
out_quant_sosi_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC;
ram_gains_mosi : IN t_mem_mosi := c_mem_mosi_rst;
ram_gains_miso : OUT t_mem_miso
);
END sdp_subband_equalizer;
ARCHITECTURE str OF sdp_subband_equalizer IS
CONSTANT c_gain_addr_w : NATURAL := ceil_log2(c_sdp_Q_fft * c_sdp_N_sub);
-- Product width, do -1 to skip double sign bit in product
CONSTANT c_gain_out_dat_w : NATURAL := c_sdp_W_sub_weight + g_raw_dat_w - 1;
CONSTANT c_quant_dat_w : NATURAL := g_raw_dat_w - g_raw_fraction_w;
-- Pipeline requantization to easy timing closure
CONSTANT c_pipeline_remove_lsb : NATURAL := 1;
CONSTANT c_pipeline_remove_msb : NATURAL := 1;
SIGNAL in_sosi : t_dp_sosi;
SIGNAL cnt : NATURAL RANGE 0 TO c_sdp_Q_fft * c_sdp_N_sub-1;
SIGNAL gains_rd_address : STD_LOGIC_VECTOR(c_gain_addr_w-1 DOWNTO 0);
SIGNAL weighted_raw_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
BEGIN
in_sosi <= in_raw_sosi_arr(0); -- use ctrl from input [0]
-----------------------------------------------------------------------------
-- Counter
-----------------------------------------------------------------------------
-- The subband weigths per PN are stored as
-- (cint16)subband_weights[S_pn/Q_fft]_[Q_fft][N_sub], but have
-- to be applied according the subband data order
-- fsub[S_pn/Q_fft]_[N_sub][Q_fft]. Therefore the counter in
-- sdp_subband_equalizer.vhd has to account for this difference in order.
p_cnt : PROCESS(dp_clk, dp_rst)
-- Use short index variables v_Q, v_SUB names in capitals, to ease
-- recognizing them as (loop) indices.
VARIABLE v_Q, v_SUB : NATURAL;
BEGIN
IF dp_rst = '1' THEN
cnt <= 0;
v_Q := 0;
v_SUB := 0;
ELSIF rising_edge(dp_clk) THEN
IF in_sosi.valid = '1' THEN
IF in_sosi.eop = '1' THEN
v_Q := 0;
v_SUB := 0;
ELSE
IF v_Q >= c_sdp_Q_fft-1 THEN
v_Q := 0;
IF v_SUB >= c_sdp_N_sub-1 THEN
v_SUB := 0;
ELSE
v_SUB := v_SUB + 1;
END IF;
ELSE
v_Q := v_Q + 1;
END IF;
END IF;
cnt <= v_Q * c_sdp_N_sub + v_SUB;
END IF;
END IF;
END PROCESS;
gains_rd_address <= TO_UVEC(cnt, c_gain_addr_w);
-----------------------------------------------------------------------------
-- Gain
-----------------------------------------------------------------------------
u_mms_dp_gain_serial_arr : ENTITY dp_lib.mms_dp_gain_serial_arr
GENERIC MAP (
g_nof_streams => g_nof_streams,
g_nof_gains => c_sdp_Q_fft * c_sdp_N_sub,
g_complex_data => TRUE,
g_complex_gain => TRUE,
g_gain_w => c_sdp_W_sub_weight,
g_in_dat_w => g_raw_dat_w,
g_out_dat_w => c_gain_out_dat_w,
g_gains_file_name => g_gains_file_name
)
PORT MAP (
-- System
mm_rst => mm_rst,
mm_clk => mm_clk,
dp_rst => dp_rst,
dp_clk => dp_clk,
-- MM interface
ram_gains_mosi => ram_gains_mosi,
ram_gains_miso => ram_gains_miso,
-- ST interface
gains_rd_address => gains_rd_address,
in_sosi_arr => in_raw_sosi_arr,
out_sosi_arr => weighted_raw_sosi_arr
);
-----------------------------------------------------------------------------
-- Requantize
-----------------------------------------------------------------------------
gen_dp_requantize : FOR I IN 0 TO g_nof_streams-1 GENERATE
-- For raw output only round the c_sdp_W_sub_weight_fraction, and keep the
-- g_raw_fraction_w, so that the output width remains the same as the input
-- width g_raw_dat_w.
u_dp_requantize_out_raw : ENTITY dp_lib.dp_requantize
GENERIC MAP (
g_complex => TRUE,
g_representation => "SIGNED",
g_lsb_w => c_sdp_W_sub_weight_fraction,
g_lsb_round => TRUE,
g_lsb_round_clip => FALSE,
g_msb_clip => TRUE, -- clip subband overflow
g_msb_clip_symmetric => FALSE,
g_pipeline_remove_lsb => c_pipeline_remove_lsb,
g_pipeline_remove_msb => c_pipeline_remove_msb,
g_in_dat_w => c_gain_out_dat_w,
g_out_dat_w => g_raw_dat_w
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
-- ST sink
snk_in => weighted_raw_sosi_arr(I),
-- ST source
src_out => out_raw_sosi_arr(I)
);
-- For quant output round the entire fraction, so that the output width
-- becomes c_quant_dat_w.
u_dp_requantize_out_quant : ENTITY dp_lib.dp_requantize
GENERIC MAP (
g_complex => TRUE,
g_representation => "SIGNED",
g_lsb_w => c_sdp_W_sub_weight_fraction + g_raw_fraction_w,
g_lsb_round => TRUE,
g_lsb_round_clip => FALSE,
g_msb_clip => TRUE, -- clip subband overflow
g_msb_clip_symmetric => FALSE,
g_pipeline_remove_lsb => c_pipeline_remove_lsb,
g_pipeline_remove_msb => c_pipeline_remove_msb,
g_in_dat_w => c_gain_out_dat_w,
g_out_dat_w => c_quant_dat_w
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
-- ST sink
snk_in => weighted_raw_sosi_arr(I),
-- ST source
src_out => out_quant_sosi_arr(I)
);
END GENERATE;
END str;