From 54b53f8a0fe8c51794eaf7a1f3713d74cdaec902 Mon Sep 17 00:00:00 2001
From: Reinier van der Walle <walle@astron.nl>
Date: Thu, 17 Sep 2020 09:46:23 +0200
Subject: [PATCH] Initial commit of tb_lofar2_unb2b_filterbank

---
 .../tb/vhdl/tb_lofar2_unb2b_filterbank.vhd    | 196 +++++++++++++-----
 1 file changed, 146 insertions(+), 50 deletions(-)

diff --git a/applications/lofar2/designs/lofar2_unb2b_filterbank/tb/vhdl/tb_lofar2_unb2b_filterbank.vhd b/applications/lofar2/designs/lofar2_unb2b_filterbank/tb/vhdl/tb_lofar2_unb2b_filterbank.vhd
index 31b4150fdf..f322629c59 100644
--- a/applications/lofar2/designs/lofar2_unb2b_filterbank/tb/vhdl/tb_lofar2_unb2b_filterbank.vhd
+++ b/applications/lofar2/designs/lofar2_unb2b_filterbank/tb/vhdl/tb_lofar2_unb2b_filterbank.vhd
@@ -27,7 +27,7 @@
 --   MM control actions:
 --
 --   1) Enable calc mode for WG via reg_diag_wg with:
---        freq = 20MHz
+--        freq = 19.921875MHz
 --        ampl = 0.5 * 2**13
 --   
 --   2) Read current BSN from reg_bsn_scheduler_wg and write reg_bsn_scheduler_wg 
@@ -37,8 +37,12 @@
 --      analogue view in Wave window:
 --   
 --   4) Read ADUH monitor power sum for via reg_aduh_mon and verify with 
---      c_exp_wg_power_sp.
+--      c_exp_wg_power_sp_0.
 --      View sp_power_sum in Wave window
+--   5) Read subband statistics (SST) via ram_st_sst and verify with 
+--      c_exp_subband_power_sp_0 at c_subband_sp_0.
+--      View sp_subband_power_0  in Wave window
+--   
 --
 -- Usage:
 --   > as 7    # default
@@ -46,9 +50,10 @@
 --   > run -a  
 --
 -------------------------------------------------------------------------------
-LIBRARY IEEE, common_lib, unb2b_board_lib, i2c_lib, mm_lib, dp_lib, diag_lib;
+LIBRARY IEEE, common_lib, unb2b_board_lib, i2c_lib, mm_lib, dp_lib, diag_lib, lofar2_sdp_lib, wpfb_lib;
 USE IEEE.std_logic_1164.ALL;
 USE IEEE.numeric_std.ALL;
+USE IEEE.MATH_REAL.ALL;
 USE common_lib.common_pkg.ALL;
 USE unb2b_board_lib.unb2b_board_pkg.ALL;
 USE common_lib.tb_common_pkg.ALL;
@@ -57,6 +62,8 @@ USE mm_lib.mm_file_pkg.ALL;
 USE dp_lib.dp_stream_pkg.ALL;
 USE mm_lib.mm_file_unb_pkg.ALL;
 USE diag_lib.diag_pkg.ALL;
+USE wpfb_lib.wpfb_pkg.ALL;
+USE lofar2_sdp_lib.sdp_pkg.ALL;
 
 ENTITY tb_lofar2_unb2b_filterbank IS
 END tb_lofar2_unb2b_filterbank;
@@ -76,43 +83,53 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_filterbank IS
   CONSTANT c_pps_period          : NATURAL := 1000;
 
   CONSTANT c_tb_clk_period       : TIME := 100 ps; -- use fast tb_clk to speed up M&C
-  CONSTANT c_cable_delay         : TIME := 12 ns
-;
+  CONSTANT c_cable_delay         : TIME := 12 ns;
+
   CONSTANT c_sample_freq         : NATURAL := c_unb2b_board_ext_clk_freq_200M/10**6;  -- 200 MSps
   CONSTANT c_sample_period       : TIME := (10**6 / c_sample_freq) * 1 ps; 
 
-  CONSTANT c_nof_sync            : NATURAL := 5;
   CONSTANT c_nof_block_per_sync  : NATURAL := 16; 
- 
+  CONSTANT c_wpfb_sim            : t_wpfb := func_wpfb_set_nof_block_per_sync(c_sdp_wpfb_subbands, c_nof_block_per_sync);
+   
   CONSTANT c_percentage          : REAL := 0.05;  -- percentage that actual value may differ from expected value
   CONSTANT c_lo_factor           : REAL := 1.0 - c_percentage;  -- lower boundary  
   CONSTANT c_hi_factor           : REAL := 1.0 + c_percentage;  -- higher boundary
 
