From 5f58358e7d88418baf41231a1beed56879e31fd7 Mon Sep 17 00:00:00 2001 From: Reinier van der Walle <walle@astron.nl> Date: Thu, 6 May 2021 14:41:00 +0200 Subject: [PATCH] fixed testbench and st_xsq to match expecting xsq values. also added tb_tb_st_xsq --- .../base/common/src/vhdl/common_math_pkg.vhd | 6 +- libraries/dsp/st/hdllib.cfg | 2 + libraries/dsp/st/src/vhdl/st_pkg.vhd | 4 +- libraries/dsp/st/src/vhdl/st_xsq.vhd | 81 +++++++++++++------ libraries/dsp/st/tb/vhdl/tb_st_xsq.vhd | 80 +++++++++--------- libraries/dsp/st/tb/vhdl/tb_tb_st_xsq.vhd | 56 +++++++++++++ 6 files changed, 161 insertions(+), 68 deletions(-) create mode 100644 libraries/dsp/st/tb/vhdl/tb_tb_st_xsq.vhd diff --git a/libraries/base/common/src/vhdl/common_math_pkg.vhd b/libraries/base/common/src/vhdl/common_math_pkg.vhd index 8455d30e7d..1fd31bbd37 100644 --- a/libraries/base/common/src/vhdl/common_math_pkg.vhd +++ b/libraries/base/common/src/vhdl/common_math_pkg.vhd @@ -80,7 +80,7 @@ PACKAGE common_math_pkg IS 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; + FUNCTION common_math_create_random_arr(N, W : POSITIVE; seed : NATURAL) RETURN t_integer_arr; END common_math_pkg; @@ -182,9 +182,9 @@ PACKAGE BODY common_math_pkg IS RETURN v_exp_arr; END; - FUNCTION common_math_create_random_arr(N, W : POSITIVE) RETURN t_integer_arr IS + FUNCTION common_math_create_random_arr(N, W : POSITIVE; seed : NATURAL) 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'); + VARIABLE v_random : STD_LOGIC_VECTOR(W-1 DOWNTO 0) := TO_UVEC(seed, W); BEGIN FOR I IN 0 TO N-1 LOOP v_random := func_common_random(v_random); diff --git a/libraries/dsp/st/hdllib.cfg b/libraries/dsp/st/hdllib.cfg index 7203491a3b..e1d6eb86e1 100644 --- a/libraries/dsp/st/hdllib.cfg +++ b/libraries/dsp/st/hdllib.cfg @@ -23,12 +23,14 @@ test_bench_files = tb/vhdl/tb_st_calc.vhd tb/vhdl/tb_mmf_st_sst.vhd tb/vhdl/tb_st_xsq.vhd + tb/vhdl/tb_tb_st_xsq.vhd tb/vhdl/tb_st_histogram.vhd tb/vhdl/tb_mms_st_histogram.vhd tb/vhdl/tb_tb_st_histogram.vhd regression_test_vhdl = tb/vhdl/tb_st_acc.vhd + tb/vhdl/tb_tb_st_xsq.vhd #tb/vhdl/tb_st_calc.vhd -- tb is not self checking yet diff --git a/libraries/dsp/st/src/vhdl/st_pkg.vhd b/libraries/dsp/st/src/vhdl/st_pkg.vhd index b790afd6a2..c9014472ab 100644 --- a/libraries/dsp/st/src/vhdl/st_pkg.vhd +++ b/libraries/dsp/st/src/vhdl/st_pkg.vhd @@ -43,8 +43,8 @@ PACKAGE BODY st_pkg IS 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)); + 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), -1 * 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), -1 * b_im(N * c_N_s + J)); END LOOP; END LOOP; END LOOP; diff --git a/libraries/dsp/st/src/vhdl/st_xsq.vhd b/libraries/dsp/st/src/vhdl/st_xsq.vhd index 91ee30fc53..524b51f5e4 100644 --- a/libraries/dsp/st/src/vhdl/st_xsq.vhd +++ b/libraries/dsp/st/src/vhdl/st_xsq.vhd @@ -72,27 +72,27 @@ END st_xsq; ARCHITECTURE str OF st_xsq IS - CONSTANT c_xsq : NATURAL := g_nof_signal_inputs * g_nof_signal_inputs; - CONSTANT c_nof_statistics : NATURAL := g_nof_crosslets * c_xsq; - - CONSTANT c_nof_stat_w : NATURAL := ceil_log2(c_nof_statistics); - 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_xsq : NATURAL := g_nof_signal_inputs * g_nof_signal_inputs; + CONSTANT c_nof_statistics : NATURAL := g_nof_crosslets * c_xsq; + CONSTANT c_nof_stat_w : NATURAL := ceil_log2(c_nof_statistics); + 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, - adr_w => c_nof_word_w, - dat_w => c_word_w, - nof_dat => c_nof_word, - init_sl => '0'); -- MM side : sla_in, sla_out - CONSTANT c_stat_ram : t_c_mem := (latency => 1, - adr_w => c_nof_stat_w, - dat_w => c_stat_word_w, - nof_dat => c_nof_statistics, - init_sl => '0'); -- ST side : stat_mosi - + CONSTANT c_mm_ram : t_c_mem := (latency => 1, + adr_w => c_nof_word_w, + dat_w => c_word_w, + nof_dat => c_nof_word, + init_sl => '0'); -- MM side : sla_in, sla_out + CONSTANT c_stat_ram : t_c_mem := (latency => 1, + adr_w => c_nof_stat_w, + dat_w => c_stat_word_w, + nof_dat => c_nof_statistics, + init_sl => '0'); -- ST side : stat_mosi + SIGNAL pipe_in_a : t_dp_sosi; + SIGNAL pipe_in_b : t_dp_sosi; SIGNAL stat_data_re : STD_LOGIC_VECTOR(g_stat_data_w-1 DOWNTO 0); SIGNAL stat_data_im : STD_LOGIC_VECTOR(g_stat_data_w-1 DOWNTO 0); @@ -100,13 +100,42 @@ ARCHITECTURE str OF st_xsq IS SIGNAL wrdata_re : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); SIGNAL wrdata_im : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); - SIGNAL stat_mosi : t_mem_mosi; + SIGNAL stat_mosi : t_mem_mosi := c_mem_mosi_rst; - SIGNAL ram_st_xsq_mosi_arr : t_mem_mosi_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst); - SIGNAL ram_st_xsq_miso_arr : t_mem_miso_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_miso_rst); + SIGNAL ram_st_xsq_mosi_arr : t_mem_mosi_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst); + SIGNAL ram_st_xsq_miso_arr : t_mem_miso_arr(c_nof_complex-1 DOWNTO 0) := (OTHERS => c_mem_miso_rst); SIGNAL remapped_ram_st_xsq_mosi : t_mem_mosi; BEGIN + --------------------------------------------------------------- + -- pipeline inputs to increase latency with 1 in comparison to sync for st_calc + --------------------------------------------------------------- + u_dp_pipeline_a : ENTITY dp_lib.dp_pipeline + GENERIC MAP ( + g_pipeline => 1 + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + -- ST sink + snk_in => in_a, + -- ST source + src_out => pipe_in_a + ); + + u_dp_pipeline_b : ENTITY dp_lib.dp_pipeline + GENERIC MAP ( + g_pipeline => 1 + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + -- ST sink + snk_in => in_b, + -- ST source + src_out => pipe_in_b + ); + -- accumulators st_calc : ENTITY work.st_calc GENERIC MAP ( @@ -121,11 +150,11 @@ BEGIN PORT MAP ( rst => dp_rst, clk => dp_clk, - in_ar => in_a.re(g_in_data_w-1 DOWNTO 0), - in_ai => in_a.im(g_in_data_w-1 DOWNTO 0), - in_br => in_b.re(g_in_data_w-1 DOWNTO 0), - in_bi => in_b.im(g_in_data_w-1 DOWNTO 0), - in_val => in_a.valid, + in_ar => pipe_in_a.re(g_in_data_w-1 DOWNTO 0), + in_ai => pipe_in_a.im(g_in_data_w-1 DOWNTO 0), + in_br => pipe_in_b.re(g_in_data_w-1 DOWNTO 0), + in_bi => pipe_in_b.im(g_in_data_w-1 DOWNTO 0), + in_val => pipe_in_a.valid, in_sync => in_a.sync, out_adr => stat_mosi.address(c_stat_ram.adr_w-1 DOWNTO 0), out_re => stat_data_re, diff --git a/libraries/dsp/st/tb/vhdl/tb_st_xsq.vhd b/libraries/dsp/st/tb/vhdl/tb_st_xsq.vhd index 29b752acce..d189297983 100644 --- a/libraries/dsp/st/tb/vhdl/tb_st_xsq.vhd +++ b/libraries/dsp/st/tb/vhdl/tb_st_xsq.vhd @@ -50,48 +50,48 @@ USE work.st_pkg.ALL; ENTITY tb_st_xsq IS GENERIC( - g_nof_crosslets : NATURAL := 1; - g_nof_signal_inputs : NATURAL := 2; + g_nof_crosslets : NATURAL := 2; + g_nof_signal_inputs : NATURAL := 12; 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 + g_stat_data_w : NATURAL := 64; -- 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_block_per_sync : NATURAL := 5; + g_nof_clk_per_blk : NATURAL := 1024 ); 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_sim : BOOLEAN := TRUE; + CONSTANT c_rl : NATURAL := 1; + CONSTANT c_block_size : NATURAL := g_nof_crosslets * g_nof_signal_inputs; + CONSTANT c_random_data_w : NATURAL := 8; + CONSTANT c_xsq : NATURAL := g_nof_signal_inputs * g_nof_signal_inputs; CONSTANT c_nof_statistics : NATURAL := g_nof_crosslets * c_xsq; + CONSTANT c_gap_size : NATURAL := g_nof_clk_per_blk - c_nof_statistics; - 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_random_in_a_re : t_integer_arr(0 TO c_block_size-1) := common_math_create_random_arr(c_block_size, c_random_data_w, 100); + CONSTANT c_random_in_a_im : t_integer_arr(0 TO c_block_size-1) := common_math_create_random_arr(c_block_size, c_random_data_w, 101); + CONSTANT c_random_in_b_re : t_integer_arr(0 TO c_block_size-1) := common_math_create_random_arr(c_block_size, c_random_data_w, 102); + CONSTANT c_random_in_b_im : t_integer_arr(0 TO c_block_size-1) := common_math_create_random_arr(c_block_size, c_random_data_w, 103); - 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); + 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; + 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 tb_end : STD_LOGIC; + SIGNAL dp_pps : STD_LOGIC; - SIGNAL mm_rst : STD_LOGIC := '1'; - SIGNAL mm_clk : STD_LOGIC := '1'; + SIGNAL mm_rst : STD_LOGIC := '1'; + SIGNAL mm_clk : STD_LOGIC := '1'; - SIGNAL dp_rst : STD_LOGIC; - SIGNAL dp_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; @@ -124,7 +124,8 @@ 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); + proc_common_wait_some_cycles(dp_clk, g_nof_clk_per_blk); + proc_common_wait_some_cycles(dp_clk, 20); -- 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; @@ -143,12 +144,13 @@ BEGIN -- Run some sync intervals with DSP counter data for the real and imag fields WAIT UNTIL rising_edge(dp_clk); + proc_common_wait_some_cycles(dp_clk, 7); 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 + proc_dp_gen_block_data(c_rl, FALSE, g_in_data_w, g_in_data_w, 0, v_re, v_im, c_nof_statistics, 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 + proc_dp_gen_block_data(c_rl, FALSE, g_in_data_w, g_in_data_w, 0, v_re, v_im, c_nof_statistics, 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; @@ -170,14 +172,18 @@ BEGIN p_random_stimuli : PROCESS BEGIN - FOR I IN 0 TO g_nof_sync * g_nof_block_per_sync-1 LOOP + FOR S 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); + FOR N IN 0 TO g_nof_crosslets -1 LOOP + FOR I IN 0 TO g_nof_signal_inputs -1 LOOP + FOR J IN 0 TO g_nof_signal_inputs -1 LOOP + in_sosi_a.re <= TO_DP_DSP_DATA(c_random_in_a_re(N * g_nof_signal_inputs + I)); + in_sosi_a.im <= TO_DP_DSP_DATA(c_random_in_a_im(N * g_nof_signal_inputs + I)); + in_sosi_b.re <= TO_DP_DSP_DATA(c_random_in_b_re(N * g_nof_signal_inputs + J)); + in_sosi_b.im <= TO_DP_DSP_DATA(c_random_in_b_im(N * g_nof_signal_inputs + J)); + proc_common_wait_some_cycles(dp_clk, 1); + END LOOP; + END LOOP; END LOOP; END LOOP; WAIT; @@ -189,7 +195,7 @@ BEGIN 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); + proc_common_wait_some_cycles(mm_clk, 2* 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; diff --git a/libraries/dsp/st/tb/vhdl/tb_tb_st_xsq.vhd b/libraries/dsp/st/tb/vhdl/tb_tb_st_xsq.vhd new file mode 100644 index 0000000000..3c2bf4340e --- /dev/null +++ b/libraries/dsp/st/tb/vhdl/tb_tb_st_xsq.vhd @@ -0,0 +1,56 @@ +------------------------------------------------------------------------------- +-- +-- 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: Test multiple instances of tb_st_xsq +-- Usage: +-- > as 10 +-- > run -all +-- +-- Description: See tb_st_xsq + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; + +ENTITY tb_tb_st_xsq IS +END tb_tb_st_xsq; + +ARCHITECTURE tb OF tb_tb_st_xsq IS + + CONSTANT c_nof_sync : NATURAL := 3; + CONSTANT c_dsp_data_w : NATURAL := 16; + SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' + +BEGIN +-- GENERICS: +-- g_nof_crosslets : NATURAL := 2; +-- g_nof_signal_inputs : NATURAL := 12; +-- 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 := 5; +-- g_nof_clk_per_blk : NATURAL := 1024 + + u_sdp : ENTITY work.tb_st_xsq GENERIC MAP (1, 12, c_dsp_data_w, c_nof_sync, 64, 2, 5, 1024); + u_max : ENTITY work.tb_st_xsq GENERIC MAP (16, 8, c_dsp_data_w, c_nof_sync, 64, 2, 5, 1024); -- g_nof_crosslets * g_nof_signal_inputs**2 = 16 * 8 * 8 = 1024 = g_nof_clk_per_blk + +END tb; -- GitLab