From e11fe282d2fa09350d23c35611187adc650b018f Mon Sep 17 00:00:00 2001
From: Reinier van der Walle <walle@astron.nl>
Date: Mon, 21 Mar 2022 16:46:50 +0100
Subject: [PATCH] made tb work for multiple nodes.

---
 .../tb_lofar2_unb2c_sdp_station_bf_ring.vhd   | 108 ++++++++++--------
 .../libraries/sdp/src/vhdl/sdp_station.vhd    |   5 +-
 2 files changed, 63 insertions(+), 50 deletions(-)

diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd
index d5aaeb438e..d1efebdef0 100644
--- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd
+++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd
@@ -167,7 +167,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS
   CONSTANT c_unb_nr              : NATURAL := 0; -- UniBoard 0
   CONSTANT c_node_nr             : NATURAL := 0;
   CONSTANT c_nof_rn              : NATURAL := 2;
-  CONSTANT c_gn_index            : NATURAL := c_unb_nr * 4 + c_node_nr;           -- this node GN
+  CONSTANT c_gn_index            : NATURAL := c_unb_nr * 4 + c_nof_rn-1; -- end node GN
   CONSTANT c_init_bsn            : NATURAL := 17;  -- some recognizable value >= 0
   CONSTANT c_nof_lanes           : NATURAL := c_sdp_N_beamsets;
 
@@ -175,8 +175,8 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS
   CONSTANT c_version             : STD_LOGIC_VECTOR(1 DOWNTO 0) := "00";
   CONSTANT c_fw_version          : t_unb2c_board_fw_version := (1, 0);
 
-  CONSTANT c_mac_15_0            : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(c_unb_nr, 8) & TO_UVEC(c_node_nr, 8);
-  CONSTANT c_ip_15_0             : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(c_unb_nr, 8) & TO_UVEC(c_node_nr+1, 8);  -- +1 to avoid IP = *.*.*.0
+  CONSTANT c_mac_15_0            : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(c_unb_nr + ((c_nof_rn-1) / c_quad), 8) & TO_UVEC((c_nof_rn-1) MOD c_quad, 8);
+  CONSTANT c_ip_15_0             : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(c_unb_nr + ((c_nof_rn-1) / c_quad), 8) & TO_UVEC(((c_nof_rn-1) MOD c_quad) +1, 8);  -- +1 to avoid IP = *.*.*.0
 
   CONSTANT c_eth_clk_period      : TIME := 8 ns;  -- 125 MHz XO on UniBoard
   CONSTANT c_ext_clk_period      : TIME := 5 ns;
@@ -209,7 +209,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS
   CONSTANT c_cep_ip_src_addr     : STD_LOGIC_VECTOR(31 DOWNTO 0) := c_sdp_cep_ip_src_addr_31_16 & c_ip_15_0;   -- C0A80001 = '192.168.0.1' = DOP36-eth0
   CONSTANT c_cep_udp_src_port    : STD_LOGIC_VECTOR(15 DOWNTO 0) := c_sdp_cep_udp_src_port_15_8 & c_id;  -- D0 & c_id
 
-  CONSTANT c_exp_ip_header_checksum : NATURAL := 16#5BDE#;  -- value obtained from rx_sdp_cep_header.ip.header_checksum in wave window
+  CONSTANT c_exp_ip_header_checksum : NATURAL := 16#5BDD#;  -- value obtained from rx_sdp_cep_header.ip.header_checksum in wave window for c_nof_rn = 2.
 
   CONSTANT c_exp_beamlet_scale   : NATURAL := NATURAL(g_beamlet_scale * REAL(c_sdp_unit_beamlet_scale));  -- c_sdp_unit_beamlet_scale = 2**15;
 
@@ -359,8 +359,8 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS
   CONSTANT c_mm_file_ram_equalizer_gains  : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_EQUALIZER_GAINS";
   CONSTANT c_mm_file_reg_dp_selector      : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_DP_SELECTOR";
   CONSTANT c_mm_file_ram_st_sst           : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ST_SST";
-  CONSTANT c_mm_file_ram_st_bst           : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ST_BST";
-  CONSTANT c_mm_file_reg_dp_xonoff        : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_DP_XONOFF";
+  CONSTANT c_mm_file_ram_st_bst           : STRING := mmf_unb_file_prefix(c_unb_nr + ((c_nof_rn-1) / c_quad), (c_nof_rn-1) MOD c_quad) & "RAM_ST_BST"; --end RN
+  CONSTANT c_mm_file_reg_dp_xonoff        : STRING := mmf_unb_file_prefix(c_unb_nr + ((c_nof_rn-1) / c_quad), (c_nof_rn-1) MOD c_quad) & "REG_DP_XONOFF"; --end RN
   CONSTANT c_mm_file_ram_ss_ss_wide       : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_SS_SS_WIDE";
   CONSTANT c_mm_file_ram_bf_weights       : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_BF_WEIGHTS";
   CONSTANT c_mm_file_reg_bf_scale         : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BF_SCALE";