-  CONSTANT c_nof_points          : NATURAL := 1024; 
-  CONSTANT c_nof_taps            : NATURAL := 16; 
-  
-  CONSTANT c_subband_period      : TIME := c_nof_points * c_sample_period;
+  CONSTANT c_subband_period      : TIME := c_sdp_N_fft * c_sample_period;
 
   -- WG
   CONSTANT c_full_scale_ampl      : REAL := REAL(2**(18-1)-1);  -- = full scale of WG
   CONSTANT c_bsn_start_wg         : NATURAL := 2;  -- start WG at this BSN to instead of some BSN, to avoid mismatches in exact expected data values
-  CONSTANT c_ampl_sp              : NATURAL := 2**(14-1)/2;  -- in number of lsb
-  CONSTANT c_subband_sp           : REAL := 51.2;  -- Select subband at index 512/10 = 51.2 = 20 MHz
-  CONSTANT c_wg_subband_freq_unit : REAL := c_diag_wg_freq_unit/512.0;  -- subband freq = Fs/512 = 200 MSps/512 = 390625 Hz sinus
+  CONSTANT c_ampl_sp_0              : NATURAL := 2**(14-1)/2;  -- in number of lsb
+  CONSTANT c_wg_subband_freq_unit : REAL := c_diag_wg_freq_unit/REAL(c_sdp_N_fft);  -- subband freq = Fs/1024 = 200 MSps/1024 = 195312.5 Hz sinus
+  CONSTANT c_wg_freq_offset       : REAL := 0.0/11.0; -- in freq_unit
+  CONSTANT c_subband_sp_0           : REAL := 102.0;  -- Select subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz 
   CONSTANT c_wg_ampl_lsb          : REAL := c_diag_wg_ampl_unit / c_full_scale_ampl;  -- amplitude in number of LSbit resolution steps
-  CONSTANT c_exp_wg_power_sp      : REAL := REAL(c_ampl_sp**2)/2.0 * REAL(c_nof_points*c_nof_block_per_sync);
-   
+  CONSTANT c_exp_wg_power_sp_0      : REAL := REAL(c_ampl_sp_0**2)/2.0 * REAL(c_sdp_N_fft*c_nof_block_per_sync);
+
+  -- WPFB
+  CONSTANT c_nof_pfb                        : NATURAL := 1; -- Verifying 1 of c_sdp_P_pfb = 6 pfb to speed up simulation.
+  CONSTANT c_wb_leakage_bin                 : NATURAL := c_wpfb_sim.nof_points / c_wpfb_sim.wb_factor;   -- = 256, leakage will occur in this bin if FIR wb_factor is reversed 
+  CONSTANT c_exp_sp_subband_power_ratio     : REAL := 1.0/8.0;   -- depends on internal WPFB quantization and FIR coefficients
+  CONSTANT c_exp_sp_subband_power_sum_ratio : REAL := c_exp_sp_subband_power_ratio;   -- because all sinus power is expected in one subband
+  CONSTANT c_exp_subband_power_sp_0         : REAL := c_exp_wg_power_sp_0 * c_exp_sp_subband_power_ratio;
+  CONSTANT c_measured_subband_power_sp_0    : REAL :=  17016589184.0;  -- obtained from Wave window
+
+  TYPE t_real_arr IS ARRAY (INTEGER RANGE <>) OF REAL; 
+  TyPE t_slv_64_subbands_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_sub);
+
   -- ADUH
-  CONSTANT c_mon_buffer_nof_samples  : NATURAL := 1024; --samples per stream 
-  CONSTANT c_mon_buffer_nof_words    : NATURAL := c_mon_buffer_nof_samples; 
+  CONSTANT c_mon_buffer_nof_samples : NATURAL := 512; --samples per stream 
+  CONSTANT c_mon_buffer_nof_words   : NATURAL := c_mon_buffer_nof_samples; 
   
   -- MM  
-  CONSTANT c_mm_file_reg_ppsh               : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "PIO_PPS";
-  CONSTANT c_mm_file_reg_bsn_source         : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE";
-  CONSTANT c_mm_file_reg_bsn_scheduler_wg   : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SCHEDULER";
-  CONSTANT c_mm_file_reg_diag_wg            : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_WG";
-  CONSTANT c_mm_file_reg_aduh_mon           : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_ADUH_MONITOR";
-  CONSTANT c_mm_file_ram_aduh_mon           : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ADUH_MONITOR";
+  CONSTANT c_mm_file_reg_ppsh             : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "PIO_PPS";
+  CONSTANT c_mm_file_reg_bsn_source       : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE";
+  CONSTANT c_mm_file_reg_bsn_scheduler_wg : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SCHEDULER";
+  CONSTANT c_mm_file_reg_diag_wg          : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_WG";
+  CONSTANT c_mm_file_reg_aduh_mon         : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_ADUH_MONITOR";
+  CONSTANT c_mm_file_ram_aduh_mon         : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ADUH_MONITOR";
+  CONSTANT c_mm_file_ram_st_sst           : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ST_SST";
 
 
   -- Tb
