From f5e119f6ec8eec7afa85dfa04075f0d3d8c49c0c Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Wed, 4 Oct 2023 13:06:17 +0200
Subject: [PATCH] Verify beamlets data for multiple destinations.

---
 .../sdp/tb/vhdl/tb_sdp_beamformer_output.vhd  | 181 +++++++++++++-----
 1 file changed, 131 insertions(+), 50 deletions(-)

diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_output.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_output.vhd
index 8516ea9ef8..c70d84b4f7 100644
--- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_output.vhd
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_output.vhd
@@ -29,7 +29,7 @@
 -- > run -a
 -------------------------------------------------------------------------------
 
-library IEEE, common_lib, dp_lib;
+library IEEE, common_lib, dp_lib, reorder_lib;
 use IEEE.std_logic_1164.all;
 use common_lib.common_pkg.all;
 use common_lib.common_mem_pkg.all;
@@ -37,6 +37,7 @@ use common_lib.tb_common_pkg.all;
 use common_lib.tb_common_mem_pkg.all;
 use common_lib.common_network_layers_pkg.all;
 use dp_lib.dp_stream_pkg.all;
+use reorder_lib.reorder_pkg.all;
 use work.sdp_pkg.all;
 use work.sdp_bdo_pkg.all;
 use work.tb_sdp_pkg.all;
@@ -75,12 +76,16 @@ architecture tb of tb_sdp_beamformer_output is
                                                                  func_sdp_gn_index_to_ip_15_0(c_gn_id);
   constant c_cep_udp_src_port : std_logic_vector(15 downto 0) := c_sdp_cep_udp_src_port_15_8 & c_id;
 
-  constant c_reorder_nof_blocks_arr : t_natural_arr(1 to g_nof_destinations_max) :=
+  constant c_mdi_reorder_nof_blocks_arr : t_natural_arr(1 to g_nof_destinations_max) :=
              func_sdp_bdo_reorder_nof_blocks_look_up_table(g_nof_destinations_max);
+  constant c_mdi_nof_blocks_per_packet : natural := c_mdi_reorder_nof_blocks_arr(g_nof_destinations);
 
-  constant c_nof_beamlets_per_block_first_destinations_arr : t_natural_arr(1 to g_nof_destinations_max) :=
+  constant c_mdi_nof_beamlets_per_block_first_destinations_arr : t_natural_arr(1 to g_nof_destinations_max) :=
              func_sdp_bdo_nof_beamlets_per_block_first_destinations_look_up_table(g_nof_destinations_max);
-  constant c_nof_beamlets_per_block : natural := c_nof_beamlets_per_block_first_destinations_arr(g_nof_destinations);
+  constant c_mdi_nof_beamlets_per_block_per_destination : natural :=
+             c_mdi_nof_beamlets_per_block_first_destinations_arr(g_nof_destinations);
+
+  constant c_mdi_nof_beamlets_all_destinations : natural := c_mdi_nof_blocks_per_packet * c_sdp_S_sub_bf;
 
   -- Checksum value obtained from rx_sdp_cep_header.ip.header_checksum in wave window
   constant c_exp_ip_header_checksum  : natural := 16#5BDB#;
@@ -128,23 +133,26 @@ architecture tb of tb_sdp_beamformer_output is
   signal rx_hdr_fields_raw   : std_logic_vector(1023 downto 0) := (others => '0');
   signal rx_beamlet_header   : t_sdp_cep_header;
 
-  signal exp_beamlet_header         : t_sdp_cep_header;
-  signal exp_beamlet_index          : natural;
-  signal exp_nof_blocks_per_packet  : natural;
-  signal exp_nof_beamlets_per_block : natural;
-  signal exp_dp_bsn                 : natural;
+  signal exp_beamlet_header             : t_sdp_cep_header;
+  signal exp_dp_bsn                     : natural;
+
+  signal mdi_exp_beamlet_header         : t_sdp_cep_header;
+  signal mdi_exp_beamlet_index          : natural;
+  signal mdi_exp_nof_beamlets_per_block : natural;
+  signal mdi_exp_dp_bsn                 : natural;
 
   signal rx_offload_sosi     : t_dp_sosi := c_dp_sosi_rst;
+  signal rx_offload_data     : std_logic_vector(c_longword_w - 1 downto 0);  -- 64 bit
   signal rx_offload_sop_cnt  : natural := 0;
   signal rx_DI               : natural := 0;
 
   -- rx merge
