From cf2dd8ee375bd1e7597e200212e2d788487569d0 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Thu, 22 Feb 2024 15:55:41 +0100
Subject: [PATCH] Add c_shiftram_latency and c_sdp_shiftram_latency to adjust
 WG phase for this.

---
 .../tb_disturb2_unb2b_sdp_station_full_wg.vhd |   2 +-
 .../tb_lofar2_unb2b_sdp_station_bf.vhd        |   2 +-
 .../tb_lofar2_unb2b_sdp_station_fsub.vhd      |   2 +-
 .../tb_lofar2_unb2c_sdp_station_bf.vhd        |   2 +-
 .../tb_lofar2_unb2c_sdp_station_bf_ring.vhd   |   2 +-
 .../tb_lofar2_unb2c_sdp_station_fsub.vhd      |   2 +-
 .../lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd |   6 +
 .../tb/vhdl/tb_sdp_beamformer_remote_ring.vhd | 165 ++++++++++++++++++
 libraries/base/common/src/vhdl/common_pkg.vhd |   2 +
 .../base/common/src/vhdl/common_shiftram.vhd  |   2 +
 10 files changed, 181 insertions(+), 6 deletions(-)
 create mode 100644 applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_remote_ring.vhd

diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/disturb2_unb2b_sdp_station_full_wg/tb_disturb2_unb2b_sdp_station_full_wg.vhd b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/disturb2_unb2b_sdp_station_full_wg/tb_disturb2_unb2b_sdp_station_full_wg.vhd
index 4a1080e760..b84d16cc0e 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/disturb2_unb2b_sdp_station_full_wg/tb_disturb2_unb2b_sdp_station_full_wg.vhd
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/disturb2_unb2b_sdp_station_full_wg/tb_disturb2_unb2b_sdp_station_full_wg.vhd
@@ -111,7 +111,7 @@ architecture tb of tb_disturb2_unb2b_sdp_station_full_wg is
   constant c_wg_ampl_sp_2         : natural := c_wg_ampl_sp_0 / 3;  -- use different ampl for sp_0 and sp_2 to distinghuis them
   -- . phase
   constant c_subband_phase        : real := 0.0;  -- wanted subband phase in degrees = WG phase at sop
-  constant c_wg_latency           : integer := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
+  constant c_wg_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
   constant c_subband_sp_0         : real := 102.0;  -- use WG at sp-0 for subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz
   constant c_subband_sp_2         : real :=  99.5;  -- use WG at sp-2 for subband at index 99.5 = 99.5/1024 * 200MHz = 19.43359375 MHz
   constant c_subband_freq_sp_0    : real := real(c_subband_sp_0) / real(c_sdp_N_fft);  -- normalized by fs = f_adc = 200 MHz = dp_clk rate
diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_bf/tb_lofar2_unb2b_sdp_station_bf.vhd b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_bf/tb_lofar2_unb2b_sdp_station_bf.vhd
index fc88e90a4a..3eb4663984 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_bf/tb_lofar2_unb2b_sdp_station_bf.vhd
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_bf/tb_lofar2_unb2b_sdp_station_bf.vhd
@@ -164,7 +164,7 @@ architecture tb of tb_lofar2_unb2b_sdp_station_bf is
   -- . phase
   constant c_subband_phase        : real := 0.0;  -- wanted subband phase in degrees = WG phase at sop
   constant c_subband_freq         : real := real(g_subband) / real(c_sdp_N_fft);  -- normalized by fs = f_adc = 200 MHz = dp_clk rate
-  constant c_wg_latency           : integer := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
+  constant c_wg_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
   constant c_wg_phase_offset      : real := 360.0 * real(c_wg_latency) * c_subband_freq;  -- c_diag_wg_latency is in dp_clk cycles
   constant c_wg_phase             : real := c_subband_phase + c_wg_phase_offset;  -- WG phase in degrees
 
diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd
index ae4d83d08e..01b7d1a62a 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd
@@ -119,7 +119,7 @@ architecture tb of tb_lofar2_unb2b_sdp_station_fsub is
   -- . phase
   constant c_subband_phase        : real := 0.0;  -- wanted subband phase in degrees = WG phase at sop
   constant c_subband_freq         : real := real(g_subband) / real(c_sdp_N_fft);  -- normalized by fs = f_adc = 200 MHz is dp_clk