@@ -122,12 +139,21 @@ ARCHITECTURE tb OF tb_lofar2_unb2b_filterbank IS
   SIGNAL rd_data             : STD_LOGIC_VECTOR(c_32-1 DOWNTO 0);
 
   -- WG
-  SIGNAL dbg_c_exp_wg_power_sp : REAL := c_exp_wg_power_sp;
-  SIGNAL sp_samples            : t_integer_arr(0 TO c_mon_buffer_nof_samples-1) := (OTHERS=>0); 
-  SIGNAL sp_sample             : INTEGER := 0;
-  SIGNAL sp_power_sum          : UNSIGNED(63 DOWNTO 0);
-  SIGNAL current_bsn_wg        : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
-
+  SIGNAL dbg_c_exp_wg_power_sp_0 : REAL := c_exp_wg_power_sp_0;
+  SIGNAL sp_samples              : t_integer_arr(0 TO c_mon_buffer_nof_samples-1) := (OTHERS=>0); 
+  SIGNAL sp_sample               : INTEGER := 0;
+  SIGNAL sp_power_sum            : STD_LOGIC_VECTOR(63 DOWNTO 0);
+  SIGNAL current_bsn_wg          : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
+
+  -- WPFB
+  SIGNAL sp_subband_powers_arr2         : t_slv_64_subbands_arr(c_nof_pfb*c_nof_complex-1 DOWNTO 0);   -- [sp][sub]
+  SIGNAL sp_subband_power_0             : REAL;
+  SIGNAL sp_subband_power_sum           : t_real_arr(c_nof_pfb*c_nof_complex-1 DOWNTO 0) := (OTHERS=>0.0);
+  SIGNAL sp_subband_power_sum_0         : REAL;
+  SIGNAL sp_subband_power_ratio_0       : REAL;
+  SIGNAL sp_subband_power_sum_ratio_0   : REAL;
+  SIGNAL sp_subband_power_leakage_sum_0 : REAL;
+  
   -- DUT
   SIGNAL ext_clk             : STD_LOGIC := '0';
   SIGNAL pps                 : STD_LOGIC := '0';
@@ -184,11 +210,13 @@ BEGIN
   ------------------------------------------------------------------------------
   u_lofar_unb2b_filterbank : ENTITY work.lofar2_unb2b_filterbank
   GENERIC MAP (
-    g_design_name => "lofar2_unb2b_filterbank_full",
-    g_design_note => "Lofar2 adc full",
-    g_sim         => c_sim,
-    g_sim_unb_nr  => c_unb_nr,
-    g_sim_node_nr => c_node_nr
+    g_design_name            => "lofar2_unb2b_filterbank_full",
+    g_design_note            => "Lofar2 adc full",
+    g_sim                    => c_sim,
+    g_sim_unb_nr             => c_unb_nr,
+    g_sim_node_nr            => c_node_nr,
+    g_wpfb                   => c_wpfb_sim,
+    g_scope_selected_subband => NATURAL(c_subband_sp_0)
   )
   PORT MAP (
     -- GENERAL
@@ -220,8 +248,8 @@ BEGIN
     QSFP_LED     => open,
 
     -- back transceivers
-    JESD204B_SERIAL_DATA       => JESD204B_SERIAL_DATA,
-    JESD204B_REFCLK  => JESD204B_REFCLK,
+    JESD204B_SERIAL_DATA => JESD204B_SERIAL_DATA,
+    JESD204B_REFCLK      => JESD204B_REFCLK,
   
     -- jesd204b syncronization signals
     JESD204B_SYSREF => jesd204b_sysref,
@@ -235,7 +263,9 @@ BEGIN
   
   p_mm_stimuli : PROCESS
     VARIABLE v_bsn                   : NATURAL;
-    VARIABLE v_sp_power_sum          : REAL;
+    VARIABLE v_sp_power_sum_0          : REAL;
+    VARIABLE v_sp_subband_power      : REAL;
+    VARIABLE v_W, v_T, v_U, v_S, v_B : NATURAL;  -- array indicies
   BEGIN
     -- Wait for DUT power up after reset
     WAIT FOR 1 us;
@@ -260,9 +290,9 @@ BEGIN
     --   3 : ampl[16:0]
     mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 0, 1024*2**16 + 1, tb_clk);  -- nof_samples, mode calc
     mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 1, INTEGER(  0.0 * c_diag_wg_phase_unit), tb_clk);  -- phase offset in degrees
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 2, INTEGER(c_subband_sp * c_wg_subband_freq_unit), tb_clk);  -- freq
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 3, INTEGER(REAL(c_ampl_sp) * c_wg_ampl_lsb), tb_clk);  -- ampl
-    
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 2, INTEGER((c_subband_sp_0+c_wg_freq_offset) * c_wg_subband_freq_unit), tb_clk);  -- freq
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 3, INTEGER(REAL(c_ampl_sp_0) * c_wg_ampl_lsb), tb_clk);  -- ampl
+
     -- Read current BSN
     mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 0, current_bsn_wg(31 DOWNTO  0), tb_clk);
     mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 1, current_bsn_wg(63 DOWNTO 32), tb_clk);
