From 0bfd2e0038545b949d12bcd3057a917418ec8398 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Mon, 18 Sep 2023 15:10:24 +0200
Subject: [PATCH] Use fixed nof_blocks_per_packet_act dependent on
 nof_destinations_act.

---
 .../lofar2/libraries/sdp/sdp.peripheral.yaml  | 12 +++----
 .../sdp/src/vhdl/sdp_bdo_destinations_reg.vhd | 35 ++++++++++---------
 2 files changed, 25 insertions(+), 22 deletions(-)

diff --git a/applications/lofar2/libraries/sdp/sdp.peripheral.yaml b/applications/lofar2/libraries/sdp/sdp.peripheral.yaml
index a01fbaaeba..4be6a8fa76 100644
--- a/applications/lofar2/libraries/sdp/sdp.peripheral.yaml
+++ b/applications/lofar2/libraries/sdp/sdp.peripheral.yaml
@@ -204,17 +204,17 @@ peripherals:
         mm_port_description: |
           "The SDP beamlets in a beamset can be send to 1 or multiple destinations, each identified
            by destination MAC addess, IP address and UDP port.
-           The number of destinations is 1 <= nof_destinations <= N_destinations_max.
-           The number of blocks per packet is nof_blocks_per_packet <= N_reorder_blocks_max / nof_destinations.
-           The actual nof_blocks_per_packet and nof_destinations is reported via the corresponding _act fields."
+           The number of destinations is 1 <= nof_destinations <= N_destinations_max. The actual
+           nof_destinations is reported via nof_destinations_act.
+           The actual number of blocks per packet depends on nof_destinations_act, and is reported
+           via nof_blocks_per_packet_act."
         fields:
           - - { field_name: eth_destination_mac,    number_of_fields: N_destinations_max, mm_width: 32, user_width: 48, radix: uint64, access_mode: RW, address_offset: 0x0 }
           - - { field_name: ip_destination_address, number_of_fields: N_destinations_max, mm_width: 32,                                access_mode: RW, address_offset: 0x80 }
           - - { field_name: udp_destination_port,   number_of_fields: N_destinations_max, mm_width: 16,                                access_mode: RW, address_offset: 0xC0 }
           - - { field_name: nof_destinations,          mm_width: 8, access_mode: RW, address_offset: 0x100 }
-          - - { field_name: nof_destinations_act,      mm_width: 8, access_mode: RW, address_offset: 0x104 }
-          - - { field_name: nof_blocks_per_packet,     mm_width: 8, access_mode: RW, address_offset: 0x108 }
-          - - { field_name: nof_blocks_per_packet_act, mm_width: 8, access_mode: RW, address_offset: 0x10C }
+          - - { field_name: nof_destinations_act,      mm_width: 8, access_mode: RO, address_offset: 0x104 }
+          - - { field_name: nof_blocks_per_packet_act, mm_width: 8, access_mode: RO, address_offset: 0x108 }
 
 
   - peripheral_name: sdp_beamformer_output_hdr_dat  #  pi_dp_offload_tx_hdr_dat_lofar2_beamformer_output.py
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_destinations_reg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_destinations_reg.vhd
index e049c553ec..69315721ce 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_destinations_reg.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_destinations_reg.vhd
@@ -33,7 +33,7 @@
 --                           -----------------> output value
 --
 -- where:
--- . _ro = parsed_nof_destinations, parsed_nof_blocks_per_packet
+-- . _ro = actual nof_destinations, actual nof_blocks_per_packet
 -- . output value = sdp_bdo_destinations
 --
 -- References:
@@ -47,6 +47,7 @@ library IEEE, common_lib, mm_lib;
   use common_lib.common_mem_pkg.all;
   use common_lib.common_field_pkg.all;
   use work.sdp_pkg.all;