@@ -622,7 +622,7 @@ BEGIN
     dp_rst              => dest_rst,
     dp_clk              => ext_clk,
 
-    serial_rx_arr(0)    => i_QSFP_1_lpbk(0)(0), -- Using RN 0 as end node.
+    serial_rx_arr(0)    => i_QSFP_1_lpbk(c_nof_rn-1)(0), -- Last RN must be used as end node.
 
     src_out_arr(0)      => tr_10GbE_src_out,
     src_in_arr(0)       => tr_10GbE_src_in
@@ -723,15 +723,20 @@ BEGIN
     --   0   block_period            : STD_LOGIC_VECTOR(15 DOWNTO 0);
     --     END RECORD;
     -- . Write
-    mmf_mm_bus_wr(c_mm_file_reg_sdp_info,  7, TO_UINT(c_exp_sdp_info.station_id), tb_clk);
-    mmf_mm_bus_wr(c_mm_file_reg_sdp_info,  6, TO_UINT(slv(c_exp_sdp_info.antenna_band_index)), tb_clk);
-    mmf_mm_bus_wr(c_mm_file_reg_sdp_info,  5, TO_UINT(c_exp_sdp_info.observation_id), tb_clk);
-    mmf_mm_bus_wr(c_mm_file_reg_sdp_info,  4, TO_UINT(c_exp_sdp_info.nyquist_zone_index), tb_clk);
-    mmf_mm_bus_wr(c_mm_file_reg_sdp_info,  1, TO_UINT(slv(c_exp_sdp_info.beam_repositioning_flag)), tb_clk);
-    -- . Read
-    mmf_mm_bus_rd(c_mm_file_reg_sdp_info,  3, rd_data, tb_clk); rd_sdp_info.f_adc <= rd_data(0);
-    mmf_mm_bus_rd(c_mm_file_reg_sdp_info,  2, rd_data, tb_clk); rd_sdp_info.fsub_type <= rd_data(0);
-    mmf_mm_bus_rd(c_mm_file_reg_sdp_info,  0, rd_data, tb_clk); rd_sdp_info.block_period <= rd_data(15 DOWNTO 0);
+
+
+    FOR RN IN 0 TO c_nof_rn-1 LOOP
+      mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO",  7, TO_UINT(c_exp_sdp_info.station_id), tb_clk);
+      mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO",  6, TO_UINT(slv(c_exp_sdp_info.antenna_band_index)), tb_clk);
+      mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO",  5, TO_UINT(c_exp_sdp_info.observation_id), tb_clk);
+      mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO",  4, TO_UINT(c_exp_sdp_info.nyquist_zone_index), tb_clk);
+      mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO",  1, TO_UINT(slv(c_exp_sdp_info.beam_repositioning_flag)), tb_clk);
+      -- . Read
+      mmf_mm_bus_rd(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO",  3, rd_data, tb_clk); rd_sdp_info.f_adc <= rd_data(0);
+      mmf_mm_bus_rd(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO",  2, rd_data, tb_clk); rd_sdp_info.fsub_type <= rd_data(0);
+      mmf_mm_bus_rd(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_SDP_INFO",  0, rd_data, tb_clk); rd_sdp_info.block_period <= rd_data(15 DOWNTO 0);
+    END LOOP;
+
     proc_common_wait_some_cycles(tb_clk, 1);
     -- . Verify read
     ASSERT c_exp_sdp_info.f_adc              = rd_sdp_info.f_adc REPORT "Wrong MM read SDP info f_adc" SEVERITY ERROR;
@@ -745,7 +750,9 @@ BEGIN
       -- MM beamlet_scale
       -- . write
       v_offset := bset * c_mm_span_reg_bf_scale;
-      mmf_mm_bus_wr(c_mm_file_reg_bf_scale, v_offset + 0, c_exp_beamlet_scale, tb_clk);
+      FOR RN IN 0 TO c_nof_rn-1 LOOP
+        mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_BF_SCALE", v_offset + 0, c_exp_beamlet_scale, tb_clk);
+      END LOOP;
       proc_common_wait_cross_clock_domain_latency(c_mm_clk_period, c_ext_clk_period);
 
       -- . readback
@@ -810,13 +817,14 @@ BEGIN
       mmf_mm_bus_rd(c_mm_file_reg_hdr_dat, v_offset + 25, rd_data, tb_clk); rd_cep_ip_dst_addr <= rd_data;
       mmf_mm_bus_rd(c_mm_file_reg_hdr_dat, v_offset + 23, rd_data, tb_clk); rd_cep_udp_dst_port <= rd_data(15 DOWNTO 0);
       proc_common_wait_some_cycles(tb_clk, 1);
+
       -- verify read
       ASSERT rd_cep_eth_dst_mac = c_sdp_cep_eth_dst_mac REPORT "Wrong MM read rd_cep_eth_dst_mac for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR;  -- 00074306C700 = DOP36-eth0
       ASSERT rd_cep_ip_dst_addr = c_sdp_cep_ip_dst_addr REPORT "Wrong MM read rd_cep_ip_dst_addr for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR;  -- C0A80001 = '192.168.0.1' = DOP36-eth0
       ASSERT rd_cep_udp_dst_port = c_sdp_cep_udp_dst_port REPORT "Wrong MM read rd_cep_udp_dst_port for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR;  -- 5000
 
       ----------------------------------------------------------------------------
-      -- Enable beamlet UDP offload (dp_xonoff)
+      -- Enable beamlet UDP offload off end node (dp_xonoff)
       ----------------------------------------------------------------------------
       v_offset := bset * c_mm_span_reg_dp_xonoff;
       mmf_mm_bus_wr(c_mm_file_reg_dp_xonoff, v_offset + 0, 1, tb_clk);
@@ -856,8 +864,8 @@ BEGIN
     -- Access scheme 1. Each RN uses and sends them along the ring.
     FOR RN IN 0 TO c_nof_rn-1 LOOP
       FOR I IN 0 TO c_nof_lanes-1 LOOP
-        IF RN = 0 THEN
-          -- Use RN 0 as end RN, so set transport_nof_hops to 0 for RN 0
+        IF RN = c_nof_rn-1 THEN
+          -- End RN, so set transport_nof_hops to 0.
           mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "REG_RING_LANE_INFO_BF", I*2+1, 0, tb_clk);
         ELSE
           -- Set transport_nof_hops to 1 on all nodes.
@@ -945,7 +953,9 @@ BEGIN
         FOR P IN 0 TO c_sdp_N_pol-1 LOOP
           v_addr := P + g_beamlet * c_sdp_N_pol + A * v_span + U * c_mm_span_ram_ss_ss_wide;
           v_sel := P + g_subband * c_sdp_N_pol;
-          mmf_mm_bus_wr(c_mm_file_ram_ss_ss_wide, v_addr, v_sel, tb_clk);
+          FOR RN IN 0 TO c_nof_rn-1 LOOP
+            mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "RAM_SS_SS_WIDE", v_addr, v_sel, tb_clk);
+          END LOOP;
         END LOOP;
       END LOOP;
     END LOOP;
@@ -974,34 +984,36 @@ BEGIN
 
     -- . write BF weights, only for g_beamlet to save sim time
     v_span := true_log_pow2(c_sdp_N_pol * c_sdp_S_sub_bf);  -- = 1024
-    FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP
-      -- Same BF weights for both beamsets
-      FOR PB IN 0 TO c_sdp_N_pol_bf-1 LOOP
-        -- Same BF weights for both beamlet polarizations
-        FOR A IN 0 TO c_sdp_A_pn-1 LOOP
-          FOR P IN 0 TO c_sdp_N_pol-1 LOOP
-            v_S := A * c_sdp_N_pol + P;
-            IF v_S = g_sp THEN
-              -- use generic BF weight for g_sp in g_beamlet
-              IF PB = 0 THEN
-                v_weight := pack_complex(re => c_bf_x_weight_re, im => c_bf_x_weight_im, w => c_sdp_W_bf_weight);
-              ELSE
-                v_weight := pack_complex(re => c_bf_y_weight_re, im => c_bf_y_weight_im, w => c_sdp_W_bf_weight);
-              END IF;
-            ELSE
-              -- use the remnant BF weights for the other SP
-              IF PB = 0 THEN
-                v_weight := pack_complex(re => c_bf_remnant_x_weight_re, im => c_bf_remnant_x_weight_im, w => c_sdp_W_bf_weight);
+    FOR RN IN 0 TO c_nof_rn-1 LOOP
+      FOR U IN 0 TO c_sdp_N_beamsets-1 LOOP
+        -- Same BF weights for both beamsets
+        FOR PB IN 0 TO c_sdp_N_pol_bf-1 LOOP
+          -- Same BF weights for both beamlet polarizations
+          FOR A IN 0 TO c_sdp_A_pn-1 LOOP
+            FOR P IN 0 TO c_sdp_N_pol-1 LOOP
+              v_S := RN * c_sdp_S_pn + A * c_sdp_N_pol + P;
+              IF v_S = g_sp THEN
+                -- use generic BF weight for g_sp in g_beamlet
+                IF PB = 0 THEN
+                  v_weight := pack_complex(re => c_bf_x_weight_re, im => c_bf_x_weight_im, w => c_sdp_W_bf_weight);
+                ELSE
+                  v_weight := pack_complex(re => c_bf_y_weight_re, im => c_bf_y_weight_im, w => c_sdp_W_bf_weight);
+                END IF;
               ELSE
-                v_weight := pack_complex(re => c_bf_remnant_y_weight_re, im => c_bf_remnant_y_weight_im, w => c_sdp_W_bf_weight);
+                -- use the remnant BF weights for the other SP
+                IF PB = 0 THEN
+                  v_weight := pack_complex(re => c_bf_remnant_x_weight_re, im => c_bf_remnant_x_weight_im, w => c_sdp_W_bf_weight);
+                ELSE
+                  v_weight := pack_complex(re => c_bf_remnant_y_weight_re, im => c_bf_remnant_y_weight_im, w => c_sdp_W_bf_weight);
+                END IF;
               END IF;
-            END IF;
-            v_addr := g_beamlet;                              -- beamlet index
-            v_addr := v_addr + P * c_sdp_S_sub_bf;            -- antenna input polarization address offset
-            v_addr := v_addr + A * v_span;                    -- antenna input address offset
-            v_addr := v_addr + PB * c_sdp_A_pn * v_span;      -- beamlet polarization address offset
-            v_addr := v_addr + U * c_mm_span_ram_bf_weights;  -- beamset address offset
-            mmf_mm_bus_wr(c_mm_file_ram_bf_weights, v_addr, v_weight, tb_clk);
+              v_addr := g_beamlet;                              -- beamlet index
+              v_addr := v_addr + P * c_sdp_S_sub_bf;            -- antenna input polarization address offset
+              v_addr := v_addr + A * v_span;                    -- antenna input address offset
+              v_addr := v_addr + PB * c_sdp_A_pn * v_span;      -- beamlet polarization address offset
+              v_addr := v_addr + U * c_mm_span_ram_bf_weights;  -- beamset address offset
+              mmf_mm_bus_wr(mmf_unb_file_prefix(c_unb_nr + (RN / c_quad), RN MOD c_quad) & "RAM_BF_WEIGHTS", v_addr, v_weight, tb_clk);
+            END LOOP;
           END LOOP;
         END LOOP;
       END LOOP;
@@ -1096,7 +1108,7 @@ BEGIN
     proc_common_wait_some_cycles(ext_clk, 100);  -- delay for ease of view in Wave window
  
     ---------------------------------------------------------------------------
-    -- Read beamlet statistics
+    -- Read beamlet statistics from end node
     ---------------------------------------------------------------------------
     -- . the beamlet statistics are c_stat_data_sz = 2 word power values.
     -- . there are c_sdp_S_sub_bf = 488 dual pol beamlets per beamset
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd
index 652c2b7f64..f8bcfb7bae 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd
@@ -383,7 +383,8 @@ ARCHITECTURE str OF sdp_station IS
   CONSTANT c_addr_w_reg_bsn_monitor_v2_rx_align_bf : NATURAL := ceil_log2(c_dual) + c_sdp_reg_bsn_monitor_v2_addr_w;
   CONSTANT c_addr_w_reg_bsn_monitor_v2_ring_rx_bf  : NATURAL := ceil_log2(c_sdp_N_pn_max) + c_sdp_reg_bsn_monitor_v2_addr_w;
   CONSTANT c_addr_w_reg_bsn_monitor_v2_ring_tx_bf  : NATURAL := ceil_log2(c_sdp_N_pn_max) + c_sdp_reg_bsn_monitor_v2_addr_w;
-
+  CONSTANT c_addr_w_reg_ring_lane_info_bf          : NATURAL := 1;
+ 
   -- Read only sdp_info values
   CONSTANT c_f_adc     : STD_LOGIC := '1'; -- '0' => 160M, '1' => 200M
   CONSTANT c_fsub_type : STD_LOGIC := '0'; -- '0' => critical sampled PFB, '1' => oversampled PFB
@@ -1172,7 +1173,7 @@ BEGIN
       u_mem_mux_reg_ring_lane_info_bf : ENTITY common_lib.common_mem_mux
       GENERIC MAP (
         g_nof_mosi    => c_sdp_N_beamsets,
-        g_mult_addr_w => c_sdp_reg_ring_lane_info_addr_w
+        g_mult_addr_w => c_addr_w_reg_ring_lane_info_bf
       )
       PORT MAP (
         mosi     => reg_ring_lane_info_bf_copi,
-- 
GitLab