@@ -276,7 +306,7 @@ BEGIN
     mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 1,     0, tb_clk);  -- assume v_bsn < 2**31-1
     
     -- Wait for ADUH monitor to have filled with WG data
-    WAIT FOR c_subband_period*c_nof_taps;
+    WAIT FOR c_subband_period*c_sdp_N_taps;
     WAIT FOR c_subband_period*2;
 
     ----------------------------------------------------------------------------
@@ -313,19 +343,85 @@ BEGIN
     
     -- Read ADUH monitor power sum 
     mmf_mm_bus_rd(c_mm_file_reg_aduh_mon, 2, rd_data, tb_clk);  -- read low part
-    sp_power_sum(31 DOWNTO 0) <= UNSIGNED(rd_data);
+    sp_power_sum(31 DOWNTO 0) <= rd_data;
     mmf_mm_bus_rd(c_mm_file_reg_aduh_mon, 3, rd_data, tb_clk);  -- read high part
-    sp_power_sum(63 DOWNTO 32) <= UNSIGNED(rd_data);
+    sp_power_sum(63 DOWNTO 32) <= rd_data;
     proc_common_wait_some_cycles(tb_clk, 1);
 
     ---------------------------------------------------------------------------
-    -- Verification 
+    -- Verify sp_power_sum 
+    ---------------------------------------------------------------------------
+
+    -- Convert STD_LOGIC_VECTOR sp_power_sum to REAL
+    v_sp_power_sum_0 := REAL(REAL(TO_UINT(sp_power_sum(61 DOWNTO 30)))*REAL(2**30) + REAL(TO_UINT(sp_power_sum(29 DOWNTO 0)))); 
+
+    ASSERT v_sp_power_sum_0 > c_lo_factor * c_exp_wg_power_sp_0 REPORT "Wrong SP power for SP 0" SEVERITY ERROR;
+    ASSERT v_sp_power_sum_0 < c_hi_factor * c_exp_wg_power_sp_0 REPORT "Wrong SP power for SP 0" SEVERITY ERROR;
+     
+    ---------------------------------------------------------------------------
+    -- Read subband statistics
     ---------------------------------------------------------------------------
-    -- Convert UNSIGNED sp_power_sum to REAL
-    v_sp_power_sum := REAL(REAL(TO_INTEGER(sp_power_sum(61 DOWNTO 30)))*REAL(2**30) + REAL(TO_INTEGER(sp_power_sum(29 DOWNTO 0)))); 
+    -- . the subband statistics are c_wpfb_sim.stat_data_sz = 2 word power values.
+    -- . there are c_sdp_N_sub = 512 subbands per signal path
+    -- . one complex WPFB can process two real inputs A, B
+    -- . the subbands are output alternately so A0 B0 A1 B1 ... A511 B511 for input A, B
+    -- . the subband statistics multiple WPFB units appear in order in the ram_st_sst address map
+    -- . the subband statistics are stored first lo word 0 then hi word 1
+    
+    FOR I IN 0 TO c_nof_pfb*c_nof_complex*c_sdp_N_sub*c_wpfb_sim.stat_data_sz-1 LOOP
+      v_W := I MOD c_wpfb_sim.stat_data_sz;
+      v_T := (I / c_wpfb_sim.stat_data_sz) MOD c_nof_complex;
+      v_U := I / (c_nof_complex*c_wpfb_sim.stat_data_sz*c_sdp_N_sub);
+      v_S := v_T + v_U * c_nof_complex;
+      v_B := (I / (c_nof_complex*c_wpfb_sim.stat_data_sz)) MOD c_sdp_N_sub;
+      IF v_W=0 THEN
+        -- low part
+        mmf_mm_bus_rd(c_mm_file_ram_st_sst, I, rd_data, tb_clk);
+        sp_subband_powers_arr2(v_S)(v_B)(31 DOWNTO 0) <= rd_data;
+      ELSE      
+        -- high part
+        mmf_mm_bus_rd(c_mm_file_ram_st_sst, I, rd_data, tb_clk);
+        sp_subband_powers_arr2(v_S)(v_B)(63 DOWNTO 32) <= rd_data;
+
+        -- Convert STD_LOGIC_VECTOR to REAL
+        v_sp_subband_power := REAL(TO_UINT(rd_data(29 DOWNTO 0) & 
+            sp_subband_powers_arr2(v_S)(v_B)(31 DOWNTO 30)))*2.0**30 + 
+            REAL(TO_UINT(sp_subband_powers_arr2(v_S)(v_B)(29 DOWNTO 0)));
+        -- sum
+        sp_subband_power_sum(v_S) <= sp_subband_power_sum(v_S) + v_sp_subband_power;
+      END IF;
+    END LOOP;
 
