-
Pieter Donker authoredPieter Donker authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
sdp_subband_equalizer.vhd 9.79 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:
-- . Block diagram:
--
-- in_raw ----> pipeline --> * co-pol weights --+-----> Q --> out_raw
-- \-> reverse pol --> * cross-pol weights --/ \--> Q --> out_quant
--
-- . 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.
-- . The subband equalizer can calibrate for co-polarization using only the
-- co-polarization weights from ram_gains_mosi. Or it can do full Jones
-- matrix calibration using also the cross polarization weights from
-- ram_gains_cross_mosi.
-- . Default the co-polarization weights are read from g_gains_file_name and
-- default the cross polarization weights are 0.
-- . 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:
-- . If the latency of sdp_subband_equalizer.vhd is changed, then
-- c_sdp_subband_equalizer_latency in sdp_pkg.vhd needs to be updated.
--
-------------------------------------------------------------------------------
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"; -- for co-polarization
g_nof_streams : natural := c_sdp_P_pfb;
-- Use no default raw width, to force instance to set it
g_raw_dat_w : natural; -- default: c_sdp_W_subband;
g_raw_fraction_w : natural -- default: 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;
ram_gains_cross_mosi : in t_mem_mosi := c_mem_mosi_rst;
ram_gains_cross_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 to easy timing closure
constant c_pipeline_remove_lsb : natural := 1;
constant c_pipeline_remove_msb : natural := 1;
signal in_pipe_raw_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0);
signal in_cross_raw_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0);
signal in_raw_sosi_2arr_2 : t_dp_sosi_2arr_2(g_nof_streams - 1 downto 0);
signal weighted_raw_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0);
signal weighted_cross_raw_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0);
signal sum_raw_sosi_arr : t_dp_sosi_arr(g_nof_streams - 1 downto 0);
begin
-----------------------------------------------------------------------------
-- Prepare co and cross input
-----------------------------------------------------------------------------
-- Total pipeline of u_reverse_pol is:
-- g_pipeline_demux_in + g_pipeline_demux_out +
-- g_reverse_len - 1 +
-- g_pipeline_mux_in + g_pipeline_mux_out = 1 + 0 + 2-1 + 0 + 1 = 3
u_pipeline_co_pol : entity dp_lib.dp_pipeline_arr
generic map (
g_nof_streams => g_nof_streams,
g_pipeline => 3
)
port map (
rst => dp_rst,
clk => dp_clk,
-- ST sink
snk_in_arr => in_raw_sosi_arr,
-- ST source
src_out_arr => in_pipe_raw_sosi_arr
);
-- The input subband data order is fsub[S_pn/Q_fft]_[N_sub][Q_fft] and
-- the [Q_fft] = [N_pol] index contains the X and Y polarizations.
-- Reverse the serial [N_pol] input polarizations to have the cross
-- polarization aligned with the co polarizations in
-- in_pipeline_raw_sosi_arr.
gen_cross_pol : for I in 0 to g_nof_streams - 1 generate
u_cross_pol : entity dp_lib.dp_reverse_n_data
generic map (
g_pipeline_demux_in => 1, -- serial to parallel section
g_pipeline_demux_out => 0,
g_pipeline_mux_in => 0, -- parallel to serial section
g_pipeline_mux_out => 1,
g_reverse_len => c_sdp_N_pol, -- = 2
g_data_w => g_raw_dat_w * c_nof_complex,
g_use_complex => true,
g_signed => true
)
port map (
rst => dp_rst,
clk => dp_clk,
snk_in => in_raw_sosi_arr(I),
src_out => in_cross_raw_sosi_arr(I)
);
end generate;
-----------------------------------------------------------------------------
-- Apply co and cross weights
-----------------------------------------------------------------------------
-- Total pipeline of sdp_subband_weights is: 5
u_sdp_subband_weigths : entity work.sdp_subband_weights
generic map (
g_gains_file_name => g_gains_file_name, -- for co polarization
g_nof_streams => g_nof_streams,
g_raw_dat_w => g_raw_dat_w
)
port map (
dp_clk => dp_clk,
dp_rst => dp_rst,
in_raw_sosi_arr => in_pipe_raw_sosi_arr,
in_cross_raw_sosi_arr => in_cross_raw_sosi_arr,
weighted_raw_sosi_arr => weighted_raw_sosi_arr,
weighted_cross_raw_sosi_arr => weighted_cross_raw_sosi_arr,
mm_rst => mm_rst,
mm_clk => mm_clk,
ram_gains_mosi => ram_gains_mosi,
ram_gains_miso => ram_gains_miso,
ram_gains_cross_mosi => ram_gains_cross_mosi,
ram_gains_cross_miso => ram_gains_cross_miso
);
-----------------------------------------------------------------------------
-- Sum co + cross
-----------------------------------------------------------------------------
-- Total pipeline of u_dp_complex_add is: 1
gen_dp_complex_add : for I in 0 to g_nof_streams - 1 generate
in_raw_sosi_2arr_2(I)(0) <= weighted_raw_sosi_arr(I);
in_raw_sosi_2arr_2(I)(1) <= weighted_cross_raw_sosi_arr(I);
u_dp_complex_add : entity dp_lib.dp_complex_add
generic map(
g_nof_inputs => c_sdp_N_pol,
g_data_w => c_gain_out_dat_w
)
port map(
rst => dp_rst,
clk => dp_clk,
snk_in_arr => in_raw_sosi_2arr_2(I),
src_out => sum_raw_sosi_arr(I)
);
end generate;
-----------------------------------------------------------------------------
-- Requantize
-----------------------------------------------------------------------------
-- Total pipeline of requantize is:
-- c_pipeline_remove_lsb + c_pipeline_remove_lsb = 1 + 1 = 2
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 => sum_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 => sum_raw_sosi_arr(I),
-- ST source
src_out => out_quant_sosi_arr(I)
);
end generate;
end str;