-  signal rx_merge_sosi                  : t_dp_sosi := c_dp_sosi_rst;
+  signal rx_merge_sosi       : t_dp_sosi := c_dp_sosi_rst;
   signal rx_merge_sop_cnt    : natural := 0;
 
   -- Beamlets packets data
-  signal rx_beamlet_data     : std_logic_vector(c_longword_w - 1 downto 0);  -- 64 bit
   signal rx_beamlet_sosi     : t_dp_sosi := c_dp_sosi_rst;
+  signal rx_beamlet_data     : std_logic_vector(c_longword_w - 1 downto 0);  -- 64 bit
 
   -- [0 : 3] =  X, Y, X, Y
   signal rx_beamlet_arr_re   : t_sdp_beamlet_part_arr;
@@ -152,16 +160,23 @@ architecture tb of tb_sdp_beamformer_output is
   signal rx_beamlet_cnt      : natural;
   signal rx_beamlet_valid    : std_logic;
 
-  -- [0 : 4 * 488 * 2 - 1] = [0 : 3903]
-  signal rx_packet_list_re    : t_sdp_beamlet_packet_list;
-  signal rx_packet_list_im    : t_sdp_beamlet_packet_list;
-  signal rx_beamlet_list_re   : t_sdp_beamlet_packet_list;
-  signal rx_beamlet_list_im   : t_sdp_beamlet_packet_list;
-  signal rx_beamlet_list_val  : std_logic := '0';
+  -- g_nof_destinations = 1: [0 : 4 * 488 * 2 - 1] = [0 : 3903]
+  signal rx_packet_list_re   : t_sdp_beamlet_packet_list;
+  signal rx_packet_list_im   : t_sdp_beamlet_packet_list;
+  signal rx_beamlet_list_re  : t_sdp_beamlet_packet_list;
+  signal rx_beamlet_list_im  : t_sdp_beamlet_packet_list;
+  signal rx_beamlet_list_val : std_logic := '0';
+  -- g_nof_destinations > 1: [0 : N * 488 * 2 - 1], where N = c_mdi_nof_blocks_per_packet
+  signal rx_mdi_packet_list_re   : t_slv_8_arr(0 to c_mdi_nof_beamlets_all_destinations * c_sdp_N_pol_bf - 1);
+  signal rx_mdi_packet_list_im   : t_slv_8_arr(0 to c_mdi_nof_beamlets_all_destinations * c_sdp_N_pol_bf - 1);
+  signal rx_mdi_beamlet_list_re  : t_slv_8_arr(0 to c_mdi_nof_beamlets_all_destinations * c_sdp_N_pol_bf - 1);
+  signal rx_mdi_beamlet_list_im  : t_slv_8_arr(0 to c_mdi_nof_beamlets_all_destinations * c_sdp_N_pol_bf - 1);
+  signal rx_mdi_beamlet_list_val : std_logic := '0';
+
   -- Use +c_beamlet_mod to ensure >= 0 to fit in natural, use mod c_beamlet_mod
   -- to fit count in c_sdp_W_beamlet bits
-  signal prev_re              : natural := (c_init_re - 1 + c_beamlet_mod) mod c_beamlet_mod;
-  signal prev_im              : natural := (c_init_im - 1 + c_beamlet_mod) mod c_beamlet_mod;
+  signal prev_re             : natural := (c_init_re - 1 + c_beamlet_mod) mod c_beamlet_mod;
+  signal prev_im             : natural := (c_init_im - 1 + c_beamlet_mod) mod c_beamlet_mod;
 begin
   dp_rst <= '1', '0' after c_dp_clk_period * 7;
   dp_clk <= (not dp_clk) or tb_end after c_dp_clk_period / 2;
@@ -343,18 +358,6 @@ begin
   -- Destination index (DI)
   rx_DI <= rx_offload_sop_cnt mod g_nof_destinations;
 
-  -- Prepare exp_beamlet_header before rx_offload_sosi.eop, so that
-  -- p_verify_beamlet_header can verify it at rx_offload_sosi.eop.
-  exp_beamlet_header <= func_sdp_compose_cep_header(c_exp_ip_header_checksum,
-                                                    c_exp_sdp_info,
-                                                    c_gn_id,
-                                                    c_exp_payload_error,
-                                                    c_exp_beamlet_scale,
-                                                    exp_beamlet_index,
-                                                    exp_nof_blocks_per_packet,
-                                                    exp_nof_beamlets_per_block,
-                                                    exp_dp_bsn);
-
   rx_beamlet_header <= func_sdp_map_cep_header(rx_hdr_fields_raw);
 
   gen_verify_one_destination : if g_nof_destinations_max = 1 generate