+  use work.sdp_bdo_pkg.all;
 
 entity sdp_bdo_destinations_reg is
   port (
@@ -68,7 +69,6 @@ end sdp_bdo_destinations_reg;
 architecture str of sdp_bdo_destinations_reg is
   constant c_field_arr : t_common_field_arr(c_sdp_bdo_destinations_info_nof_hdr_fields - 1 downto 0) :=
     ( (field_name_pad("nof_blocks_per_packet_act"), "RO",  8, field_default(c_sdp_cep_nof_blocks_per_packet)),
-      (field_name_pad("nof_blocks_per_packet"),     "RW",  8, field_default(c_sdp_cep_nof_blocks_per_packet)),
       (field_name_pad("nof_destinations_act"),      "RO",  8, field_default(1)),
       (field_name_pad("nof_destinations"),          "RW",  8, field_default(1)),
 
@@ -129,21 +129,21 @@ architecture str of sdp_bdo_destinations_reg is
   signal sdp_bdo_destinations_rd : t_sdp_bdo_destinations_info;
   signal sdp_bdo_destinations_wr : t_sdp_bdo_destinations_info;
 
-  signal parsed_nof_destinations      : natural;
-  signal parsed_nof_blocks_per_packet : natural;
+  signal nof_destinations_act      : natural := 1;
+  signal nof_blocks_per_packet_act : natural := c_sdp_cep_nof_blocks_per_packet;
 begin
   sdp_bdo_destinations <= sdp_bdo_destinations_rd;
 
   p_sdp_bdo_destinations_rd : process(sdp_bdo_destinations_wr,
-                                      parsed_nof_destinations,
-                                      parsed_nof_blocks_per_packet)
+                                      nof_destinations_act,
+                                      nof_blocks_per_packet_act)
   begin
     -- default write assign all fields
     sdp_bdo_destinations_rd <= sdp_bdo_destinations_wr;
 
     -- overrule the read only fields
-    sdp_bdo_destinations_rd.nof_destinations_act      <= parsed_nof_destinations;
-    sdp_bdo_destinations_rd.nof_blocks_per_packet_act <= parsed_nof_blocks_per_packet;
+    sdp_bdo_destinations_rd.nof_destinations_act      <= nof_destinations_act;
+    sdp_bdo_destinations_rd.nof_blocks_per_packet_act <= nof_blocks_per_packet_act;
   end process;
 
   u_mm_fields: entity mm_lib.mm_fields
@@ -223,13 +223,16 @@ begin
   sdp_bdo_destinations_wr.udp_destination_port_arr(14) <= mm_fields_out(field_hi(c_field_arr, "udp_destination_port_14") downto field_lo(c_field_arr, "udp_destination_port_14"));
   sdp_bdo_destinations_wr.udp_destination_port_arr(15) <= mm_fields_out(field_hi(c_field_arr, "udp_destination_port_15") downto field_lo(c_field_arr, "udp_destination_port_15"));
 
-  sdp_bdo_destinations_wr.nof_destinations      <= to_uint(mm_fields_out(field_hi(c_field_arr, "nof_destinations") downto field_lo(c_field_arr, "nof_destinations")));
-  sdp_bdo_destinations_wr.nof_blocks_per_packet <= to_uint(mm_fields_out(field_hi(c_field_arr, "nof_blocks_per_packet") downto field_lo(c_field_arr, "nof_blocks_per_packet")));
+  sdp_bdo_destinations_wr.nof_destinations <= to_uint(mm_fields_out(field_hi(c_field_arr, "nof_destinations") downto field_lo(c_field_arr, "nof_destinations")));
 
-  parsed_nof_destinations <= func_sdp_parse_nof_destinations(
-    sdp_bdo_destinations_wr.nof_destinations);
-
-  parsed_nof_blocks_per_packet <= func_sdp_parse_nof_blocks_per_packet(
-    sdp_bdo_destinations_wr.nof_blocks_per_packet,
-    sdp_bdo_destinations_wr.nof_destinations);
+  -- Register the read only actual values, to ease timing closure
+  p_dp_clk : process(dp_clk)
+    constant c_look_up_table : t_natural_arr(1 to c_sdp_bdo_nof_destinations_max) :=
+      func_sdp_bdo_nof_blocks_per_packet_look_up_table;
+  begin
+    if rising_edge(dp_clk) then
+      nof_destinations_act <= func_sdp_bdo_parse_nof_destinations(sdp_bdo_destinations_wr.nof_destinations);
+      nof_blocks_per_packet_act <= c_look_up_table(nof_destinations_act);
+    end if;
+  end process;
 end str;
-- 
GitLab