diff --git a/applications/arts/libraries/arts_tab_beamformer/hdllib.cfg b/applications/arts/libraries/arts_tab_beamformer/hdllib.cfg new file mode 100644 index 0000000000000000000000000000000000000000..b5df0617f2951f384eb6cd7f304b3fb41817c818 --- /dev/null +++ b/applications/arts/libraries/arts_tab_beamformer/hdllib.cfg @@ -0,0 +1,22 @@ +hdl_lib_name = arts_tab_beamformer +hdl_library_clause_name = arts_tab_beamformer_lib +hdl_lib_uses_synth = dp beamformer +hdl_lib_uses_sim = diag +hdl_lib_technology = + +synth_files = + src/vhdl/arts_tab_beamformer.vhd + +test_bench_files = + tb/vhdl/tb_arts_tab_beamformer.vhd + +regression_test_vhdl = + # no self checking tb available yet + + +[modelsim_project_file] +modelsim_copy_files = + src/hex hex + +[quartus_project_file] + diff --git a/applications/arts/libraries/arts_tab_beamformer/src/python/gen_hex_files_beamformer_weights.py b/applications/arts/libraries/arts_tab_beamformer/src/python/gen_hex_files_beamformer_weights.py new file mode 100644 index 0000000000000000000000000000000000000000..f7e9851b43cc8c1e0c89a57d1e2a4e967194a99f --- /dev/null +++ b/applications/arts/libraries/arts_tab_beamformer/src/python/gen_hex_files_beamformer_weights.py @@ -0,0 +1,60 @@ +############################################################################### +# +# Copyright (C) 2013 +# 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/>. +# +############################################################################### + +from common import * +from mem_init_file import list_to_hex + +# Purpose: +# . Generate HEX files with weights for the X and Y pol +# Description: +# . Converts list of 176 words to HEX file +# . 176 words = 2 (X,Y pols) interleaved streams of 88 complex numbers + +PATH = "../hex" +FILENAME = "beamformer_weights" + +NOF_WEIGHTS_RAMS = 12 +COMPLEX_WIDTH = 16 +NOF_WORDS_PER_POL = 88 +MEM_WIDTH =32 +MEM_DEPTH = 176 + +############################################################################### +# Create the data list +# . 176 words = 2 (X,Y pols) interleaved streams of 88 complex numbers +# . X-pol = complex( 1, 1) +# . Y-pol = complex(-1,-1) +############################################################################### +complex_x = [complex(i, 0) for i in range(NOF_WORDS_PER_POL)] +complex_y = [complex(i, 0) for i in range(NOF_WORDS_PER_POL)] + +concat_int_x = concat_complex(complex_x, COMPLEX_WIDTH) +concat_int_y = concat_complex(complex_y, COMPLEX_WIDTH) + +data = interleave([concat_int_x,concat_int_y]) +print data + +############################################################################### +# Write the HEX file +############################################################################### +for i in range(NOF_WEIGHTS_RAMS): + list_to_hex(data, PATH+"/"+FILENAME+"_"+str(i)+".mif", MEM_WIDTH, MEM_DEPTH) + diff --git a/applications/arts/libraries/arts_tab_beamformer/src/python/gen_hex_files_diag_block_gen.py b/applications/arts/libraries/arts_tab_beamformer/src/python/gen_hex_files_diag_block_gen.py new file mode 100644 index 0000000000000000000000000000000000000000..62fc157fc7b01d2ec209d7a4578f5260c44a52bb --- /dev/null +++ b/applications/arts/libraries/arts_tab_beamformer/src/python/gen_hex_files_diag_block_gen.py @@ -0,0 +1,60 @@ +############################################################################### +# +# Copyright (C) 2013 +# 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/>. +# +############################################################################### + +from common import * +from mem_init_file import list_to_hex + +# Purpose: +# . Generate HEX files with simple complex numbers to tag the X and Y pol +# Description: +# . Converts list of 176 words to HEX file +# . 176 words = 2 (X,Y pols) interleaved streams of 88 complex numbers +# . X-pol = complex( 1, 1) +# . Y-pol = complex(-1,-1) + +PATH = "../hex" +FILENAME = "mms_diag_block_gen_0" + +COMPLEX_WIDTH = 8 +NOF_WORDS_PER_POL = 88 +MEM_WIDTH = 16 +MEM_DEPTH = 176 + +############################################################################### +# Create the data list +# . 176 words = 2 (X,Y pols) interleaved streams of 88 complex numbers +# . X-pol = complex( 1, 1) +# . Y-pol = complex(-1,-1) +############################################################################### +complex_x = NOF_WORDS_PER_POL * [complex( 1, 1)] +complex_y = NOF_WORDS_PER_POL * [complex(-1,-1)] + +concat_int_x = concat_complex(complex_x, COMPLEX_WIDTH) +concat_int_y = concat_complex(complex_y, COMPLEX_WIDTH) + +data = interleave([concat_int_x,concat_int_y]) +print data + +############################################################################### +# Write the HEX file +############################################################################### +list_to_hex(data, PATH+"/"+FILENAME+".hex", MEM_WIDTH, MEM_DEPTH) + diff --git a/applications/arts/libraries/arts_tab_beamformer/src/vhdl/arts_tab_beamformer.vhd b/applications/arts/libraries/arts_tab_beamformer/src/vhdl/arts_tab_beamformer.vhd new file mode 100644 index 0000000000000000000000000000000000000000..0e8c6dacfd74462a2331f86d2bbbc80e82308027 --- /dev/null +++ b/applications/arts/libraries/arts_tab_beamformer/src/vhdl/arts_tab_beamformer.vhd @@ -0,0 +1,150 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2017 +-- 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/>. +-- +------------------------------------------------------------------------------- + +-- Author: +-- . Daniel van der Schuur +-- Purpose: +-- . Beamformer instance with ARTS specific weight addressing +-- Description: +-- . All comments apply to the default generic parameter values +-- . With 176 32b (16b complex) weights per stream, we'll use +-- 5632kb per stream = 1 M9K RAM per stream, or 12 M9Ks in total. + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +LIBRARY common_lib, common_mult_lib, technology_lib, dp_lib, beamformer_lib; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; + +ENTITY arts_tab_beamformer IS + GENERIC ( + g_technology : NATURAL := c_tech_select_default; + g_nof_inputs : NATURAL := 12; --12 dishes, X,Y pols interleaved + g_nof_tabs : NATURAL := 12; --12 Tied Array Beams + g_nof_beamlets : NATURAL := 88; --88 beamlets per FPGA (704 per UniBoard) in 8b mode + g_data_w : NATURAL := 8 --8b complex input data + ); + PORT ( + dp_clk : IN STD_LOGIC; + dp_rst : IN STD_LOGIC; + + mm_clk : IN STD_LOGIC; + mm_rst : IN STD_LOGIC; + + ram_mosi : IN t_mem_mosi := c_mem_mosi_rst; -- MM interface to upload weights to RAM + ram_miso : OUT t_mem_miso; + + snk_in_arr : IN t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0); -- All streams must be synchronous + src_out_arr : OUT t_dp_sosi_arr(g_nof_tabs-1 DOWNTO 0) + ); +END arts_tab_beamformer; + +ARCHITECTURE str OF arts_tab_beamformer IS + + ----------------------------------------------------------------------------- + -- dp_counter + ----------------------------------------------------------------------------- + CONSTANT c_nof_counts : NATURAL := 3; + CONSTANT c_nof_samples_per_beamlet : NATURAL := 100; --800000 + CONSTANT c_nof_pols : NATURAL := 2; + + SIGNAL dp_counter_count_src_out_arr : t_dp_sosi_arr(c_nof_counts-1 DOWNTO 0); + SIGNAL dp_counter_src_out : t_dp_sosi; + + ----------------------------------------------------------------------------- + -- beamformer + ----------------------------------------------------------------------------- + CONSTANT c_nof_weights : NATURAL := 2*g_nof_beamlets; --176 (2 (XY interleaved) * 88 beamlets) + + SIGNAL weight_addr : STD_LOGIC_VECTOR(ceil_log2(c_nof_weights)-1 DOWNTO 0); + +BEGIN + + ----------------------------------------------------------------------------- + -- dp_counter to tag input samples with useful indices + -- . c0 = range(0,1,1) c_nof_pols, X,Y + -- . c1 = range(0,800000,1) c_nof_samples_per_beamlet + -- . c2 = range(0,88,1) c_nof_beamlets + ----------------------------------------------------------------------------- + u_dp_counter : ENTITY dp_lib.dp_counter + GENERIC MAP ( + g_nof_counters => c_nof_counts,-- c2, c1, c0 + g_range_start => (0,0,0,0,0,0,0, 0, 0, 0), + g_range_stop => (0,0,0,0,0,0,0,g_nof_beamlets, c_nof_samples_per_beamlet, c_nof_pols), + g_range_step => (0,0,0,0,0,0,0, 1, 1, 1) + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + + snk_in => snk_in_arr(0), + + src_out => dp_counter_src_out, + + count_src_out_arr => dp_counter_count_src_out_arr + ); + + ------------------------------------------------------------------------------ + -- Convert (dp_counter) counts to weight address + -- . For each stream, the weights sit in RAM as follows: + -- . All X pol weights @ even offsets: 0,2,4,..,174 + -- . All Y pol weights @ odd offsets: 1,3,5,..,175 + -- . X pol Beamlet 0 @ address 0 + -- . Y pol Beamlet 0 @ address 1 + -- . X pol Beamlet 1 @ address 2 + -- . Y pol Beamlet 1 @ address 3 + -- . . + -- . . + -- . X pol Beamlet 87 @ address 174 + -- . Y pol Beamlet 87 @ address 175 + ------------------------------------------------------------------------------ + weight_addr(0) <= dp_counter_count_src_out_arr(0).data(0); -- X pol = even adress, Y pol = odd address + weight_addr(7 DOWNTO 1) <= dp_counter_count_src_out_arr(2).data(6 DOWNTO 0); -- 88 beamets @ adresses 0,2,..174. + + ----------------------------------------------------------------------------- + -- beamformer for each TAB + ----------------------------------------------------------------------------- + gen_beamformer : FOR i IN 0 TO g_nof_tabs-1 GENERATE + u_beamformer : ENTITY beamformer_lib.beamformer + GENERIC MAP ( + g_technology => g_technology, + g_nof_inputs => g_nof_inputs, + g_nof_weights => c_nof_weights, + g_data_w => g_data_w + ) + PORT MAP ( + dp_clk => dp_clk, + dp_rst => dp_rst, + + mm_clk => mm_clk, + mm_rst => mm_rst, + + weight_addr => weight_addr, + + snk_in_arr => snk_in_arr, + src_out => src_out_arr(i) + ); + END GENERATE; + +END str; diff --git a/applications/arts/libraries/arts_tab_beamformer/tb/vhdl/tb_arts_tab_beamformer.vhd b/applications/arts/libraries/arts_tab_beamformer/tb/vhdl/tb_arts_tab_beamformer.vhd new file mode 100644 index 0000000000000000000000000000000000000000..c4a52177d8ee3b15a4ff134321eac7538f170985 --- /dev/null +++ b/applications/arts/libraries/arts_tab_beamformer/tb/vhdl/tb_arts_tab_beamformer.vhd @@ -0,0 +1,152 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2017 +-- 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/>. +-- +-------------------------------------------------------------------------------- + +-- Author: +-- . Daniel van der Schuur +-- Purpose: +-- . Feed ARTS input data to arts_tab_beamformer, verify output rate +-- Description: +-- . All comments apply to the default generic parameter values + +LIBRARY IEEE, common_lib, dp_lib, diag_lib, technology_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE diag_lib.diag_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; + +ENTITY tb_arts_tab_beamformer IS + GENERIC ( + g_technology : NATURAL := c_tech_select_default; + g_nof_inputs : NATURAL := 12; --12 dishes, X,Y pols interleaved + g_nof_tabs : NATURAL := 12; --12 Tied Array Beams + g_nof_beamlets : NATURAL := 88; --88 beamlets per FPGA (704 per UniBoard) in 8b mode + g_data_w : NATURAL := 8 --8b complex input data + ); +END tb_arts_tab_beamformer; + +ARCHITECTURE tb OF tb_arts_tab_beamformer IS + + ----------------------------------------------------------------------------- + -- General + ----------------------------------------------------------------------------- + CONSTANT c_dp_clk_period : TIME := 5 ns; + CONSTANT c_mm_clk_period : TIME := 25 ns; + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL dp_clk : STD_LOGIC := '1'; + SIGNAL dp_rst : STD_LOGIC; + SIGNAL mm_clk : STD_LOGIC := '1'; + SIGNAL mm_rst : STD_LOGIC; + + ----------------------------------------------------------------------------- + -- Block generator + -- . 2 pols * 88 beamlets * 2*8b @ 781250 Hz = 2.2Gbps per stream + -- . Max data rate of 16b stream = 3.2Gbps + -- . 2.2Gbps = 3.2Gbps /256 * 176 + -- . Blocksize = 2 pols * 88 beamlets = 176 + -- . Gapsize = 256-176 + ----------------------------------------------------------------------------- + CONSTANT c_bg_block_size : NATURAL := 2*g_nof_beamlets; + CONSTANT c_bg_gapsize : NATURAL := 256-c_bg_block_size; + CONSTANT c_bg_blocks_per_sync : NATURAL := 10; --not used + CONSTANT c_bg_ctrl : t_diag_block_gen := ('1', -- enable + '0', -- enable_sync + TO_UVEC( c_bg_block_size, c_diag_bg_samples_per_packet_w), + TO_UVEC(c_bg_blocks_per_sync, c_diag_bg_blocks_per_sync_w), + TO_UVEC( c_bg_gapsize, c_diag_bg_gapsize_w), + TO_UVEC( 0, c_diag_bg_mem_low_adrs_w), + TO_UVEC( c_bg_block_size-1, c_diag_bg_mem_high_adrs_w), + TO_UVEC( 0, c_diag_bg_bsn_init_w)); + + SIGNAL block_gen_src_out_arr : t_dp_sosi_arr(1-1 DOWNTO 0); + + ----------------------------------------------------------------------------- + -- ARTS TAB beamformer + ----------------------------------------------------------------------------- + SIGNAL arts_tab_beamformer_snk_in_arr : t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0); + SIGNAL arts_tab_beamformer_src_out_arr : t_dp_sosi_arr(g_nof_tabs-1 DOWNTO 0); + +BEGIN + + ----------------------------------------------------------------------------- + -- Clocks and reset + ----------------------------------------------------------------------------- + dp_clk <= NOT dp_clk OR tb_end AFTER c_dp_clk_period/2; + dp_rst <= '1', '0' AFTER c_dp_clk_period*7; + + mm_clk <= NOT mm_clk OR tb_end AFTER c_mm_clk_period/2; + mm_rst <= '1', '0' AFTER c_mm_clk_period*7; + + ----------------------------------------------------------------------------- + -- Block generator: + -- . X pol = complex( 1, 1) + -- . Y pol = complex(-1,-1) + ----------------------------------------------------------------------------- + u_mms_diag_block_gen : ENTITY diag_lib.mms_diag_block_gen + GENERIC MAP ( + g_nof_streams => 1, + g_buf_dat_w => 2*g_data_w, + g_buf_addr_w => ceil_log2(TO_UINT(c_bg_ctrl.samples_per_packet)), + g_file_name_prefix => "hex/mms_diag_block_gen", + g_diag_block_gen_rst => c_bg_ctrl + ) + PORT MAP ( + mm_clk => mm_clk, + mm_rst => mm_rst, + + dp_clk => dp_clk, + dp_rst => dp_rst, + + out_sosi_arr => block_gen_src_out_arr + ); + + ----------------------------------------------------------------------------- + -- Device under test: ARTS TAB beamformer + -- . All outputs = 1+1j, -1-1j, 2+2j, -2-2j, .. 175+175j, -175-175j times g_nof_inputs. + ----------------------------------------------------------------------------- + gen_arts_tab_beamformer_snk_in_arr : FOR i IN 0 TO g_nof_inputs-1 GENERATE + arts_tab_beamformer_snk_in_arr(i) <= block_gen_src_out_arr(0); -- Copy the block gen stream 12 times + END GENERATE; + + u_arts_tab_beamformer : ENTITY work.arts_tab_beamformer + GENERIC MAP ( + g_technology => g_nof_beamlets, + g_nof_inputs => g_nof_inputs, + g_nof_tabs => g_nof_tabs, + g_nof_beamlets => g_nof_beamlets, + g_data_w => g_data_w + ) + PORT MAP ( + dp_clk => dp_clk, + dp_rst => dp_rst, + + mm_clk => mm_clk, + mm_rst => mm_rst, + + snk_in_arr => arts_tab_beamformer_snk_in_arr, + src_out_arr => arts_tab_beamformer_src_out_arr + ); + +END tb; diff --git a/libraries/dsp/beamformer/hdllib.cfg b/libraries/dsp/beamformer/hdllib.cfg new file mode 100644 index 0000000000000000000000000000000000000000..85c0204b1f9fdc86a431defd9efa1805c8b0a1f7 --- /dev/null +++ b/libraries/dsp/beamformer/hdllib.cfg @@ -0,0 +1,21 @@ +hdl_lib_name = beamformer +hdl_library_clause_name = beamformer_lib +hdl_lib_uses_synth = common common_mult technology mm dp +hdl_lib_uses_sim = +hdl_lib_technology = + +synth_files = + src/vhdl/beamformer.vhd + +test_bench_files = + tb/vhdl/tb_beamformer.vhd + +regression_test_vhdl = + # no self checking tb available yet + + +[modelsim_project_file] + + +[quartus_project_file] + diff --git a/libraries/dsp/beamformer/src/vhdl/beamformer.vhd b/libraries/dsp/beamformer/src/vhdl/beamformer.vhd new file mode 100644 index 0000000000000000000000000000000000000000..bf0ff81186028658073e7f1dec473202a5112d77 --- /dev/null +++ b/libraries/dsp/beamformer/src/vhdl/beamformer.vhd @@ -0,0 +1,225 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2017 +-- 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/>. +-- +------------------------------------------------------------------------------- + +-- Author: +-- . Daniel van der Schuur +-- Purpose: +-- . Structural beamformer using weights RAM, multiplier and adder stage +-- Description: +-- . This beamformer multiplies each valid input sample of snk_in_arr by +-- weights read from RAM, and adds the resulting products of all streams +-- together into a single output stream. +-- . The weight is taken from the RAM that corresponds to the snk_in stream +-- index. +-- . To keep this beamformer generic and easily reusable the user can wrap +-- this beamformer with simple application specific logic to control +-- weight_addr. +-- . Input/output reordering and quantization are also application +-- specific and should be done in the wrapper. +-- . The input array snk_in_arr must be synchronous. + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +LIBRARY common_lib, common_mult_lib, technology_lib, dp_lib; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; + +ENTITY beamformer IS + GENERIC ( + g_technology : NATURAL := c_tech_select_default; + g_nof_inputs : NATURAL; + g_data_w : NATURAL; + g_nof_weights : NATURAL; + g_weights_w : NATURAL := 16; + g_weights_file : STRING := "hex/beamformer_weights"; + g_weights_write_only : BOOLEAN := FALSE + ); + PORT ( + dp_clk : IN STD_LOGIC; + dp_rst : IN STD_LOGIC; + + mm_clk : IN STD_LOGIC; + mm_rst : IN STD_LOGIC; + + ram_mosi : IN t_mem_mosi := c_mem_mosi_rst; -- MM interface to upload weights to RAM + ram_miso : OUT t_mem_miso; + + weight_addr : IN STD_LOGIC_VECTOR(ceil_log2(g_nof_weights)-1 DOWNTO 0); -- Weight RAM address + + snk_in_arr : IN t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0); -- All streams must be synchronous + src_out : OUT t_dp_sosi + ); +END beamformer; + +ARCHITECTURE str OF beamformer IS + + ------------------------------------------------------------------------------ + -- Weights RAM + ------------------------------------------------------------------------------ + CONSTANT c_common_ram_crw_crw_ram : t_c_mem := (latency => 1, + adr_w => ceil_log2(g_nof_weights), + dat_w => c_nof_complex*g_weights_w, + nof_dat => g_nof_weights, + init_sl => '0'); + + TYPE t_common_ram_crw_crw_adr_b_arr IS ARRAY(g_nof_inputs-1 DOWNTO 0) OF STD_LOGIC_VECTOR(ceil_log2(g_nof_weights)-1 DOWNTO 0); + TYPE t_common_ram_crw_crw_rd_dat_b_arr IS ARRAY(g_nof_inputs-1 DOWNTO 0) OF STD_LOGIC_VECTOR(c_nof_complex*g_weights_w-1 DOWNTO 0); + + SIGNAL ram_mosi_arr : t_mem_mosi_arr(g_nof_inputs-1 DOWNTO 0); + SIGNAL ram_miso_arr : t_mem_miso_arr(g_nof_inputs-1 DOWNTO 0); + + SIGNAL common_ram_crw_crw_adr_b_arr : t_common_ram_crw_crw_adr_b_arr; + SIGNAL common_ram_crw_crw_rd_en_b_arr : STD_LOGIC_VECTOR(g_nof_inputs-1 DOWNTO 0); + SIGNAL common_ram_crw_crw_rd_dat_b_arr : t_common_ram_crw_crw_rd_dat_b_arr; + SIGNAL common_ram_crw_crw_rd_val_b_arr : STD_LOGIC_VECTOR(g_nof_inputs-1 DOWNTO 0); + + SIGNAL common_ram_crw_crw_src_out_arr : t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0); + + ------------------------------------------------------------------------------ + -- Pipeline + ------------------------------------------------------------------------------ + SIGNAL dp_pipeline_arr_src_out_arr : t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0); + + ------------------------------------------------------------------------------ + -- Multiplier stage + ------------------------------------------------------------------------------ + SIGNAL dp_complex_mult_snk_in_2arr_2 : t_dp_sosi_2arr_2(g_nof_inputs-1 DOWNTO 0); + SIGNAL dp_complex_mult_src_out_arr : t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0); + +BEGIN + + ------------------------------------------------------------------------------ + -- Weights RAM + ------------------------------------------------------------------------------ + gen_common_ram_crw_crw : FOR i IN 0 TO g_nof_inputs-1 GENERATE + + -- Read request on every incoming valid cycle + common_ram_crw_crw_rd_en_b_arr(i) <= snk_in_arr(i).valid; + + -- Use entity input for read address + common_ram_crw_crw_adr_b_arr(i) <= weight_addr; + + -- Dual clock RAM + u_common_ram_crw_crw : ENTITY common_lib.common_ram_crw_crw + GENERIC MAP ( + g_technology => g_technology, + g_ram => c_common_ram_crw_crw_ram, +-- g_init_file => g_weights_file & "_" & NATURAL'IMAGE(i) & ".hex", + g_true_dual_port => FALSE --NOT(g_weights_write_only) + ) + PORT MAP ( + rst_a => mm_rst, + clk_a => mm_clk, + wr_en_a => ram_mosi_arr(i).wr, + wr_dat_a => ram_mosi_arr(i).wrdata(c_common_ram_crw_crw_ram.dat_w -1 DOWNTO 0), + adr_a => ram_mosi_arr(i).address(c_common_ram_crw_crw_ram.adr_w-1 DOWNTO 0), + rd_en_a => ram_mosi_arr(i).rd, + rd_dat_a => ram_miso_arr(i).rddata(c_common_ram_crw_crw_ram.dat_w -1 DOWNTO 0), + rd_val_a => ram_miso_arr(i).rdval, + + rst_b => dp_rst, + clk_b => dp_clk, + wr_en_b => '0', + wr_dat_b => (OTHERS =>'0'), + adr_b => common_ram_crw_crw_adr_b_arr(i), + rd_en_b => common_ram_crw_crw_rd_en_b_arr(i), + rd_dat_b => common_ram_crw_crw_rd_dat_b_arr(i), + rd_val_b => common_ram_crw_crw_rd_val_b_arr(i) + ); + + -- RAM output rewired to SOSI array + common_ram_crw_crw_src_out_arr(i).re(g_weights_w-1 DOWNTO 0) <= common_ram_crw_crw_rd_dat_b_arr(i)( g_weights_w-1 DOWNTO 0); + common_ram_crw_crw_src_out_arr(i).im(g_weights_w-1 DOWNTO 0) <= common_ram_crw_crw_rd_dat_b_arr(i)(2*g_weights_w-1 DOWNTO g_weights_w); + common_ram_crw_crw_src_out_arr(i).valid <= common_ram_crw_crw_rd_val_b_arr(i); + + END GENERATE; + + -- Combine the individual RAM MM buses into one + u_common_mem_mux : ENTITY common_lib.common_mem_mux + GENERIC MAP ( + g_nof_mosi => g_nof_inputs, + g_mult_addr_w => ceil_log2(g_nof_weights) + ) + PORT MAP ( + mosi => ram_mosi, + miso => ram_miso, + mosi_arr => ram_mosi_arr, + miso_arr => ram_miso_arr + ); + + ------------------------------------------------------------------------------ + -- Pipeline to align snk_in_arr with dp_ram_src_out_arr + ------------------------------------------------------------------------------ + u_dp_pipeline_arr : ENTITY dp_lib.dp_pipeline_arr + GENERIC MAP( + g_nof_streams => g_nof_inputs, + g_pipeline => 1 + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + + snk_in_arr => common_ram_crw_crw_src_out_arr, + + src_out_arr => dp_pipeline_arr_src_out_arr + ); + + ------------------------------------------------------------------------------ + -- Multiplier stage + ------------------------------------------------------------------------------ + gen_mult_inputs: FOR i IN 0 TO g_nof_inputs-1 GENERATE + dp_complex_mult_snk_in_2arr_2(i)(0) <= dp_pipeline_arr_src_out_arr(i); -- Streaming data + dp_complex_mult_snk_in_2arr_2(i)(1) <= common_ram_crw_crw_src_out_arr(i); -- Weights RAM + END GENERATE; + + u_dp_complex_mult : ENTITY dp_lib.dp_complex_mult + GENERIC MAP ( + g_nof_multipliers => g_nof_inputs, + g_data_w => g_data_w + ) + PORT MAP ( + clk => dp_clk, + rst => dp_rst, + + snk_in_2arr_2 => dp_complex_mult_snk_in_2arr_2, + src_out_arr => dp_complex_mult_src_out_arr + ); + + ------------------------------------------------------------------------------ + -- Adder stage + ------------------------------------------------------------------------------ + u_dp_complex_add : ENTITY dp_lib.dp_complex_add + GENERIC MAP ( + g_nof_inputs => g_nof_inputs, + g_data_w => 2*g_data_w + ) + PORT MAP ( + clk => dp_clk, + rst => dp_rst, + + snk_in_arr => dp_complex_mult_src_out_arr, + src_out => src_out + ); + +END str; diff --git a/libraries/dsp/beamformer/tb/vhdl/tb_beamformer.vhd b/libraries/dsp/beamformer/tb/vhdl/tb_beamformer.vhd new file mode 100644 index 0000000000000000000000000000000000000000..1d776c18af182faea91474372222cfaa1eab6215 --- /dev/null +++ b/libraries/dsp/beamformer/tb/vhdl/tb_beamformer.vhd @@ -0,0 +1,103 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2017 +-- 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/>. +-- +-------------------------------------------------------------------------------- + +-- Author: +-- . Daniel van der Schuur +-- Purpose: +-- . +-- Description: +-- . + +LIBRARY IEEE, common_lib, dp_lib, technology_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; + +ENTITY tb_beamformer IS + GENERIC ( + g_technology : NATURAL := c_tech_select_default; + g_nof_inputs : NATURAL := 4; + g_nof_weights : NATURAL := 32; + g_data_w : NATURAL := 8 --8b complex input data + ); +END tb_beamformer; + +ARCHITECTURE tb OF tb_beamformer IS + + ----------------------------------------------------------------------------- + -- General + ----------------------------------------------------------------------------- + CONSTANT c_dp_clk_period : TIME := 5 ns; + CONSTANT c_mm_clk_period : TIME := 25 ns; + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL dp_clk : STD_LOGIC := '1'; + SIGNAL dp_rst : STD_LOGIC; + SIGNAL mm_clk : STD_LOGIC := '1'; + SIGNAL mm_rst : STD_LOGIC; + + ----------------------------------------------------------------------------- + -- beamformer + ----------------------------------------------------------------------------- + SIGNAL beamformer_snk_in_arr : t_dp_sosi_arr(g_nof_inputs-1 DOWNTO 0); + SIGNAL beamformer_src_out : t_dp_sosi; + + SIGNAL beamformer_weight_addr : STD_LOGIC_VECTOR(ceil_log2(g_nof_weights)-1 DOWNTO 0); + +BEGIN + + ----------------------------------------------------------------------------- + -- Clocks and reset + ----------------------------------------------------------------------------- + dp_clk <= NOT dp_clk OR tb_end AFTER c_dp_clk_period/2; + dp_rst <= '1', '0' AFTER c_dp_clk_period*7; + + mm_clk <= NOT mm_clk OR tb_end AFTER c_mm_clk_period/2; + mm_rst <= '1', '0' AFTER c_mm_clk_period*7; + + ----------------------------------------------------------------------------- + -- beamformer for each TAB + ----------------------------------------------------------------------------- + u_beamformer : ENTITY work.beamformer + GENERIC MAP ( + g_technology => g_technology, + g_nof_inputs => g_nof_inputs, + g_nof_weights => g_nof_weights, + g_data_w => g_data_w + ) + PORT MAP ( + dp_clk => dp_clk, + dp_rst => dp_rst, + + mm_clk => mm_clk, + mm_rst => mm_rst, + + weight_addr => beamformer_weight_addr, + + snk_in_arr => beamformer_snk_in_arr, + src_out => beamformer_src_out + ); + +END tb;