-  constant c_wg_latency           : integer := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
+  constant c_wg_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
   constant c_wg_phase_offset      : real := 360.0 * real(c_wg_latency) * c_subband_freq;  -- c_diag_wg_latency is in dp_clk cycles
   constant c_wg_phase             : real := c_subband_phase + c_wg_phase_offset;  -- WG phase in degrees
 
diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd
index e1121127b6..5961e34066 100644
--- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd
+++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd
@@ -277,7 +277,7 @@ architecture tb of tb_lofar2_unb2c_sdp_station_bf is
   constant c_exp_sp_ast           : real := c_exp_sp_power * real(c_nof_clk_per_sync);
   -- . phase
   constant c_subband_freq         : real := real(g_subband) / real(c_sdp_N_fft);  -- normalized by fs = f_adc = 200 MHz = dp_clk rate
-  constant c_wg_latency           : integer := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
+  constant c_wg_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
   constant c_wg_phase_offset      : real := 360.0 * real(c_wg_latency) * c_subband_freq;  -- c_diag_wg_latency is in dp_clk cycles
   constant c_wg_phase             : real := g_sp_phase + c_wg_phase_offset;  -- WG phase in degrees
   constant c_wg_remnant_phase     : real := g_sp_remnant_phase + c_wg_phase_offset;  -- WG phase in degrees
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 18702afb27..3abd033083 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
@@ -277,7 +277,7 @@ architecture tb of tb_lofar2_unb2c_sdp_station_bf_ring is
   constant c_exp_sp_ast           : real := c_exp_sp_power * real(c_nof_clk_per_sync);
   -- . phase
   constant c_subband_freq         : real := real(g_subband) / real(c_sdp_N_fft);  -- normalized by fs = f_adc = 200 MHz = dp_clk rate
-  constant c_wg_latency           : integer := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
+  constant c_wg_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
   constant c_wg_phase_offset      : real := 360.0 * real(c_wg_latency) * c_subband_freq;  -- c_diag_wg_latency is in dp_clk cycles
   constant c_wg_phase             : real := g_sp_phase + c_wg_phase_offset;  -- WG phase in degrees
   constant c_wg_remnant_phase     : real := g_sp_remnant_phase + c_wg_phase_offset;  -- WG phase in degrees
diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub.vhd
index 7d739b0f82..cf06a7e713 100644
--- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub.vhd
+++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub.vhd
@@ -135,7 +135,7 @@ architecture tb of tb_lofar2_unb2c_sdp_station_fsub is
   constant c_subband_freq         : real := real(g_subband) / real(c_sdp_N_fft);  -- normalized by fs = f_adc = 200 MHz is dp_clk
   -- . phase
   constant c_subband_phase        : real := 0.0;  -- wanted subband phase in degrees = WG phase at sop
-  constant c_wg_latency           : integer := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
+  constant c_wg_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
   constant c_wg_phase_offset      : real := 360.0 * real(c_wg_latency) * c_subband_freq;  -- c_diag_wg_latency is in dp_clk cycles
   constant c_wg_phase             : real := c_subband_phase + c_wg_phase_offset;  -- WG phase in degrees
   constant c_co_wg_phase          : real := c_wg_phase;
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
index ee8b891623..aeef6fc98f 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
@@ -157,6 +157,12 @@ package sdp_pkg is
   -- c_sdp_nof_beamlets_per_longword * c_sdp_N_pol_bf * c_nof_complex = 2 * 2 * 2 = 8 octets
   subtype t_sdp_dual_pol_beamlet_in_longword is t_slv_8_arr(0 to 7);
 
+  -----------------------------------------------------------------------------
+  -- Signal input delay buffer (dp_shiftram)
+  -----------------------------------------------------------------------------
+  constant c_sdp_input_mux_latency : natural := 1;
+  constant c_sdp_shiftram_latency  : natural := c_shiftram_latency + c_sdp_input_mux_latency;
+
   -----------------------------------------------------------------------------
   -- PFB
   -----------------------------------------------------------------------------
diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_remote_ring.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_remote_ring.vhd
new file mode 100644
index 0000000000..421f449654
--- /dev/null
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_remote_ring.vhd
@@ -0,0 +1,165 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2023
+-- 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: E. Kooistra
+-- Purpose:
+-- . Test bench for multiple sdp_beamformer_output.vhd + ring_lane.vhd in a ring
+-- Description:
+-- . https://support.astron.nl/confluence/display/L2M/L5+SDPFW+Design+Document%3A+Beamformer
+--
+--   This tb is inspired by tb_lofar2_unb2c_sdp_station_bf_ring.vhd, however
+--   here the purpose is to simulate the memory usage of the circular buffer
+--   in the bsn_aligner_v2 at each node.
+--
+-- Usage:
+-- > as 8
+-- > run -a
+-------------------------------------------------------------------------------
+
+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;
+use common_lib.tb_common_pkg.all;
+use common_lib.tb_common_mem_pkg.all;
+use dp_lib.dp_stream_pkg.all;
+use work.sdp_pkg.all;
+use work.tb_sdp_pkg.all;
+
+entity tb_sdp_beamformer_remote_ring is
+  generic (
+    g_nof_rn             : natural := 16  -- number of nodes in the ring
+  );
+end tb_sdp_beamformer_remote_ring;
+
+architecture tb of tb_sdp_beamformer_remote_ring is
+  constant c_dp_clk_period : time := 5 ns;  -- 200 MHz
+  constant c_mm_clk_period : time := 1 ns;  -- fast MM clk to speed up simulation
+
+  constant c_last_rn             : natural := g_nof_rn - 1;  -- first ring node has index RN = 0 by definition.
+
+  signal mm_init      : std_logic := '1';
+  signal tb_end       : std_logic := '0';
+  signal dp_clk       : std_logic := '1';
+  signal dp_rst       : std_logic;
+  signal mm_clk       : std_logic := '1';
+  signal mm_rst       : std_logic;
+
+  signal rn_index     : natural range 0 to c_sdp_N_pn_max - 1 := 0;
+
+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;
+
+  mm_rst <= '1', '0' after c_mm_clk_period * 7;
+  mm_clk <= (not mm_clk) or tb_end after c_mm_clk_period / 2;
+
+  p_mm : process
+    variable v_offset : natural;
+  begin
+    proc_common_wait_until_low(dp_clk, mm_rst);
+    proc_common_wait_some_cycles(mm_clk, 10);
+
+    proc_common_wait_cross_clock_domain_latency(c_mm_clk_period, c_dp_clk_period, c_common_cross_clock_domain_latency * 2);
+    mm_init <= '0';
+    wait;
+  end process;
+
+
+  ------------------------------------------------------------------------------
+  -- DUT
+  ------------------------------------------------------------------------------
+  gen_dut : for RN in 0 to c_last_rn generate
+    -- Ring connections between nodes 0:c_last_rn,0
+    u_ring_lane_bf : entity ring_lib.ring_lane
+      generic map (
+        g_lane_direction            => 1,  -- transport in positive RN direction.
+        g_lane_data_w               => c_longword_w,
+        g_lane_packet_length        => c_lane_payload_nof_longwords_bf,
+        g_lane_total_nof_packets_w  => c_lane_total_nof_packets_w,
+        g_use_dp_layer              => true,
+        g_nof_rx_monitors           => 1,
+        g_nof_tx_monitors           => 1,
+        g_err_bi                    => c_err_bi,
+        g_nof_err_counts            => c_nof_err_counts,
+        g_bsn_at_sync_check_channel => c_bsn_at_sync_check_channel,
+        g_validate_channel          => c_validate_channel,
+        g_validate_channel_mode     => c_validate_channel_mode,
+        g_sync_timeout              => c_sync_timeout
+      )
+      port map (
+        mm_rst => mm_rst,
+        mm_clk => mm_clk,
+        dp_clk => dp_clk,
+        dp_rst => dp_rst,
+
+        from_lane_sosi     => bf_from_ri_sosi_arr(beamset_id),
+        to_lane_sosi       => bf_to_ri_sosi_arr(beamset_id),
+        lane_rx_cable_sosi => lane_rx_cable_sosi_arr(1 + beamset_id),
+        lane_rx_board_sosi => lane_rx_board_sosi_arr(1 + beamset_id),
+        lane_tx_cable_sosi => lane_tx_cable_sosi_arr(1 + beamset_id),
+        lane_tx_board_sosi => lane_tx_board_sosi_arr(1 + beamset_id),
+        bs_sosi            => bf_bs_sosi,  -- used for bsn and sync
+
+        reg_ring_lane_info_copi                => reg_ring_lane_info_bf_copi_arr(beamset_id),
+        reg_ring_lane_info_cipo                => reg_ring_lane_info_bf_cipo_arr(beamset_id),
+        reg_bsn_monitor_v2_ring_rx_copi        => reg_bsn_monitor_v2_ring_rx_bf_copi_arr(beamset_id),
+        reg_bsn_monitor_v2_ring_rx_cipo        => reg_bsn_monitor_v2_ring_rx_bf_cipo_arr(beamset_id),
+        reg_bsn_monitor_v2_ring_tx_copi        => reg_bsn_monitor_v2_ring_tx_bf_copi_arr(beamset_id),
+        reg_bsn_monitor_v2_ring_tx_cipo        => reg_bsn_monitor_v2_ring_tx_bf_cipo_arr(beamset_id),
+        reg_dp_block_validate_err_copi         => reg_dp_block_validate_err_bf_copi_arr(beamset_id),
+        reg_dp_block_validate_err_cipo         => reg_dp_block_validate_err_bf_cipo_arr(beamset_id),
+        reg_dp_block_validate_bsn_at_sync_copi => reg_dp_block_validate_bsn_at_sync_bf_copi_arr(beamset_id),
+        reg_dp_block_validate_bsn_at_sync_cipo => reg_dp_block_validate_bsn_at_sync_bf_cipo_arr(beamset_id),
+
+        this_rn   => this_rn,
+        N_rn      => ring_info.N_rn,
+        rx_select => ring_info.use_cable_to_previous_rn,
+        tx_select => ring_info.use_cable_to_next_rn
+      );
+
+    -- Intermediate BF alignment and summation at each node
+    u_sdp_beamformer_remote : entity work.sdp_beamformer_remote
+      port map (
+        dp_clk        => dp_clk,
+        dp_rst        => dp_rst,
+
+        rn_index      => rn_index,
+
+        local_bf_sosi : in  t_dp_sosi;
+        from_ri_sosi  : in  t_dp_sosi;
+        to_ri_sosi    : out t_dp_sosi;
+        bf_sum_sosi   : out t_dp_sosi;
+
+        mm_rst        : in  std_logic;
+        mm_clk        : in  std_logic;
+
+        reg_bsn_align_copi : in  t_mem_copi := c_mem_copi_rst;
+        reg_bsn_align_cipo : out t_mem_cipo;
+
+        reg_bsn_monitor_v2_bsn_align_input_copi  : in  t_mem_copi := c_mem_copi_rst;
+        reg_bsn_monitor_v2_bsn_align_input_cipo  : out t_mem_cipo;
+
+        reg_bsn_monitor_v2_bsn_align_output_copi : in  t_mem_copi := c_mem_copi_rst;
+        reg_bsn_monitor_v2_bsn_align_output_cipo : out t_mem_cipo
+      );
+end generate;  -- gen_dut
+
+end tb;
diff --git a/libraries/base/common/src/vhdl/common_pkg.vhd b/libraries/base/common/src/vhdl/common_pkg.vhd
index 9fdebec875..90462168da 100644
--- a/libraries/base/common/src/vhdl/common_pkg.vhd
+++ b/libraries/base/common/src/vhdl/common_pkg.vhd
@@ -95,6 +95,8 @@ package common_pkg is
 
   constant c_fifo_afull_margin    : natural := 4;  -- default or minimal FIFO almost full margin
 
+  constant c_shiftram_latency     : natural := 3;  -- minimal latency of common_shiftram when data_in_shift = 0
+
   -- DSP
   constant c_dsp_mult_w           : natural := 18;  -- Width of the embedded multipliers in Stratix IV (and Arria 10 for 2 multipliers per DSP block)
   constant c_dsp_mult_18_w        : natural := 18;  -- Width of the embedded multipliers in Stratix IV (and Arria 10 for 2 multipliers per DSP block)
diff --git a/libraries/base/common/src/vhdl/common_shiftram.vhd b/libraries/base/common/src/vhdl/common_shiftram.vhd
index 382a87a482..7770e46a34 100644
--- a/libraries/base/common/src/vhdl/common_shiftram.vhd
+++ b/libraries/base/common/src/vhdl/common_shiftram.vhd
@@ -30,6 +30,8 @@
 --   interpreted as the maximum value.
 -- . data_out_shift will always indicate the shift as applied to the
 --   corresponding data_out.
+-- . The common_shiftram has a latency of c_shiftram_latency = 3, so the
+--   actual shift is c_shiftram_latency + data_in_shift.
 --
 --
 --    Cycle 0              Cycle 1             Cycle 2           Cycle 3
-- 
GitLab