-    ASSERT v_sp_power_sum > c_lo_factor * c_exp_wg_power_sp REPORT "Wrong SP power for SP 0" SEVERITY ERROR;
-    ASSERT v_sp_power_sum < c_hi_factor * c_exp_wg_power_sp REPORT "Wrong SP power for SP 0" SEVERITY ERROR;
+    -- sp_subband_power_sum is the sum of all subband powers per SP, this value will be close to sp_subband_power
+    -- because the input is a sinus, so most power will be in 1 subband. The sp_subband_power_leakage_sum shows
+    -- how much power from the input sinus at a specific subband has leaked into the 511 other subbands.
+    sp_subband_power_0 <= REAL(TO_UINT(sp_subband_powers_arr2(0)(INTEGER(ROUND(c_subband_sp_0)))(61 DOWNTO 30)))*2.0**30 + 
+        REAL(TO_UINT(sp_subband_powers_arr2(0)(INTEGER(ROUND(c_subband_sp_0)))(29 DOWNTO 0)));
+
+    sp_subband_power_sum_0 <= sp_subband_power_sum(0);
+    
+    proc_common_wait_some_cycles(tb_clk, 1);
+
+    ---------------------------------------------------------------------------
+    -- Verify subband statistics
+    ---------------------------------------------------------------------------  
+    -- verify expected subband power based on WG power
+    IF v_sp_power_sum_0>0.0 THEN ASSERT sp_subband_power_0 > c_lo_factor * c_exp_subband_power_sp_0 REPORT "Wrong subband power for SP 0" SEVERITY ERROR; END IF;
+    IF v_sp_power_sum_0>0.0 THEN ASSERT sp_subband_power_0 < c_hi_factor * c_exp_subband_power_sp_0 REPORT "Wrong subband power for SP 0" SEVERITY ERROR; END IF;
+    
+    -- verify expected subband power based on earlier simulation of exactly measurement of subband power
+    ASSERT sp_subband_power_0 = c_measured_subband_power_sp_0 REPORT "Wrong exact subband power for SP 0" SEVERITY ERROR;
+    
+    -- view c_exp_sp_subband_power_ratio in Wave window
+    IF v_sp_power_sum_0>0.0 THEN sp_subband_power_ratio_0 <= sp_subband_power_0/v_sp_power_sum_0; END IF;
+    
+    -- view c_exp_sp_subband_power_sum_ratio in Wave window
+    -- The sp_subband_power_sum_ratio show similar information as sp_subband_power_leakage_sum, because when
+    -- sp_subband_power_leakage_sum is small then sp_subband_power_sum_ratio ~= sp_subband_power_ratio.
+    IF v_sp_power_sum_0>0.0 THEN sp_subband_power_sum_ratio_0 <= sp_subband_power_sum_0/v_sp_power_sum_0; END IF;
+
+    -- View sp_subband_power_leakage_sum in Wave window
+    IF v_sp_power_sum_0>0.0 THEN sp_subband_power_leakage_sum_0 <= sp_subband_power_sum_0 - sp_subband_power_0; END IF;
 
     ---------------------------------------------------------------------------
     -- End Simulation 
@@ -335,5 +431,5 @@ BEGIN
     proc_common_stop_simulation(TRUE, ext_clk, sim_done, tb_end);
     WAIT;
   END PROCESS;
-  
+
 END tb;
-- 
GitLab