From 4dcd8e2778f1f46efda013d4ede53196223c294f Mon Sep 17 00:00:00 2001
From: donker <donker@astron.nl>
Date: Mon, 25 Jan 2021 15:26:52 +0100
Subject: [PATCH] L2SDP-200, working version.

---
 .../lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd |  16 +-
 .../sdp/src/vhdl/sdp_statistics_offload.vhd   |  62 +++---
 .../sdp/tb/vhdl/tb_sdp_statistics_offload.vhd | 191 ++++++++++++++++--
 .../common/src/vhdl/common_variable_delay.vhd |   2 +-
 .../base/dp/src/vhdl/dp_block_from_mm.vhd     |   2 +-
 5 files changed, 205 insertions(+), 68 deletions(-)

diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
index 487fef2361..15e3a26778 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
@@ -200,8 +200,8 @@ PACKAGE sdp_pkg is
   CONSTANT c_sdp_reg_nw_10GbE_eth10g_addr_w : NATURAL := 1;
 
   -- statistics SST offload
-  CONSTANT c_sdp_stat_nof_hdr_fields : NATURAL := 3+12+4+20+1+1; -- 592b; 9.25 64b words
-  CONSTANT c_sdp_stat_hdr_field_sel  : STD_LOGIC_VECTOR(c_sdp_stat_nof_hdr_fields-1 DOWNTO 0) := "101"&"111111111001"&"0111"&"11111111111111000000"&"0"&"0";  -- 0=data path, 1=MM controlled TODO
+  CONSTANT c_sdp_stat_nof_hdr_fields : NATURAL := 3+12+4+20+1; -- 592b; 9.25 64b words
+  CONSTANT c_sdp_stat_hdr_field_sel  : STD_LOGIC_VECTOR(c_sdp_stat_nof_hdr_fields-1 DOWNTO 0) := "101"&"111111111001"&"0111"&"01000000000000000000"&"0";  -- 0=data path, 1=MM controlled TODO
 
   CONSTANT c_sdp_stat_hdr_field_arr : t_common_field_arr(c_sdp_stat_nof_hdr_fields-1 DOWNTO 0) := (
       ( field_name_pad("eth_dst_mac"                             ), "RW", 48, field_default(x"00074306C700") ), -- 00074306C700=DOP36-eth0 
@@ -227,10 +227,10 @@ PACKAGE sdp_pkg is
       ( field_name_pad("udp_checksum"                            ), "RW", 16, field_default(0) ),
       
       ( field_name_pad("sdp_marker"                              ), "RW",  8, field_default(0) ),
-      ( field_name_pad("sdp_version_id"                          ), "RW",  8, field_default(1) ),
+      ( field_name_pad("sdp_version_id"                          ), "RW",  8, field_default(5) ),
+      
       ( field_name_pad("sdp_observation_id"                      ), "RW", 32, field_default(0) ),
       ( field_name_pad("sdp_station_id"                          ), "RW", 16, field_default(0) ),
-      
       ( field_name_pad("sdp_source_info_antenna_band_id"         ), "RW",  1, field_default(0) ),
       ( field_name_pad("sdp_source_info_nyquist_zone_id"         ), "RW",  2, field_default(0) ),
       ( field_name_pad("sdp_source_info_f_adc"                   ), "RW",  1, field_default(0) ),
@@ -247,11 +247,9 @@ PACKAGE sdp_pkg is
       ( field_name_pad("sdp_nof_signal_inputs"                   ), "RW",  8, field_default(0) ),
       ( field_name_pad("sdp_nof_bytes_per_statistics"            ), "RW",  8, field_default(8) ),
       ( field_name_pad("sdp_nof_statistics_per_package"          ), "RW", 16, field_default(0) ),
-      ( field_name_pad("sdp_block_period"                        ), "RW", 16, field_default(5120) ),
-
-      ( field_name_pad("dp_bsn"                                  ), "RW", 64, field_default(0) ),
-      ( field_name_pad("pad_to_32b"                              ), "RW", 16, field_default(0) )
-
+      ( field_name_pad("sdp_block_period"                        ), "RW", 16, field_default(0) ),
+      
+      ( field_name_pad("dp_bsn"                                  ), "RW", 64, field_default(0) )
   );
 END PACKAGE sdp_pkg;
 
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
index 171ef0d5de..c02c5797be 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
@@ -64,7 +64,7 @@ USE work.sdp_pkg.ALL;
 ENTITY sdp_statistics_offload IS
   GENERIC (
     g_statistics_type : STRING  := "SST";
-    g_offload_time    : NATURAL := 0;  -- from wave window (330320nS - 83105nS) / 50nS = 12361 cycles.
+    g_offload_time    : NATURAL := 13000;  -- from wave window 62855nS / 5nS = 12571 cycles.
     g_beamset_id      : NATURAL := 0
   );
   PORT (
@@ -103,9 +103,7 @@ END sdp_statistics_offload;
 
 ARCHITECTURE str OF sdp_statistics_offload IS
 
-  CONSTANT c_version                    : NATURAL := 1;
   CONSTANT c_marker                     : NATURAL := sel_a_b((g_statistics_type="BST"), 66, sel_a_b((g_statistics_type="XST"), 88, 83));  -- based on g_statistics_type: 'S'=0x53="SST", 'B'=0x42="BST", 'X'=0x58="XST"
-  CONSTANT c_nof_statistics_per_packet  : NATURAL := 0;
   CONSTANT c_data_size                  : NATURAL := 2;
   CONSTANT c_step_size                  : NATURAL := 4;
   CONSTANT c_nof_data                   : NATURAL := 512;
@@ -132,8 +130,6 @@ ARCHITECTURE str OF sdp_statistics_offload IS
   SIGNAL trigger                  : STD_LOGIC := '0';
   SIGNAL nof_cycles_dly           : NATURAL   := 0;
   SIGNAL mm_done                  : STD_LOGIC := '0';
-  SIGNAL start_addr               : NATURAL   := 0;
-  SIGNAL start_pulse              : STD_LOGIC := '0';
   SIGNAL dp_block_from_mm_src_out : t_dp_sosi;
   SIGNAL dp_block_from_mm_src_in  : t_dp_siso;
   
@@ -146,8 +142,6 @@ ARCHITECTURE str OF sdp_statistics_offload IS
   SIGNAL sdp_data_id : STD_LOGIC_VECTOR(31 DOWNTO 0);
   
 BEGIN
-  
-  -- count number of sop's in a sync interval
   p_bsn_at_sync : PROCESS(in_sosi)
   BEGIN
     IF in_sosi.sync = '1' THEN
@@ -157,32 +151,31 @@ BEGIN
 
   -- count number of sop's in a sync interval
   p_integration_interval : PROCESS(in_sosi)
-    VARIABLE cnt : NATURAL;
+    VARIABLE v_cnt : NATURAL;
   BEGIN
-    cnt := integration_interval_cnt;
+    v_cnt := integration_interval_cnt;
     IF in_sosi.sync = '1' THEN
-      integration_interval <= TO_UVEC(cnt, integration_interval'LENGTH);
+      integration_interval <= TO_UVEC(v_cnt, integration_interval'LENGTH);
       integration_interval_cnt <= 0;
     ELSE
       IF in_sosi.sop = '1' THEN
-        integration_interval_cnt <= cnt + 1;
+        integration_interval_cnt <= v_cnt + 1;
       END IF;
     END IF;
   END PROCESS;
 
   -- get payload errors and keep them till next sync
   p_payload_error : PROCESS(in_sosi)
-    VARIABLE err : STD_LOGIC;
+    VARIABLE v_err : STD_LOGIC;
   BEGIN
-    err := payload_err;
+    v_err := payload_err;
     IF in_sosi.sync = '1' THEN
       payload_err <= '0';
     ELSE
-      payload_err <= err OR in_sosi.err(0);
+      payload_err <= v_err OR in_sosi.err(0);
     END IF;
   END PROCESS;
 
-
   -------------------------------------------------------------------------------
   -- Assemble offload header info
   -------------------------------------------------------------------------------
@@ -209,7 +202,6 @@ BEGIN
   dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_block_period"                        ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "sdp_block_period"                        )) <= sdp_info.block_period;
   dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "dp_bsn"                                  ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "dp_bsn"                                  )) <= bsn_at_sync; 
 
-
   nof_cycles_dly <= gn_index * g_offload_time;
   sdp_data_id    <= r.data_id;
 
@@ -225,7 +217,9 @@ BEGIN
   p_control_packet_offload : PROCESS(r, trigger, mm_done)
   BEGIN
     d <= r;
-    d.last_mm_done <= mm_done;
+    d.start_pulse   <= '0';
+    d.last_mm_done  <= mm_done;
+    
     -- assign sdp_data_id for different statistic types
     IF g_statistics_type = "SST" THEN
       d.data_id <= x"000000" & TO_UVEC(r.block_count, 8);
@@ -237,31 +231,29 @@ BEGIN
       d.data_id <= x"00000000";
     END IF;
 
-    IF trigger = '1' AND d.block_count = 0 THEN
-      d.start_pulse <= '1';
-    END IF;
-
     IF mm_done = '1' AND r.last_mm_done = '0' THEN
-      d.block_count <= r.block_count + 1;
-      IF r.block_count mod 2 = 0 THEN
-        d.start_address <= r.block_count / 2 * c_block_size;
-      ELSE 
-        d.start_address <= r.start_address + c_data_size; 
+      IF r.block_count + 1 < c_sdp_S_pn THEN
+        d.block_count <= r.block_count + 1;
+        IF r.block_count mod 2 = 0 THEN
+          d.start_address <= r.block_count / 2 * c_block_size;
+        ELSE 
+          d.start_address <= r.start_address + c_data_size; 
+        END IF;
+        d.start_pulse <= '1';
+      ELSE
+        d.start_address <= 0; 
+        d.block_count   <= 0;
       END IF;
+    END IF;
+
+    IF trigger = '1' AND r.block_count = 0 THEN
       d.start_pulse <= '1';
     END IF;
 
     IF mm_done = '1' THEN
       d.dp_header_info <= dp_header_info;
     END IF;
-    
-    IF r.block_count >= c_sdp_S_pn THEN
-      d.block_count   <= 0;
-      d.start_address <= 0; 
-    END IF;
-
   END PROCESS;
-    
 
   u_mms_common_variable_delay : ENTITY common_lib.mms_common_variable_delay
   PORT MAP (
@@ -301,7 +293,7 @@ BEGIN
   GENERIC MAP (
     g_nof_streams    => c_nof_streams,
     g_data_w         => c_word_w,
-    g_symbol_w       => c_word_w,  -- if header is 32b alligned else c_byte_w
+    g_symbol_w       => c_word_w,
     g_hdr_field_arr  => c_sdp_stat_hdr_field_arr,
     g_hdr_field_sel  => c_sdp_stat_hdr_field_sel,
     g_pipeline_ready => TRUE
@@ -317,6 +309,6 @@ BEGIN
     snk_out_arr(0)       => dp_block_from_mm_src_in,
     src_out_arr(0)       => out_sosi,
     src_in_arr(0)        => out_siso,
-    hdr_fields_in_arr(0) => r.dp_header_info -- hdr_fields_in_arr(i) is considered valid @ snk_in_arr(i).sop
+    hdr_fields_in_arr(0) => r.dp_header_info
   );
 END str;
diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd
index 1495ce8949..5d27c9cf57 100644
--- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd
@@ -41,14 +41,16 @@ USE common_lib.tb_common_pkg.ALL;
 USE common_lib.tb_common_mem_pkg.ALL;
 USE common_lib.common_network_layers_pkg.ALL;
 USE common_lib.common_field_pkg.ALL;
+USE common_lib.common_str_pkg.ALL;
 USE dp_lib.dp_stream_pkg.ALL;
 USE work.sdp_pkg.ALL;
 
 
 ENTITY tb_sdp_statistics_offload IS
   GENERIC (
-    g_statistics_type : STRING := "SST";
-    g_nof_signal_inputs_per_pn : NATURAL := 12
+    g_statistics_type          : STRING := "SST";
+    g_nof_signal_inputs_per_pn : NATURAL := 12;
+    g_offload_time             : NATURAL := 500
   );
 END tb_sdp_statistics_offload;
 
@@ -76,11 +78,19 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS
   CONSTANT c_step_size : NATURAL := 4;
   CONSTANT c_ram_size  : NATURAL := c_nof_data * c_data_size * g_nof_signal_inputs_per_pn;
   CONSTANT c_ram_w     : NATURAL := ceil_log2(c_ram_size);
-  CONSTANT c_ram_buf   : t_c_mem := (c_mem_ram_rd_latency, c_ram_w,  32, 2**c_ram_w, 'X');
+  --CONSTANT c_ram_buf   : t_c_mem := (c_mem_ram_rd_latency, c_ram_w,  32, 2**c_ram_w, 'X');
+  CONSTANT c_ram_buf   : t_c_mem := (1, c_ram_w,  32, 2**c_ram_w, 'X');
 
   CONSTANT c_nof_block_per_sync : NATURAL := 20;  -- sufficient to fit more than g_nof_signal_inputs_per_pn offload packets per sync interval
   CONSTANT c_nof_clk_per_block : NATURAL := c_nof_data * c_data_size;
 
+  -- based on g_statistics_type: 'S'=0x53="SST", 'B'=0x42="BST", 'X'=0x58="XST"
+  CONSTANT c_marker                     : NATURAL := sel_a_b((g_statistics_type="BST"), 66            , sel_a_b((g_statistics_type="XST"), 88, 83));  
+  CONSTANT c_nof_signal_inputs          : NATURAL := sel_a_b((g_statistics_type="BST"), 0             , sel_a_b((g_statistics_type="XST"), c_sdp_S_pn, 1));
+  CONSTANT c_nof_statistics_per_package : NATURAL := sel_a_b((g_statistics_type="BST"), c_sdp_S_sub_bf, sel_a_b((g_statistics_type="XST"), (c_sdp_S_pn*c_sdp_S_pn*c_nof_complex), c_sdp_N_sub));
+
+  CONSTANT c_nof_clk_in_valid : NATURAL := c_nof_data * c_data_size + 1;  -- +1 for cmem_ram_rd_latency
+
   SIGNAL tb_end              : STD_LOGIC := '0';
 
   SIGNAL dp_clk              : STD_LOGIC := '1';   -- digital data path clock = 200 MHz (deser factor 4);
@@ -115,21 +125,35 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS
   SIGNAL rx_hdr_fields_raw   : STD_LOGIC_VECTOR(1023 DOWNTO 0) := (OTHERS => '0');
 
   -- signals used to change settings of sdp_info 
-  SIGNAL gn_index  : NATURAL   := 1; 
-  SIGNAL f_adc     : STD_LOGIC := '0'; 
-  SIGNAL fsub_type : STD_LOGIC := '0';
-
-  SIGNAL sdp_info  : t_sdp_info := ( x"0001", '0', x"00000003", b"01", '0', '0', '0', '0', x"00", x"00", x"00", x"00", x"0000", x"0000");
+  SIGNAL gn_index  : NATURAL := 1;  -- select > 0 to see effect of g_offload_time 
+  
+  SIGNAL sdp_info  :  t_sdp_info := (
+                        TO_UVEC(601, 16),   -- station_id
+                        '0',                -- antenna_band_index
+                        x"00001111",        -- observation_id  
+                        b"01",              -- nyquist_zone_index
+                        '0',                -- f_adc  
+                        '1',                -- fsub_type
+                        '0',                -- beam_repositioning_flag
+                        '1',                -- subband_calibrated_flag
+                        x"01",              -- O_si
+                        x"02",              -- N_si
+                        x"04",              -- O_rn
+                        x"08",              -- N_rn
+                        x"1400",            -- block_period = 5120
+                        x"0000"             -- beamlet_scale
+                      );
 
   -- signals used for starting processes
-  SIGNAL ram_wr_data      : STD_LOGIC_VECTOR(c_ram_buf.dat_w-1 DOWNTO 0);
-  SIGNAL ram_wr_addr      : STD_LOGIC_VECTOR(c_ram_buf.adr_w-1 DOWNTO 0);
-  SIGNAL ram_wr_en        : STD_LOGIC;
-  SIGNAL init_ram_done: STD_LOGIC := '0';
-
-  SIGNAL rx_bsn     : NATURAL := 0;
-  SIGNAL rx_data_id : NATURAL := 0;
+  SIGNAL ram_wr_data   : STD_LOGIC_VECTOR(c_ram_buf.dat_w-1 DOWNTO 0);
+  SIGNAL ram_wr_addr   : STD_LOGIC_VECTOR(c_ram_buf.adr_w-1 DOWNTO 0);
+  SIGNAL ram_wr_en     : STD_LOGIC;
+  SIGNAL init_ram_done : STD_LOGIC := '0';
 
+  SIGNAL rx_bsn           : NATURAL := 0;
+  SIGNAL rx_data_id       : NATURAL := 0;
+  SIGNAL rx_block_cnt     : NATURAL := 0;
+  SIGNAL rx_valid_clk_cnt : NATURAL := 0;
 
 BEGIN
   dp_rst <= '1', '0' AFTER c_dp_clk_period*7;
@@ -154,7 +178,8 @@ BEGIN
       proc_common_wait_some_cycles(mm_clk, 1);
     END LOOP; 
     ram_wr_en <= '0';
-    
+
+    proc_common_wait_until_high(dp_clk, in_sosi.sync);
     init_ram_done <= '1'; 
     WAIT;
   END PROCESS;
@@ -168,11 +193,18 @@ BEGIN
     WAIT;
   END PROCESS;
 
+  -- dp_offload_tx_v3.vhd can handle 32 data that is not alligned, dp_offload_rx can not.
+  -- this is the reason the firts 16bit of the header are always zero.
+  -- this process will start counting with bit16 high, the firt bit that wil be received
+  -- on each dp_clk bsn is incremented with 0xffff, if you look at B63..b16 it looks like normal counting
+  -- if dp_offload_rx.vhd is fixed this can be set normal again.
   p_in_sosi : PROCESS
   BEGIN
     proc_common_wait_until_low(dp_clk, dp_rst);
     proc_common_wait_some_cycles(dp_clk, 10);
     in_sosi.valid <= '1';
+    in_sosi.bsn <= x"0000000000010000";
+    proc_common_wait_some_cycles(dp_clk, 1);
     WHILE TRUE LOOP
       FOR i IN 0 TO c_nof_block_per_sync-1 LOOP
         FOR j IN 0 TO c_nof_clk_per_block-1 LOOP
@@ -184,7 +216,7 @@ BEGIN
           END IF;
           IF j = 0 THEN
             in_sosi.sop  <= '1';
-            in_sosi.bsn  <= INCR_UVEC(in_sosi.bsn, 1);
+            in_sosi.bsn  <= INCR_UVEC(in_sosi.bsn, 65535);
           END IF;
           IF j = c_nof_clk_per_block-1 THEN
             in_sosi.eop  <= '1';
@@ -196,15 +228,130 @@ BEGIN
     WAIT;
   END PROCESS;
 
-  p_verify : PROCESS(test_offload_sosi, rx_hdr_fields_raw)
+  p_verify_header : PROCESS
   BEGIN
-    IF test_offload_sosi.sop = '1' THEN
-      rx_bsn     <= TO_UINT(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "dp_bsn")      DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "dp_bsn")));
+    proc_common_wait_until_high(mm_clk, init_ram_done);
+    proc_common_wait_until_high(mm_clk, test_offload_sosi.eop);
+    -- bsn is not fully received (bit 0-15 is missing) because 32 bit allignment not working in dp_offload_rx.vhd.   
+    -- check fixed settings
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "eth_dst_mac") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "eth_dst_mac")) = x"00074306C700"
+      REPORT "wrong eth_dst_mac" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "eth_type") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "eth_type")) = x"0800"
+      REPORT "wrong eth_type" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_version") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_version")) = TO_UVEC(4, 4)
+      REPORT "wrong ip_version" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_header_length") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_header_length")) = TO_UVEC(5, 4)
+      REPORT "wrong ip_header_length" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_services") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_services")) = TO_UVEC(0, 8)
+      REPORT "wrong ip_services" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_total_length") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_total_length")) = TO_UVEC(7868, 16)
+      REPORT "wrong ip_total_length" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_identification") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_identification")) = TO_UVEC(0, 16)
+      REPORT "wrong ip_identification" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_flags") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_flags")) = TO_UVEC(2, 3)
+      REPORT "wrong ip_flags" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_fragment_offset") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_fragment_offset")) = TO_UVEC(0, 13)
+      REPORT "wrong ip_fragment_offset" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_time_to_live") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_time_to_live")) = TO_UVEC(127, 8)
+      REPORT "wrong ip_time_to_live" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_protocol") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_protocol")) = TO_UVEC(17, 8)
+      REPORT "wrong ip_protocol" SEVERITY ERROR;  
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_dst_addr") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_dst_addr")) = x"C0A80001"
+      REPORT "wrong ip_dst_addr" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "udp_dst_port") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_dst_port")) = TO_UVEC(0, 16)
+      REPORT "wrong udp_dst_port" SEVERITY ERROR;  
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "udp_total_length") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_total_length")) = TO_UVEC(7848, 16)
+      REPORT "wrong udp_total_length" SEVERITY ERROR; 
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_version_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_version_id")) = TO_UVEC(5, 8)
+      REPORT "wrong sdp_version_id" SEVERITY ERROR;  
+    
+    -- check settings set by mm interface in this test bench
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "eth_src_mac") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "eth_src_mac")) = c_eth_src_mac
+      REPORT "wrong eth_src_mac" SEVERITY ERROR;    
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "ip_src_addr") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_src_addr")) = c_ip_src_addr
+      REPORT "wrong ip_src_addr" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "udp_src_port") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_src_port")) = c_udp_src_port
+      REPORT "wrong udp_src_port" SEVERITY ERROR;
+    
+    -- check g_statistics_type settings set by sdp_statistics_offload.vhd 
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_marker") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_marker")) = TO_UVEC(c_marker, 8)
+      REPORT "wrong sdp_marker" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_signal_inputs") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_signal_inputs")) = TO_UVEC(c_nof_signal_inputs, 8)
+      REPORT "wrong sdp_nof_signal_inputs" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_statistics_per_package") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_statistics_per_package")) = TO_UVEC(c_nof_statistics_per_package, 8)
+      REPORT "wrong sdp_nof_statistics_per_package" SEVERITY ERROR;
+    
+    -- check some values from sdp_source_info
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_observation_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_observation_id")) = sdp_info.observation_id
+      REPORT "wrong sdp_observation_id" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_station_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_station_id")) = sdp_info.station_id
+      REPORT "wrong sdp_station_id" SEVERITY ERROR;
+    ASSERT SL(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_antenna_band_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_antenna_band_id"))) = sdp_info.antenna_band_index
+      REPORT "wrong sdp_source_info_antenna_band_id" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_nyquist_zone_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_nyquist_zone_id")) = sdp_info.nyquist_zone_index
+      REPORT "wrong sdp_source_info_nyquist_zone_id" SEVERITY ERROR;
+    ASSERT SL(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_f_adc") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_f_adc"))) = sdp_info.f_adc
+      REPORT "wrong sdp_source_info_f_adc" SEVERITY ERROR;
+    ASSERT SL(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_fsub_type") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_fsub_type"))) = sdp_info.fsub_type
+      REPORT "wrong sdp_source_info_fsub_type" SEVERITY ERROR;
+    ASSERT SL(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_beam_repositioning_flag") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_beam_repositioning_flag"))) = sdp_info.beam_repositioning_flag
+      REPORT "wrong sdp_source_info_beam_repositioning_flag" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_gn_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_gn_id")) = TO_UVEC(gn_index, 5)
+      REPORT "wrong sdp_source_info_gn_id" SEVERITY ERROR;
+    ASSERT rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_block_period") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_block_period")) = sdp_info.block_period
+      REPORT "wrong sdp_block_period" SEVERITY ERROR;
+    WAIT;
+  END PROCESS;
+
+ p_verify : PROCESS(in_sosi.sync, test_offload_sosi, rx_hdr_fields_raw)
+    VARIABLE v_bsn       : NATURAL;
+    VARIABLE v_block_cnt : NATURAL;
+  BEGIN
+    v_bsn       := rx_bsn;
+    v_block_cnt := rx_block_cnt;
+    
+    IF init_ram_done = '1' THEN
+      IF in_sosi.sync = '1' AND rx_block_cnt > 0 THEN
+        ASSERT rx_block_cnt = g_nof_signal_inputs_per_pn REPORT "wrong number of blocks between 2 sync" SEVERITY ERROR;
+      END IF;
+
+      IF test_offload_sosi.sop = '1' AND v_block_cnt = g_nof_signal_inputs_per_pn THEN
+        v_block_cnt := 0;
+      END IF;
+
+      IF test_offload_sosi.eop = '1' THEN
+        -- check info by p_in_sosi why +16 is used
+        v_bsn := TO_UINT(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "dp_bsn") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "dp_bsn")+16));
+        v_block_cnt := v_block_cnt + 1;
+        IF rx_bsn > 0 AND v_bsn > rx_bsn THEN
+          ASSERT (v_bsn - rx_bsn) = c_nof_block_per_sync REPORT "wrong number of blocks between 2 bsn numbers" SEVERITY ERROR;
+        END IF;
+      END IF;
+
       rx_data_id <= TO_UINT(rx_hdr_fields_raw(field_hi(c_sdp_stat_hdr_field_arr, "sdp_data_id") DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_data_id")));
     END IF;
     test_offload_siso <= c_dp_siso_rdy;
+    rx_bsn            <= v_bsn;
+    rx_block_cnt      <= v_block_cnt;
   END PROCESS;
 
+  p_verify_valid : PROCESS(dp_clk)
+    VARIABLE v_cnt : NATURAL;
+  BEGIN
+    v_cnt := rx_valid_clk_cnt;
+    IF rising_edge(dp_clk) THEN
+      IF test_offload_sosi.valid = '1' THEN
+        v_cnt := v_cnt + 1;
+      ELSE
+        IF v_cnt > 0 THEN
+          ASSERT v_cnt = c_nof_clk_in_valid REPORT "wrong number of clock counts while valid" SEVERITY ERROR;
+          v_cnt := 0;
+        END IF;
+      END IF;
+    END IF;
+    rx_valid_clk_cnt <= v_cnt; 
+  END PROCESS; 
+
   p_mm_offload : PROCESS
   BEGIN
     proc_common_wait_until_low(mm_clk, mm_rst);
@@ -239,7 +386,7 @@ BEGIN
   p_dp_end : PROCESS
   BEGIN
     proc_common_wait_until_high(mm_clk, init_ram_done);
-    proc_common_wait_some_cycles(dp_clk, 320000);
+    proc_common_wait_some_cycles(dp_clk, 100000);  -- will show 4 sync periods
     tb_end <= '1';
     WAIT;
   END PROCESS;
@@ -297,7 +444,7 @@ BEGIN
   u_dut: ENTITY work.sdp_statistics_offload
   GENERIC MAP (
     g_statistics_type => "SST",
-    g_offload_time    => 500,
+    g_offload_time    => g_offload_time,
     g_beamset_id      => 0
   )
   PORT MAP (
diff --git a/libraries/base/common/src/vhdl/common_variable_delay.vhd b/libraries/base/common/src/vhdl/common_variable_delay.vhd
index 847bb54e53..8d4c8f65e3 100644
--- a/libraries/base/common/src/vhdl/common_variable_delay.vhd
+++ b/libraries/base/common/src/vhdl/common_variable_delay.vhd
@@ -57,7 +57,7 @@ ARCHITECTURE rtl OF common_variable_delay IS
 BEGIN
   out_val <= i_out_val;
   
-  p_delay: PROCESS(enable, in_val, prev_in_val, delay, delay_cnt)
+  p_delay: PROCESS(in_val, prev_in_val, delay, delay_cnt)
   BEGIN
     nxt_out_val   <= '0';
     nxt_delay_cnt <= 0; 
diff --git a/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd b/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd
index d0b3fecfc1..d3b8c961bb 100644
--- a/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd
+++ b/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd
@@ -72,7 +72,7 @@ ARCHITECTURE rtl OF dp_block_from_mm IS
   SIGNAL last_mm_address : NATURAL := 0;
 BEGIN
 
-  last_mm_address <= g_step_size * (g_nof_data - 1) + g_data_size + start_address;
+  last_mm_address <= g_step_size * (g_nof_data - 1) + g_data_size + start_address - 1;
   mm_address      <= start_address + r.word_index + r.step_index;
   
   mm_mosi.address <= TO_MEM_ADDRESS(mm_address);
-- 
GitLab