@@ -363,13 +366,21 @@ begin
     rx_beamlet_sosi <= rx_offload_sosi;
 
     ---------------------------------------------------------------------------
-    -- Verify beamlet header
+    -- Verify one destination: beamlet header
     ---------------------------------------------------------------------------
-    exp_beamlet_index <= c_exp_beamlet_index;
-    exp_nof_blocks_per_packet <= c_sdp_cep_nof_blocks_per_packet;
-    exp_nof_beamlets_per_block <= c_sdp_cep_nof_beamlets_per_block;
-
-    p_verify_beamlet_header : process
+    -- Prepare exp_beamlet_header before rx_offload_sosi.eop, so that
+    -- p_verify_beamlet_header can verify it at rx_offload_sosi.eop.
+    exp_beamlet_header <= func_sdp_compose_cep_header(c_exp_ip_header_checksum,
+                                                      c_exp_sdp_info,
+                                                      c_gn_id,
+                                                      c_exp_payload_error,
+                                                      c_exp_beamlet_scale,
+                                                      c_exp_beamlet_index,
+                                                      c_sdp_cep_nof_blocks_per_packet,
+                                                      c_sdp_cep_nof_beamlets_per_block,
+                                                      exp_dp_bsn);
+
+    p_verify_one_beamlet_header : process
       variable v_bool    : boolean;
     begin
       wait until rising_edge(dp_clk);
@@ -386,7 +397,7 @@ begin
     end process;
 
     -----------------------------------------------------------------------------
-    -- Verify beamlet data
+    -- Verify one destination: beamlet data
     -----------------------------------------------------------------------------
     -- To view the 64 bit 10GbE offload data more easily in the Wave window
     rx_beamlet_data <= rx_beamlet_sosi.data(c_longword_w - 1 downto 0);
@@ -400,7 +411,7 @@ begin
                                rx_packet_list_re,
                                rx_packet_list_im);
 
-    p_verify_rx_beamlet_list : process
+    p_verify_one_rx_beamlet_list : process
       -- Nof complex (= nof re = nof im = c_N) values in t_sdp_beamlet_packet_list
       constant c_N : natural := c_sdp_cep_nof_beamlets_per_packet * c_sdp_N_pol_bf;
       variable v_re : natural;
@@ -464,11 +475,21 @@ begin
       );
 
     ---------------------------------------------------------------------------
-    -- Verify beamlet header
+    -- Verify multiple destinations: beamlet header
     ---------------------------------------------------------------------------
-    exp_nof_blocks_per_packet <= c_reorder_nof_blocks_arr(g_nof_destinations_max);
-
-    p_verify_beamlet_header : process
+    -- Prepare mdi_exp_beamlet_header before rx_offload_sosi.eop, so that
+    -- p_verify_beamlet_header can verify it at rx_offload_sosi.eop.
+    mdi_exp_beamlet_header <= func_sdp_compose_cep_header(c_exp_ip_header_checksum,
+                                                          c_exp_sdp_info,
+                                                          c_gn_id,
+                                                          c_exp_payload_error,
+                                                          c_exp_beamlet_scale,
+                                                          mdi_exp_beamlet_index,
+                                                          c_mdi_nof_blocks_per_packet,
+                                                          mdi_exp_nof_beamlets_per_block,
+                                                          mdi_exp_dp_bsn);
+
+    p_verify_multi_beamlet_header : process
       variable v_nof_beamlets   : natural;
       variable v_bool           : boolean;
     begin
@@ -476,26 +497,86 @@ begin
       -- Prepare exp_sdp_cep_header, so that it can be verified at rx_offload_sosi.eop
       if rx_offload_sosi.sop = '1' then
         -- Default expect nof_beamlets_per_block for first destinations
-        exp_nof_beamlets_per_block <= c_nof_beamlets_per_block;
+        mdi_exp_nof_beamlets_per_block <= c_mdi_nof_beamlets_per_block_per_destination;
         if rx_DI = g_nof_destinations - 1 then
           -- Remaining nof_beamlets_per_block for last destination
-          exp_nof_beamlets_per_block <= c_sdp_S_sub_bf - rx_DI * exp_nof_beamlets_per_block;
+          mdi_exp_nof_beamlets_per_block <= c_sdp_S_sub_bf - rx_DI * mdi_exp_nof_beamlets_per_block;
         end if;
 
