From 070604c170f26dbba8ddce9e7d93b6770a826255 Mon Sep 17 00:00:00 2001 From: Reinier van der Walle <walle@astron.nl> Date: Thu, 6 May 2021 09:56:27 +0200 Subject: [PATCH] added tb_st_xsq --- libraries/base/common/hdllib.cfg | 2 +- .../base/common/src/vhdl/common_math_pkg.vhd | 21 +- libraries/dsp/st/hdllib.cfg | 2 + libraries/dsp/st/src/vhdl/st_pkg.vhd | 54 +++++ libraries/dsp/st/src/vhdl/st_xsq.vhd | 14 +- libraries/dsp/st/tb/vhdl/tb_st_xsq.vhd | 225 ++++++++++++++++++ 6 files changed, 308 insertions(+), 10 deletions(-) create mode 100644 libraries/dsp/st/src/vhdl/st_pkg.vhd create mode 100644 libraries/dsp/st/tb/vhdl/tb_st_xsq.vhd diff --git a/libraries/base/common/hdllib.cfg b/libraries/base/common/hdllib.cfg index 75b70901a1..e95d804fc6 100644 --- a/libraries/base/common/hdllib.cfg +++ b/libraries/base/common/hdllib.cfg @@ -8,9 +8,9 @@ synth_files = $RADIOHDL_WORK/libraries/base/common/src/vhdl/common_pkg.vhd src/vhdl/common_str_pkg.vhd src/vhdl/common_mem_pkg.vhd - src/vhdl/common_math_pkg.vhd src/vhdl/common_field_pkg.vhd src/vhdl/common_lfsr_sequences_pkg.vhd + src/vhdl/common_math_pkg.vhd src/vhdl/common_interface_layers_pkg.vhd src/vhdl/common_network_layers_pkg.vhd src/vhdl/common_network_total_header_pkg.vhd diff --git a/libraries/base/common/src/vhdl/common_math_pkg.vhd b/libraries/base/common/src/vhdl/common_math_pkg.vhd index 0cbb134183..8455d30e7d 100644 --- a/libraries/base/common/src/vhdl/common_math_pkg.vhd +++ b/libraries/base/common/src/vhdl/common_math_pkg.vhd @@ -36,7 +36,7 @@ LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.MATH_REAL.ALL; USE work.common_pkg.ALL; - +USE work.common_lfsr_sequences_pkg.ALL; PACKAGE common_math_pkg IS @@ -79,7 +79,10 @@ PACKAGE common_math_pkg IS -- To create an FFT input phasor with frequency in the middle of a channel use FREQ = ch. FUNCTION common_math_create_look_up_table_phasor(N, W : POSITIVE; AMPL, FREQ, PHI : REAL) RETURN t_nat_integer_arr; FUNCTION common_math_create_look_up_table_phasor(N, W : POSITIVE; AMPL, FREQ, PHI : REAL) RETURN t_slv_32_arr; -- range 0 TO N-1 - + + FUNCTION common_math_create_random_arr(N, W : POSITIVE) RETURN t_integer_arr; + + END common_math_pkg; @@ -178,6 +181,18 @@ PACKAGE BODY common_math_pkg IS END LOOP; RETURN v_exp_arr; END; - + + FUNCTION common_math_create_random_arr(N, W : POSITIVE) RETURN t_integer_arr IS + VARIABLE v_rand_arr : t_integer_arr(0 TO N-1); + VARIABLE v_random : STD_LOGIC_VECTOR(W-1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + FOR I IN 0 TO N-1 LOOP + v_random := func_common_random(v_random); + v_rand_arr(I) := TO_SINT(v_random); + END LOOP; + RETURN v_rand_arr; + END; + + END common_math_pkg; diff --git a/libraries/dsp/st/hdllib.cfg b/libraries/dsp/st/hdllib.cfg index ae82da9fbc..7203491a3b 100644 --- a/libraries/dsp/st/hdllib.cfg +++ b/libraries/dsp/st/hdllib.cfg @@ -5,6 +5,7 @@ hdl_lib_uses_sim = hdl_lib_technology = synth_files = + src/vhdl/st_pkg.vhd src/vhdl/st_acc.vhd src/vhdl/st_ctrl.vhd src/vhdl/st_calc.vhd @@ -21,6 +22,7 @@ test_bench_files = tb/vhdl/tb_st_acc.vhd tb/vhdl/tb_st_calc.vhd tb/vhdl/tb_mmf_st_sst.vhd + tb/vhdl/tb_st_xsq.vhd tb/vhdl/tb_st_histogram.vhd tb/vhdl/tb_mms_st_histogram.vhd tb/vhdl/tb_tb_st_histogram.vhd diff --git a/libraries/dsp/st/src/vhdl/st_pkg.vhd b/libraries/dsp/st/src/vhdl/st_pkg.vhd new file mode 100644 index 0000000000..b790afd6a2 --- /dev/null +++ b/libraries/dsp/st/src/vhdl/st_pkg.vhd @@ -0,0 +1,54 @@ +------------------------------------------------------------------------------- +-- +-- 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. vd Walle +-- Purpose: +-- Functions used in st_lib +LIBRARY IEEE, common_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; + +PACKAGE st_pkg IS + + FUNCTION func_st_calculate_expected_xsq(a_re, a_im, b_re, b_im : t_integer_arr; N_crosslets, N_int : NATURAL) RETURN t_integer_arr; + +END st_pkg; + +PACKAGE BODY st_pkg IS + + FUNCTION func_st_calculate_expected_xsq(a_re, a_im, b_re, b_im : t_integer_arr; N_crosslets, N_int : NATURAL) RETURN t_integer_arr IS + CONSTANT c_N_s : NATURAL := a_re'LENGTH/N_crosslets; + CONSTANT c_xsq : NATURAL := c_N_s * c_N_s; + CONSTANT c_N_stat : NATURAL := N_crosslets * c_xsq; + VARIABLE v_exp_xsq : t_integer_arr(0 TO c_nof_complex * c_N_stat-1); + BEGIN + + FOR N IN 0 TO N_crosslets-1 LOOP + FOR I IN 0 TO c_N_s-1 LOOP + FOR J IN 0 TO c_N_s-1 LOOP + v_exp_xsq(c_nof_complex * (N*c_xsq + I*c_N_s+J) ) := N_int * COMPLEX_MULT_REAL(a_re(N*c_N_s +I), a_im(N*c_N_s +I), b_re(N*c_N_s +J), b_im(N*c_N_s +J)); + v_exp_xsq(c_nof_complex * (N*c_xsq + I*c_N_s+J)+1) := N_int * COMPLEX_MULT_IMAG(a_re(N*c_N_s +I), a_im(N*c_N_s +I), b_re(N*c_N_s +J), b_im(N*c_N_s +J)); + END LOOP; + END LOOP; + END LOOP; + RETURN v_exp_xsq; + END; + +END st_pkg; diff --git a/libraries/dsp/st/src/vhdl/st_xsq.vhd b/libraries/dsp/st/src/vhdl/st_xsq.vhd index b151affbd5..91ee30fc53 100644 --- a/libraries/dsp/st/src/vhdl/st_xsq.vhd +++ b/libraries/dsp/st/src/vhdl/st_xsq.vhd @@ -65,8 +65,8 @@ ENTITY st_xsq IS in_b : IN t_dp_sosi; -- Complex input data -- Memory Mapped - ram_st_xsq_mosi : IN t_mem_mosi; - ram_st_xsq_miso : OUT t_mem_miso + ram_st_xsq_mosi : IN t_mem_mosi := c_mem_mosi_rst; + ram_st_xsq_miso : OUT t_mem_miso := c_mem_miso_rst ); END st_xsq; @@ -79,6 +79,7 @@ ARCHITECTURE str OF st_xsq IS CONSTANT c_nof_word : NATURAL := g_stat_data_sz*c_nof_statistics; CONSTANT c_nof_word_w : NATURAL := ceil_log2(c_nof_word); CONSTANT c_stat_word_w : NATURAL := g_stat_data_sz*c_word_w; + CONSTANT c_total_ram_addr_w : NATURAL := ceil_log2(c_nof_complex) + c_nof_word_w; -- Statistics register CONSTANT c_mm_ram : t_c_mem := (latency => 1, @@ -139,13 +140,14 @@ BEGIN --------------------------------------------------------------- -- COMBINE MEMORY MAPPED INTERFACES --------------------------------------------------------------- - -- Translate incoming MM interface [N_crosslets][S_pn A][S_pn B][N_complex] to - -- [N_complex][N_crosslets][S_pn A][S_pn B] + -- Translate incoming MM interface [N_crosslets][S_pn A][S_pn B][N_complex][word] to + -- [N_complex][N_crosslets][S_pn A][S_pn B][word] p_remap : PROCESS(ram_st_xsq_mosi) BEGIN remapped_ram_st_xsq_mosi <= ram_st_xsq_mosi; - remapped_ram_st_xsq_mosi.address(ceil_log2(c_nof_complex)+c_nof_word_w -1 DOWNTO c_nof_word_w) <= ram_st_xsq_mosi.address(ceil_log2(c_nof_complex)-1 DOWNTO 0); - remapped_ram_st_xsq_mosi.address(c_nof_word_w -1 DOWNTO 0) <= ram_st_xsq_mosi.address(ceil_log2(c_nof_complex)+c_nof_word_w -1 DOWNTO ceil_log2(c_nof_complex)); + -- + remapped_ram_st_xsq_mosi.address(c_total_ram_addr_w -1 DOWNTO c_nof_word_w) <= ram_st_xsq_mosi.address(ceil_log2(c_nof_complex)+ceil_log2(g_stat_data_sz)-1 DOWNTO ceil_log2(g_stat_data_sz)); + remapped_ram_st_xsq_mosi.address(c_nof_word_w -1 DOWNTO 0) <= ram_st_xsq_mosi.address(c_total_ram_addr_w -1 DOWNTO ceil_log2(c_nof_complex)+ceil_log2(g_stat_data_sz)) & ram_st_xsq_mosi.address(ceil_log2(g_stat_data_sz)-1 DOWNTO 0); END PROCESS; -- Combine the internal array of mm interfaces for both real diff --git a/libraries/dsp/st/tb/vhdl/tb_st_xsq.vhd b/libraries/dsp/st/tb/vhdl/tb_st_xsq.vhd new file mode 100644 index 0000000000..29b752acce --- /dev/null +++ b/libraries/dsp/st/tb/vhdl/tb_st_xsq.vhd @@ -0,0 +1,225 @@ + +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2012 +-- 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/>. +-- +------------------------------------------------------------------------------- +-- +-- Purpose: Testbench for the st_xsq unit. +-- +-- +-- Usage in non-auto-mode (c_modelsim_start = 0 in python): +-- > as 5 +-- > run -all +-- > Run python script in separate terminal: "python tc_mmf_st_xst.py --unb 0 --bn 0 --sim" +-- > Check the results of the python script. +-- > Stop the simulation manually in Modelsim by pressing the stop-button. +-- > Evalute the WAVE window. + +LIBRARY IEEE, common_lib, mm_lib, diag_lib, dp_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_math_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE common_lib.common_str_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE common_lib.tb_common_mem_pkg.ALL; +USE common_lib.common_lfsr_sequences_pkg.ALL; +USE mm_lib.mm_file_unb_pkg.ALL; +USE mm_lib.mm_file_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE diag_lib.diag_pkg.ALL; +USE dp_lib.tb_dp_pkg.ALL; +USE work.st_pkg.ALL; + +ENTITY tb_st_xsq IS + GENERIC( + g_nof_crosslets : NATURAL := 1; + g_nof_signal_inputs : NATURAL := 2; + g_in_data_w : NATURAL := 16; + g_stat_data_w : NATURAL := 32; -- statistics accumulator width + g_stat_data_sz : NATURAL := 2; -- statistics word width >= statistics accumulator width and fit in a power of 2 multiple 32b MM words + g_nof_sync : NATURAL := 3; + g_nof_block_per_sync : NATURAL := 20; + g_nof_clk_per_blk : NATURAL := 512 + ); +END tb_st_xsq; + +ARCHITECTURE tb OF tb_st_xsq IS + + CONSTANT c_sim : BOOLEAN := TRUE; + CONSTANT c_rl : NATURAL := 1; + CONSTANT c_block_size : NATURAL := g_nof_crosslets * g_nof_signal_inputs; + CONSTANT c_gap_size : NATURAL := g_nof_clk_per_blk - c_block_size; + + CONSTANT c_xsq : NATURAL := g_nof_signal_inputs * g_nof_signal_inputs; + CONSTANT c_nof_statistics : NATURAL := g_nof_crosslets * c_xsq; + + CONSTANT c_random_in_a_re : t_integer_arr(0 TO c_block_size-1) := common_math_create_random_arr(c_block_size, g_in_data_w); + CONSTANT c_random_in_a_im : t_integer_arr(0 TO c_block_size-1) := common_math_create_random_arr(c_block_size, g_in_data_w-1); + CONSTANT c_random_in_b_re : t_integer_arr(0 TO c_block_size-1) := common_math_create_random_arr(c_block_size, g_in_data_w-2); + CONSTANT c_random_in_b_im : t_integer_arr(0 TO c_block_size-1) := common_math_create_random_arr(c_block_size, g_in_data_w-3); + + CONSTANT c_expected_xsq : t_integer_arr(0 TO c_nof_statistics * c_nof_complex-1) := func_st_calculate_expected_xsq(c_random_in_a_re, c_random_in_a_im, c_random_in_b_re, c_random_in_b_im, g_nof_crosslets, g_nof_block_per_sync); + ---------------------------------------------------------------------------- + -- Clocks and resets + ---------------------------------------------------------------------------- + CONSTANT c_mm_clk_period : TIME := 100 ps; + CONSTANT c_dp_clk_period : TIME := 5 ns; + CONSTANT c_dp_pps_period : NATURAL := 64; + + SIGNAL tb_end : STD_LOGIC; + SIGNAL dp_pps : STD_LOGIC; + + SIGNAL mm_rst : STD_LOGIC := '1'; + SIGNAL mm_clk : STD_LOGIC := '1'; + + SIGNAL dp_rst : STD_LOGIC; + SIGNAL dp_clk : STD_LOGIC := '1'; + + SIGNAL st_en : STD_LOGIC := '1'; + SIGNAL st_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL st_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL in_sosi_a : t_dp_sosi := c_dp_sosi_rst; + SIGNAL in_sosi_b : t_dp_sosi := c_dp_sosi_rst; + + ---------------------------------------------------------------------------- + -- MM buses + ---------------------------------------------------------------------------- + SIGNAL ram_st_xsq_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL ram_st_xsq_miso : t_mem_miso := c_mem_miso_rst; + SIGNAL st_xsq_out_arr : t_slv_32_arr(0 TO c_nof_statistics * c_nof_complex * g_stat_data_sz-1) := (OTHERS => (OTHERS => '0')); +BEGIN + + ---------------------------------------------------------------------------- + -- Clock and reset generation + ---------------------------------------------------------------------------- + mm_clk <= NOT mm_clk OR tb_end AFTER c_mm_clk_period/2; + mm_rst <= '1', '0' AFTER c_mm_clk_period*5; + + dp_clk <= NOT dp_clk OR tb_end AFTER c_dp_clk_period/2; + dp_rst <= '1', '0' AFTER c_dp_clk_period*5; + + ------------------------------------------------------------------------------ + -- MM Stimuli + ------------------------------------------------------------------------------ + p_mm_stimuli : PROCESS + BEGIN + FOR I IN 0 TO g_nof_sync -1 LOOP + proc_common_wait_until_lo_hi(dp_clk, st_sosi.sync); + END LOOP; + proc_common_wait_some_cycles(dp_clk, 3); + -- read ram + proc_mem_read_ram(0, c_nof_statistics * c_nof_complex * g_stat_data_sz, mm_clk, ram_st_xsq_mosi, ram_st_xsq_miso, st_xsq_out_arr); + WAIT; + END PROCESS; + + ------------------------------------------------------------------------------ + -- Data blocks + ------------------------------------------------------------------------------ + p_st_stimuli : PROCESS + VARIABLE v_re : NATURAL := 0; + VARIABLE v_im : NATURAL := 0; + BEGIN + tb_end <= '0'; + st_sosi <= c_dp_sosi_rst; + proc_common_wait_until_low(dp_clk, dp_rst); + + -- Run some sync intervals with DSP counter data for the real and imag fields + WAIT UNTIL rising_edge(dp_clk); + FOR I IN 0 TO g_nof_sync-1 LOOP + proc_dp_gen_block_data(c_rl, FALSE, g_in_data_w, g_in_data_w, 0, v_re, v_im, c_block_size, 0, 0, '1', "0", dp_clk, st_en, st_siso, st_sosi); -- next sync + st_sosi <= c_dp_sosi_rst; + proc_common_wait_some_cycles(dp_clk, c_gap_size); + FOR J IN 0 TO g_nof_block_per_sync-2 LOOP -- provide sop and eop for block reference + proc_dp_gen_block_data(c_rl, FALSE, g_in_data_w, g_in_data_w, 0, v_re, v_im, c_block_size, 0, 0, '0', "0", dp_clk, st_en, st_siso, st_sosi); -- no sync + st_sosi <= c_dp_sosi_rst; + proc_common_wait_some_cycles(dp_clk, c_gap_size); + END LOOP; + END LOOP; + st_sosi <= c_dp_sosi_rst; + proc_common_wait_some_cycles(dp_clk, 100); + tb_end <= '1'; + WAIT; + END PROCESS; + + in_sosi_a.sync <= st_sosi.sync; + in_sosi_b.sync <= st_sosi.sync; + in_sosi_a.sop <= st_sosi.sop; + in_sosi_b.sop <= st_sosi.sop; + in_sosi_a.eop <= st_sosi.eop; + in_sosi_b.eop <= st_sosi.eop; + in_sosi_a.valid <= st_sosi.valid; + in_sosi_b.valid <= st_sosi.valid; + + p_random_stimuli : PROCESS + BEGIN + FOR I IN 0 TO g_nof_sync * g_nof_block_per_sync-1 LOOP + WAIT UNTIL rising_edge(st_sosi.sop); + FOR J IN 0 TO c_block_size-1 LOOP + in_sosi_a.re <= TO_DP_DSP_DATA(c_random_in_a_re(J)); + in_sosi_a.im <= TO_DP_DSP_DATA(c_random_in_a_im(J)); + in_sosi_b.re <= TO_DP_DSP_DATA(c_random_in_b_re(J)); + in_sosi_b.im <= TO_DP_DSP_DATA(c_random_in_b_im(J)); + proc_common_wait_some_cycles(dp_clk, 1); + END LOOP; + END LOOP; + WAIT; + END PROCESS; + + ------------------------------------------------------------------------------ + -- Verification + ------------------------------------------------------------------------------ + p_verify : PROCESS + BEGIN + proc_common_wait_until_high(mm_clk, ram_st_xsq_miso.rdval); + proc_common_wait_some_cycles(mm_clk, c_nof_statistics * c_nof_complex * g_stat_data_sz + 10); + FOR I IN 0 TO c_nof_statistics * c_nof_complex -1 LOOP + ASSERT TO_SINT(st_xsq_out_arr(I*2)) = c_expected_xsq(I) REPORT "WRONG XSQ DATA" SEVERITY ERROR; -- Only read low part of statistic + END LOOP; + WAIT; + END PROCESS; + + ---------------------------------------------------------------------------- + -- DUT: Device Under Test + ---------------------------------------------------------------------------- + u_dut : ENTITY work.st_xsq + GENERIC MAP( + g_nof_signal_inputs => g_nof_signal_inputs, + g_nof_crosslets => g_nof_crosslets, + g_in_data_w => g_in_data_w, + g_stat_data_w => g_stat_data_w, + g_stat_data_sz => g_stat_data_sz + ) + PORT MAP( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + + -- Streaming + in_a => in_sosi_a, + in_b => in_sosi_b, + + -- Memory Mapped + ram_st_xsq_mosi => ram_st_xsq_mosi, + ram_st_xsq_miso => ram_st_xsq_miso + ); + +END tb; -- GitLab