From 656425661d40e30489f8830a96eace85e74870d2 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Tue, 12 Mar 2024 13:24:22 +0100
Subject: [PATCH] Add and use sdp_crosslets_remote_v2.vhd.

---
 applications/lofar2/libraries/sdp/hdllib.cfg  |   1 +
 .../sdp/src/vhdl/node_sdp_correlator.vhd      |   2 +-
 .../sdp/src/vhdl/sdp_crosslets_remote_v2.vhd  | 273 ++++++++++++++++++
 3 files changed, 275 insertions(+), 1 deletion(-)
 create mode 100644 applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_remote_v2.vhd

diff --git a/applications/lofar2/libraries/sdp/hdllib.cfg b/applications/lofar2/libraries/sdp/hdllib.cfg
index 73c93d93c0..8369aee4be 100644
--- a/applications/lofar2/libraries/sdp/hdllib.cfg
+++ b/applications/lofar2/libraries/sdp/hdllib.cfg
@@ -23,6 +23,7 @@ synth_files =
     src/vhdl/sdp_statistics_offload.vhd
     src/vhdl/sdp_crosslets_subband_select.vhd
     src/vhdl/sdp_crosslets_remote.vhd
+    src/vhdl/sdp_crosslets_remote_v2.vhd
     src/vhdl/node_sdp_adc_input_and_timing.vhd
     src/vhdl/node_sdp_filterbank.vhd
     src/vhdl/node_sdp_oversampled_filterbank.vhd
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd
index 9a1d0fe6f2..fa97a9f7d7 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd
@@ -181,7 +181,7 @@ begin
   ---------------------------------------------------------------
   -- Local and remote crosslets
   ---------------------------------------------------------------