-        -- Expected beamlet index increments by c_nof_beamlets_per_block per destination index
-        exp_beamlet_index <= rx_DI * c_nof_beamlets_per_block;
+        -- Expected beamlet index increments by c_mdi_nof_beamlets_per_block_per_destination per destination index
+        mdi_exp_beamlet_index <= rx_DI * c_mdi_nof_beamlets_per_block_per_destination;
       end if;
 
       if rx_merge_sosi.sop = '1' then
-        -- Expected BSN increments by exp_nof_blocks_per_packet, after every merged packet
-        exp_dp_bsn <= c_init_bsn + rx_merge_sop_cnt * exp_nof_blocks_per_packet;
+        -- Expected BSN increments by c_mdi_nof_blocks_per_packet, after every merged packet,
+        -- because packets for all g_nof_destinations have same BSN.
+        mdi_exp_dp_bsn <= c_init_bsn + rx_merge_sop_cnt * c_mdi_nof_blocks_per_packet;
       end if;
 
       -- Verify header at eop
       if rx_offload_sosi.eop = '1' then
-        v_bool := func_sdp_verify_cep_header(rx_beamlet_header, exp_beamlet_header);
+        v_bool := func_sdp_verify_cep_header(rx_beamlet_header, mdi_exp_beamlet_header);
       end if;
     end process;
 
+    ---------------------------------------------------------------------------
+    -- Verify multiple destinations: beamlet data
+    ---------------------------------------------------------------------------
+    -- Wires
+    rx_beamlet_sosi <= rx_merge_sosi;
+
+    -- To view the 64 bit 10GbE offload data more easily in the Wave window
+    rx_offload_data <= rx_offload_sosi.data(c_longword_w - 1 downto 0);
+    rx_beamlet_data <= rx_beamlet_sosi.data(c_longword_w - 1 downto 0);
+
+    proc_sdp_rx_beamlet_octets(c_mdi_nof_blocks_per_packet,
+                               dp_clk,
+                               rx_beamlet_sosi,
+                               rx_beamlet_cnt,
+                               rx_beamlet_valid,
+                               rx_beamlet_arr_re,
+                               rx_beamlet_arr_im,
+                               rx_mdi_packet_list_re,
+                               rx_mdi_packet_list_im);
+
+    p_verify_multi_rx_beamlet_list : process
+      -- Nof complex (= nof re = nof im = c_N) values in packet_list
+      constant c_N : natural := c_mdi_nof_beamlets_all_destinations * c_sdp_N_pol_bf;
+      variable v_re : natural;
+      variable v_im : natural;
+    begin
+      -- Wait until end of a beamlet packet
+      -- . use at least one wait statement in process to avoid Modelsim warning: (vcom-1090)
+      wait until rising_edge(dp_clk);
+      proc_common_wait_until_hi_lo(dp_clk, rx_beamlet_sosi.eop);
+      -- Undo the beamlet output transpose, to have original beamlet order
+      rx_mdi_beamlet_list_re <= func_reorder_transpose_packet(c_sdp_S_sub_bf,
+                                                              c_mdi_nof_blocks_per_packet,
+                                                              c_sdp_N_pol_bf,
+                                                              rx_mdi_packet_list_re);
+      rx_mdi_beamlet_list_im <= func_reorder_transpose_packet(c_sdp_S_sub_bf,
+                                                              c_mdi_nof_blocks_per_packet,
+                                                              c_sdp_N_pol_bf,
+                                                              rx_mdi_packet_list_im);
+      rx_mdi_beamlet_list_val <= '1';
+
+      -- Wait until rx_beamlet_list is valid
+      wait until rising_edge(dp_clk);
+      rx_mdi_beamlet_list_val <= '0';
+      -- Verify rx_beamlet_list
+      -- . get last values from previous block
+      v_re := prev_re;
+      v_im := prev_im;
+      for vI in 0 to c_N - 1 loop
+        -- Verify incrementing beamlets
+        v_re := (v_re + 1) mod c_beamlet_mod;
+        v_im := (v_im + 1) mod c_beamlet_mod;
+        assert to_uint(rx_mdi_beamlet_list_re(vI)) = v_re report "Wrong mdi re_beamlet." severity error;
+        assert to_uint(rx_mdi_beamlet_list_im(vI)) = v_im report "Wrong mdi im_beamlet." severity error;
+      end loop;
+      -- . hold last values for next block
+      prev_re <= v_re;
+      prev_im <= v_im;
+    end process;
   end generate;
 end tb;
-- 
GitLab