diff --git a/applications/lofar2/libraries/sdp/hdllib.cfg b/applications/lofar2/libraries/sdp/hdllib.cfg index a1e0d5853c6bc74858f1a4f75a4a722b02a275d0..465219f6cdac4a4a43b46ff3a3f6c42d16b82ed2 100644 --- a/applications/lofar2/libraries/sdp/hdllib.cfg +++ b/applications/lofar2/libraries/sdp/hdllib.cfg @@ -9,6 +9,7 @@ synth_files = src/vhdl/sdp_scope.vhd src/vhdl/sdp_subband_equalizer.vhd src/vhdl/sdp_bf_weights.vhd + src/vhdl/sdp_beamformer_local.vhd src/vhdl/node_sdp_adc_input_and_timing.vhd src/vhdl/node_sdp_filterbank.vhd test_bench_files = diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_local.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_local.vhd new file mode 100644 index 0000000000000000000000000000000000000000..64ad0c71c40c5723288b536b4907c982884e6ebf --- /dev/null +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_local.vhd @@ -0,0 +1,248 @@ +------------------------------------------------------------------------------- +-- +-- 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 beamformer_local in node_sdp_beamformer. +-- Description: +-- The local BF function weights the subbands from the S_pn signal inputs and +-- adds them to form the local beamlet sum. +-- 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_beamformer_local IS + GENERIC ( + g_bf_weights_file_name : STRING := "UNUSED" + ); + 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; + + ram_bf_weights_mosi : IN t_mem_mosi := c_mem_mosi_rst; + ram_bf_weights_miso : OUT t_mem_miso + ); +END sdp_beamformer_local; + +ARCHITECTURE str OF sdp_beamformer_local IS + + CONSTANT c_complex_adder_latency : NATURAL := ceil_log2(c_sdp_S_pn); + CONSTANT c_bf_weights_latency : NATURAL := 3; + CONSTANT c_total_latency : NATURAL := 2 + c_bf_weights_latency + c_complex_adder_latency; + + CONSTANT c_complex_adder_sum_w : NATURAL := c_sdp_W_bf_product + ceil_log2(c_sdp_S_pn); + + SIGNAL sub_sosi_arr : t_dp_sosi_arr(c_sdp_N_pol*c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL bf_weights_out_sosi_arr : t_dp_sosi_arr(c_sdp_N_pol*c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL bf_weights_x_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL bf_weights_y_sosi_arr : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL deinterleaved_x_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL deinterleaved_y_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL interleave_out_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL complex_add_out_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL pipelined_in_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL dp_requantize_in_sosi : t_dp_sosi := c_dp_sosi_rst; + +BEGIN + --------------------------------------------------------------- + -- COPY INPUT STERAMS FOR X AND Y POLARIZATION PATHS + --------------------------------------------------------------- + gen_pol : FOR N_pol IN 0 TO c_sdp_N_pol-1 GENERATE + gen_pfb : FOR P_pfb IN 0 TO c_sdp_P_pfb-1 GENERATE + sub_sosi_arr(N_pol*c_sdp_P_pfb + P_pfb) <= in_sosi_arr(P_pfb); + END GENERATE; + END GENERATE; + + --------------------------------------------------------------- + -- BEAMFORMER WEIGHTS + --------------------------------------------------------------- + u_sdp_bf_weights : ENTITY work.sdp_bf_weights + GENERIC MAP ( + g_gains_file_name => g_bf_weights_file_name + ) + PORT MAP( + dp_clk => dp_clk, + dp_rst => dp_rst, + + in_sosi_arr => sub_sosi_arr, + out_sosi_arr => bf_weights_out_sosi_arr, + + mm_rst => mm_rst, + mm_clk => mm_clk, + + ram_gains_mosi => ram_bf_weights_mosi, + ram_gains_miso => ram_bf_weights_miso + ); + + -- X pol is lower half of bf_weights_out + bf_weights_x_sosi_arr <= bf_weights_out_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); + + --------------------------------------------------------------- + -- DP PIPELINE Y PATH + --------------------------------------------------------------- + -- The weighted subbands from the Y polarization path are pipelined + -- by one cycle so that they can be time multiplexed with the + -- weighted subbands from the X polarization. + u_pipeline_y_pol : ENTITY dp_lib.dp_pipeline_arr + GENERIC MAP ( + g_nof_streams => c_sdp_P_pfb, + g_pipeline => 1 + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + snk_in_arr => bf_weights_out_sosi_arr(2*c_sdp_P_pfb-1 DOWNTO c_sdp_P_pfb), + src_out_arr => bf_weights_y_sosi_arr + ); + + --------------------------------------------------------------- + -- DEINTERLEAVE X PATH + --------------------------------------------------------------- + gen_deinterleave_x_pol : FOR I IN 0 TO c_sdp_P_pfb-1 GENERATE + u_dp_deinterleave_x_pol : ENTITY dp_lib.dp_deinterleave_one_to_n + GENERIC MAP( + g_nof_outputs => c_sdp_Q_fft + ) + PORT MAP( + rst => dp_rst, + clk => dp_clk, + + snk_in => bf_weights_x_sosi_arr(I), + src_out_arr(0) => deinterleaved_x_sosi_arr(c_sdp_Q_fft*I), + src_out_arr(1) => deinterleaved_x_sosi_arr(c_sdp_Q_fft*I+1) + ); + END GENERATE; + + --------------------------------------------------------------- + -- DEINTERLEAVE Y PATH + --------------------------------------------------------------- + gen_deinterleave_y_pol : FOR I IN 0 TO c_sdp_P_pfb-1 GENERATE + u_dp_deinterleave_y_pol : ENTITY dp_lib.dp_deinterleave_one_to_n + GENERIC MAP( + g_nof_outputs => c_sdp_Q_fft + ) + PORT MAP( + rst => dp_rst, + clk => dp_clk, + + snk_in => bf_weights_y_sosi_arr(I), + src_out_arr(0) => deinterleaved_y_sosi_arr(c_sdp_Q_fft*I), + src_out_arr(1) => deinterleaved_y_sosi_arr(c_sdp_Q_fft*I+1) + ); + END GENERATE; + + --------------------------------------------------------------- + -- INTERLEAVE X AND Y POLARIZATIONS + --------------------------------------------------------------- + gen_interleave : FOR I IN 0 TO c_sdp_S_pn-1 GENERATE + u_dp_interleave : ENTITY dp_lib.dp_interleave_n_to_one + GENERIC MAP( + g_nof_inputs => c_sdp_N_pol + ) + PORT MAP( + rst => dp_rst, + clk => dp_clk, + + snk_in_arr(0) => deinterleaved_x_sosi_arr(I), + snk_in_arr(1) => deinterleaved_y_sosi_arr(I), + src_out => interleave_out_sosi_arr(I) + ); + END GENERATE; + + --------------------------------------------------------------- + -- ADD + --------------------------------------------------------------- + u_dp_complex_add : ENTITY dp_lib.dp_complex_add + GENERIC MAP( + g_nof_inputs => c_sdp_S_pn, + g_data_w => c_sdp_W_bf_product + ) + PORT MAP( + rst => dp_rst, + clk => dp_clk, + + snk_in_arr => interleave_out_sosi_arr, + src_out => complex_add_out_sosi + ); + + --------------------------------------------------------------- + -- DP PIPELINE IN_SOSI FIELDS + --------------------------------------------------------------- + u_pipeline : ENTITY dp_lib.dp_pipeline + GENERIC MAP ( + g_pipeline => c_total_latency + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + snk_in => in_sosi_arr(0), + src_out => pipelined_in_sosi + ); + + --------------------------------------------------------------- + -- COMBINE OUTPUT WITH PIPELINED IN_SOSI + --------------------------------------------------------------- + p_sosi : PROCESS(pipelined_in_sosi, complex_add_out_sosi) + BEGIN + dp_requantize_in_sosi <= pipelined_in_sosi; + dp_requantize_in_sosi.re <= complex_add_out_sosi.re; + dp_requantize_in_sosi.im <= complex_add_out_sosi.im; + END PROCESS; + + --------------------------------------------------------------- + -- REQUANTIZE + --------------------------------------------------------------- + u_dp_requantize : ENTITY dp_lib.dp_requantize + GENERIC MAP ( + g_complex => TRUE, + g_representation => "SIGNED", + g_lsb_w => c_sdp_W_bf_fraction, + g_lsb_round => TRUE, + g_lsb_round_clip => FALSE, + g_msb_clip => TRUE, + g_msb_clip_symmetric => FALSE, + g_in_dat_w => c_complex_adder_sum_w, + g_out_dat_w => c_sdp_W_beamlet_sum + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + -- ST sink + snk_in => dp_requantize_in_sosi, + -- ST source + src_out => out_sosi + ); + +END str; diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd index f24c7902a16ff4efb86082da850975d5baf827c7..4b3b73192078cd3d24aaa258544409e190025cf7 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd @@ -60,6 +60,8 @@ PACKAGE sdp_pkg is CONSTANT c_sdp_W_bf_weight : NATURAL := 16; CONSTANT c_sdp_W_bf_magnitude : NATURAL := 1; CONSTANT c_sdp_W_bf_fraction : NATURAL := c_sdp_W_bf_weight - c_sdp_W_bf_magnitude -1; + CONSTANT c_sdp_W_bf_product : NATURAL := c_sdp_W_subband + c_sdp_W_bf_weight -1; + CONSTANT c_sdp_W_beamlet_sum : NATURAL := 18; CONSTANT c_sdp_ait_buf_nof_data_jesd : NATURAL := 1024; -- 1024 14 bit samples fit in one M20k BRAM CONSTANT c_sdp_ait_buf_nof_data_bsn : NATURAL := 1024; -- 1024 14 bit samples fit in one M20k BRAM