-  u_sdp_crosslets_remote : entity work.sdp_crosslets_remote
+  u_sdp_crosslets_remote : entity work.sdp_crosslets_remote_v2
   generic map (
     g_P_sq => g_P_sq
   )
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_remote_v2.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_remote_v2.vhd
new file mode 100644
index 0000000000..2f283a3803
--- /dev/null
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_remote_v2.vhd
@@ -0,0 +1,273 @@
+-------------------------------------------------------------------------------
+--
+-- 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. van der Walle, E. Kooistra
+-- Purpose:
+-- . Implements the functionality for remote crosslets IO and aligning the
+--   local and remote crosslets in the node_sdp_correlator of the LOFAR2
+--   SDPFW design.
+-- Description:
+-- . Improvement compared to v1 is that in v2 the local crosslets are passed
+--   on directly to input 0 of the dp_bsn_align_v2, instead of via the
+--   ring_mux and dp_demux. In this way the block period of the reference
+--   input 0 remains constant and therefore also of crosslets_sosi.sop. This
+--   ensure that there is always constant, and thus enough, time to read the
+--   aligned output. via crosslets_copi.
+-------------------------------------------------------------------------------
+
+library IEEE, common_lib, dp_lib, reorder_lib, st_lib, mm_lib, ring_lib;
+use IEEE.std_logic_1164.all;
+use common_lib.common_pkg.all;
+use common_lib.common_mem_pkg.all;
+use common_lib.common_network_layers_pkg.all;
+use dp_lib.dp_stream_pkg.all;
+use ring_lib.ring_pkg.all;
+use work.sdp_pkg.all;
+
+entity sdp_crosslets_remote_v2 is
+  generic (
+    g_P_sq             : natural := c_sdp_P_sq
+  );
+  port (
+    dp_clk             : in  std_logic;
+    dp_rst             : in  std_logic;
+
+    xsel_sosi          : in  t_dp_sosi;
+    from_ri_sosi       : in  t_dp_sosi := c_dp_sosi_rst;
+    to_ri_sosi         : out t_dp_sosi;
+
+    crosslets_sosi     : out t_dp_sosi;
+    crosslets_copi     : in  t_mem_copi := c_mem_copi_rst;
+    crosslets_cipo_arr : out t_mem_cipo_arr(g_P_sq - 1 downto 0);
+
+    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 sdp_crosslets_remote_v2;
+
+architecture str of sdp_crosslets_remote_v2 is
+  constant c_block_size           : natural := c_sdp_N_crosslets_max * c_sdp_S_pn;
+  constant c_block_size_longwords : natural := ceil_div(c_block_size, 2);  -- 32b -> 64b
+  constant c_data_w               : natural := c_sdp_W_crosslet * c_nof_complex;
+  -- The channel field carries the index of time multiplexed crosslet packets
+  constant c_use_channel          : boolean := true;
+  constant c_channel_w            : natural := ceil_log2(g_P_sq);
+  -- With 32b data repacked in 64b one empty bit is enough. For crosslets the number
+  -- of 32b words is c_block_size is even, so empty will be 0 always. However do
+  -- support odd sizes, to be save.
+  constant c_use_empty            : boolean := true;
+  constant c_empty_w              : natural := 1;
+  -- The from_ri_sosi only carries correct packets, so error field is not used.
+  constant c_use_error            : boolean := false;
+
+  -- The size for 1 block is probably already enough as the number of blocks received
+  -- on the remote input of the mux probably have enough gap time in between. Just
+  -- to be sure to not run into issues in the future, the fifo size is increased to
+  -- buffer the maximum nof blocks per block period.
+  constant c_mux_fifo_size   : natural  := 2**ceil_log2(g_P_sq * c_block_size_longwords);
+  -- c_repack_fifo_size should be at least c_block_size_longwords / 2, as dp_repack_data
+  -- unpacks by factor 2 from 64bit to 32bit. Choose 1x to have some room.
+  constant c_repack_fifo_size  : natural  := 2**ceil_log2(1 * c_block_size_longwords);
+
+  signal xsel_data_sosi                : t_dp_sosi := c_dp_sosi_rst;
+  signal local_sosi                    : t_dp_sosi := c_dp_sosi_rst;
+  signal ring_mux_sosi                 : t_dp_sosi := c_dp_sosi_rst;
+  signal ring_mux_siso                 : t_dp_siso := c_dp_siso_rdy;
+  signal repack_fifo_sosi              : t_dp_sosi := c_dp_sosi_rst;
+  signal repack_fifo_siso              : t_dp_siso := c_dp_siso_rdy;
+  signal rx_sosi                       : t_dp_sosi := c_dp_sosi_rst;
+  signal dispatch_invert_sosi_arr      : t_dp_sosi_arr(0 to g_P_sq - 1) := (others => c_dp_sosi_rst);
+  signal dispatch_sosi_arr             : t_dp_sosi_arr(g_P_sq - 1 downto 0) := (others => c_dp_sosi_rst);
+  signal to_aligner_sosi_arr           : t_dp_sosi_arr(g_P_sq - 1 downto 0) := (others => c_dp_sosi_rst);
+begin
+  ---------------------------------------------------------------
+  -- Repack 32b to 64b
+  ---------------------------------------------------------------
+  -- repacking xsel re/im to data field.
+  p_wire_xsel_sosi : process(xsel_sosi)
+  begin
+    xsel_data_sosi <= xsel_sosi;
+    xsel_data_sosi.data(                c_sdp_W_crosslet - 1 downto 0)                <= xsel_sosi.re(c_sdp_W_crosslet - 1 downto 0);
+    xsel_data_sosi.data(c_nof_complex * c_sdp_W_crosslet - 1 downto c_sdp_W_crosslet) <= xsel_sosi.im(c_sdp_W_crosslet - 1 downto 0);
+  end process;
+
+  u_dp_repack_data_local : entity dp_lib.dp_repack_data
+  generic map (
+    g_in_dat_w       => c_data_w,
+    g_in_nof_words   => c_longword_w / c_data_w,
+    g_out_dat_w      => c_longword_w,
+    g_out_nof_words  => 1,
+    g_pipeline_ready => true  -- Needed for src_in.ready to snk_out.ready.
+  )
+  port map (
+    rst => dp_rst,
+    clk => dp_clk,
+
+    snk_in  => xsel_data_sosi,
+    src_out => local_sosi
+  );
+
+  ---------------------------------------------------------------
+  -- ring_mux
+  ---------------------------------------------------------------
+  u_ring_mux : entity ring_lib.ring_mux
+  generic map (
+    g_bsn_w        => c_dp_stream_bsn_w,
+    g_data_w       => c_longword_w,
+    g_channel_w    => c_word_w,
+    g_use_error    => c_use_error,
+    g_fifo_size    => array_init(c_mux_fifo_size, 2)
+  )
+  port map (
+    dp_clk => dp_clk,
+    dp_rst => dp_rst,
+
+    remote_sosi => from_ri_sosi,
+    local_sosi  => local_sosi,
+    mux_sosi    => ring_mux_sosi,
+    mux_siso    => ring_mux_siso
+  );
+
+  to_ri_sosi <= ring_mux_sosi;
+
+  ---------------------------------------------------------------
+  -- Repack 64b to 32b
+  ---------------------------------------------------------------
+  -- FIFO to take backpressure from u_dp_repack_data_rx
+  u_dp_fifo_sc : entity dp_lib.dp_fifo_sc
+  generic map (
+    g_data_w         => c_longword_w,
+    g_bsn_w          => c_dp_stream_bsn_w,
+    g_empty_w        => c_empty_w,
+    g_channel_w      => c_channel_w,
+    g_use_bsn        => true,
+    g_use_empty      => c_use_empty,
+    g_use_channel    => c_use_channel,
+    g_use_error      => c_use_error,
+    g_use_sync       => true,
+    g_fifo_size      => c_repack_fifo_size
+  )
+  port map (
+    rst         => dp_rst,
+    clk         => dp_clk,
+
+    snk_out     => open,
+    snk_in      => from_ri_sosi,
+
+    src_in      => repack_fifo_siso,
+    src_out     => repack_fifo_sosi
+  );
+
+  u_dp_repack_data_rx : entity dp_lib.dp_repack_data
+  generic map (
+    g_in_dat_w       => c_longword_w,
+    g_in_nof_words   => 1,
+    g_out_dat_w      => c_data_w,
+    g_out_nof_words  => c_longword_w / c_data_w,
+    g_pipeline_ready => true  -- Needed for src_in.ready to snk_out.ready.
+  )
+  port map (
+    rst => dp_rst,
+    clk => dp_clk,
+
+    snk_in  => repack_fifo_sosi,
+    snk_out => repack_fifo_siso,
+    src_out => rx_sosi
+  );
+
+  ---------------------------------------------------------------
+  -- dp_demux
+  ---------------------------------------------------------------
+  u_dp_demux : entity dp_lib.dp_demux
+  generic map (
+    g_mode              => 0,
+    g_nof_output        => g_P_sq,
+    g_remove_channel_lo => false,
+    g_sel_ctrl_invert   => true  -- TRUE when indexed (g_nof_input-1 DOWNTO 0)
+  )
+  port map (
+    rst => dp_rst,
+    clk => dp_clk,
+
+    snk_in      => rx_sosi,
+    src_out_arr => dispatch_invert_sosi_arr
+  );
+
+  dispatch_sosi_arr <= func_dp_stream_arr_reverse_range(dispatch_invert_sosi_arr);
+
+  -- Group local input stream with and remote input streams
+  to_aligner_sosi_arr(g_P_sq - 1 downto 1) <= dispatch_sosi_arr(g_P_sq - 1 downto 1);
+  to_aligner_sosi_arr(0) <= xsel_data_sosi;
+
+  ---------------------------------------------------------------
+  -- dp_bsn_aligner_v2
+  ---------------------------------------------------------------
+  u_mmp_dp_bsn_align_v2 : entity dp_lib.mmp_dp_bsn_align_v2
+  generic map(
+    -- for dp_bsn_align_v2
+    g_nof_streams             => g_P_sq,
+    g_bsn_latency_max         => 2,
+    g_nof_aligners_max        => 1,  -- 1 for Access scheme 3.
+    g_block_size              => c_block_size,
+    g_data_w                  => c_data_w,
+    g_use_mm_output           => true,
+    g_rd_latency              => 1,  -- Required for st_xst
+    -- for mms_dp_bsn_monitor_v2
+    -- Using c_sdp_N_clk_sync_timeout_xsub as g_nof_clk_per_sync is used for BSN monitor timeout.
+    g_nof_clk_per_sync        => c_sdp_N_clk_sync_timeout_xsub,
+    g_nof_input_bsn_monitors  => g_P_sq,
+    g_use_bsn_output_monitor  => true
+    )
+  port map (
+    -- Memory-mapped clock domain
+    mm_rst                  => mm_rst,
+    mm_clk                  => mm_clk,
+
+    reg_bsn_align_copi      => reg_bsn_align_copi,
+    reg_bsn_align_cipo      => reg_bsn_align_cipo,
+
+    reg_input_monitor_copi  => reg_bsn_monitor_v2_bsn_align_input_copi,
+    reg_input_monitor_cipo  => reg_bsn_monitor_v2_bsn_align_input_cipo,
+
+    reg_output_monitor_copi => reg_bsn_monitor_v2_bsn_align_output_copi,
+    reg_output_monitor_cipo => reg_bsn_monitor_v2_bsn_align_output_cipo,
+
+    -- Streaming clock domain
+    dp_rst     => dp_rst,
+    dp_clk     => dp_clk,
+
+    -- Streaming input
+    in_sosi_arr => to_aligner_sosi_arr,
+
+    -- Output via local MM interface in dp_clk domain, when g_use_mm_output = TRUE.
+    mm_sosi     => crosslets_sosi,
+    mm_copi     => crosslets_copi,
+    mm_cipo_arr => crosslets_cipo_arr
+  );
+end str;
-- 
GitLab