diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml b/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml
index 259d0c1739204987cf5f0668e8890aff7734861d..483d9968983f1978dfc20c426639d7d875cac575 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml
@@ -11,8 +11,12 @@ parameters:
   - { name: c_N_beamsets,           value: 2 }
   - { name: c_N_sub,                value: 512 }
   - { name: c_N_fft,                value: 1024 }
+  - { name: c_N_pn_lb,              value: 16 }
   - { name: c_S_pn,                 value: 12 }
   - { name: c_Q_fft,                value: 2 }
+  - { name: c_P_sq,                 value: 1 + c_N_pn_lb // 2 }  # = 1 + 16 // 2 = 9, on revision xsub_one only first X_sq cell is used
+  - { name: c_X_sq,                 value: c_S_pn * c_S_pn }  # = 144
+  - { name: c_N_crosslets,          value: 1 }
   - { name: c_N_taps,               value: 16 }
   - { name: c_W_adc_jesd,           value: 16 }
   - { name: c_W_adc,                value: 14 }
@@ -220,6 +224,9 @@ peripherals:
       - REG_DP_SYNC_INSERT_V2   
       
   - peripheral_name: st/st_xst_for_sdp
+    parameter_overrides:
+      - { name: g_nof_streams, value: c_P_sq }
+      - { name: g_nof_crosslets, value: c_N_crosslets }
     mm_port_names:
       - RAM_ST_XSQ
       
@@ -236,6 +243,7 @@ peripherals:
     peripheral_group: xst
     mm_port_names:
       - REG_STAT_HDR_DAT_XST
+
   #############################################################################
   # BF = Beamformer (from node_sdp_beamformer.vhd)
   #############################################################################
diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.mmap.gold b/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.mmap.gold
index 43436c87930d6ee258b7137a3e52b6e226bad8ad..dca487687ea75fb0a4b6f8d7a0eb4c0f7d709756 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.mmap.gold
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.mmap.gold
@@ -112,7 +112,7 @@ number_of_columns = 13
   REG_DP_SHIFTRAM           1     12    REG    shift                                     0x00022000       1     RW       uint32     b[11:0]           -  -      2    
   REG_BSN_SOURCE_V2         1     1     REG    dp_on                                     0x00024000       1     RW       uint32      b[0:0]           -  -      -    
   -                         -     -     -      dp_on_pps                                 0x00024000       1     RW       uint32      b[1:1]           -  -      -    
-  -                         -     -     -      nof_block_per_sync                        0x00024001       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      nof_clk_per_sync                          0x00024001       1     RW       uint32     b[31:0]           -  -      -    
   -                         -     -     -      bsn_init                                  0x00024002       1     RW       uint64     b[31:0]     b[31:0]  -      -    
   -                         -     -     -      -                                         0x00024003       -      -            -     b[31:0]    b[63:32]  -      -    
   -                         -     -     -      bsn_time_offset                           0x00024004       1     RW       uint32      b[9:0]           -  -      -    
@@ -146,8 +146,8 @@ number_of_columns = 13
   RAM_FIL_COEFS             1     16    RAM    data                                      0x0003c000    1024     RW       uint32     b[15:0]           -  -      1024 
   RAM_EQUALIZER_GAINS       1     6     RAM    data                                      0x00040000    1024     RW    cint16_ir     b[31:0]           -  -      1024 
   REG_DP_SELECTOR           1     1     REG    input_select                              0x00042000       1     RW       uint32      b[0:0]           -  -      -    
-  RAM_ST_SST                1     6     RAM    data                                      0x00044000    2048     RW       uint64     b[31:0]     b[31:0]  -      2048 
-  -                         -     -     -      -                                         0x00042001       -      -            -     b[21:0]    b[53:32]  -      -    
+  RAM_ST_SST                1     6     RAM    data                                      0x00044000    1024     RW       uint64     b[31:0]     b[31:0]  -      2048 
+  -                         -     -     -      -                                         0x00044001       -      -            -     b[21:0]    b[53:32]  -      -    
   REG_STAT_ENABLE_SST       1     1     REG    enable                                    0x00048000       1     RW       uint32      b[0:0]           -  -      -    
   REG_STAT_HDR_DAT_SST      1     1     REG    bsn                                       0x0004a000       1     RW       uint64     b[31:0]     b[31:0]  -      -    
   -                         -     -     -      -                                         0x0004a001       -      -            -     b[31:0]    b[63:32]  -      -    
@@ -198,331 +198,331 @@ number_of_columns = 13
   REG_BSN_SCHEDULER_XSUB    1     1     REG    scheduled_bsn                             0x0004c000       1     RW       uint64     b[31:0]     b[31:0]  -      -    
   -                         -     -     -      -                                         0x0004c001       -      -            -     b[31:0]    b[63:32]  -      -    
   REG_DP_SYNC_INSERT_V2     1     1     REG    nof_blk_per_sync                          0x0004e000       1     RW       uint32     b[31:0]           -  -      -    
-  RAM_ST_XSQ                1     1     RAM    data                                      0x00050000     576     RW    cint64_ir     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      -                                         0x0004e001       -      -            -     b[31:0]    b[63:32]  -      -    
-  REG_CROSSLETS_INFO        1     1     REG    offset                                    0x00052000      15     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      step                                      0x0005200f       1     RW       uint32     b[31:0]           -  -      -    
-  REG_STAT_ENABLE_XST       1     1     REG    enable                                    0x00054000       1     RW       uint32      b[0:0]           -  -      -    
-  REG_STAT_HDR_DAT_XST      1     1     REG    bsn                                       0x00056000       1     RW       uint64     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      -                                         0x00056001       -      -            -     b[31:0]    b[63:32]  -      -    
-  -                         -     -     -      block_period                              0x00056002       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      nof_statistics_per_packet                 0x00056003       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      nof_bytes_per_statistic                   0x00056004       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      nof_signal_inputs                         0x00056005       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      sdp_data_id                               0x00056006       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      sdp_data_id_xst_signal_input_b_index      0x00056006       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      sdp_data_id_xst_signal_input_a_index      0x00056006       1     RW       uint32     b[15:8]           -  -      -    
-  -                         -     -     -      sdp_data_id_xst_subband_index             0x00056006       1     RW       uint32    b[24:16]           -  -      -    
-  -                         -     -     -      sdp_data_id_xst_reserved                  0x00056006       1     RW       uint32    b[31:25]           -  -      -    
-  -                         -     -     -      sdp_integration_interval                  0x00056007       1     RW       uint32     b[23:0]           -  -      -    
-  -                         -     -     -      sdp_reserved                              0x00056008       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      sdp_source_info_gn_index                  0x00056009       1     RW       uint32      b[4:0]           -  -      -    
-  -                         -     -     -      sdp_source_info_reserved                  0x0005600a       1     RW       uint32      b[7:5]           -  -      -    
-  -                         -     -     -      sdp_source_info_subband_calibrated_flag   0x0005600b       1     RW       uint32      b[8:8]           -  -      -    
-  -                         -     -     -      sdp_source_info_beam_repositioning_flag   0x0005600c       1     RW       uint32      b[9:9]           -  -      -    
-  -                         -     -     -      sdp_source_info_payload_error             0x0005600d       1     RW       uint32    b[10:10]           -  -      -    
-  -                         -     -     -      sdp_source_info_fsub_type                 0x0005600e       1     RW       uint32    b[11:11]           -  -      -    
-  -                         -     -     -      sdp_source_info_f_adc                     0x0005600f       1     RW       uint32    b[12:12]           -  -      -    
-  -                         -     -     -      sdp_source_info_nyquist_zone_index        0x00056010       1     RW       uint32    b[14:13]           -  -      -    
-  -                         -     -     -      sdp_source_info_antenna_band_index        0x00056011       1     RW       uint32    b[15:15]           -  -      -    
-  -                         -     -     -      sdp_station_id                            0x00056012       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      sdp_observation_id                        0x00056013       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      sdp_version_id                            0x00056014       1     RO       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      sdp_marker                                0x00056015       1     RO       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      udp_checksum                              0x00056016       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      udp_length                                0x00056017       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      udp_destination_port                      0x00056018       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      udp_source_port                           0x00056019       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_destination_address                    0x0005601a       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      ip_source_address                         0x0005601b       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      ip_header_checksum                        0x0005601c       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_protocol                               0x0005601d       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      ip_time_to_live                           0x0005601e       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      ip_fragment_offset                        0x0005601f       1     RW       uint32     b[12:0]           -  -      -    
-  -                         -     -     -      ip_flags                                  0x00056020       1     RW       uint32      b[2:0]           -  -      -    
-  -                         -     -     -      ip_identification                         0x00056021       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_total_length                           0x00056022       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_services                               0x00056023       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      ip_header_length                          0x00056024       1     RW       uint32      b[3:0]           -  -      -    
-  -                         -     -     -      ip_version                                0x00056025       1     RW       uint32      b[3:0]           -  -      -    
-  -                         -     -     -      eth_type                                  0x00056026       1     RO       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      eth_source_mac                            0x00056027       1     RO       uint64     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      -                                         0x00056028       -      -            -     b[15:0]    b[47:32]  -      -    
-  -                         -     -     -      eth_destination_mac                       0x00056029       1     RW       uint64     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      -                                         0x0005602a       -      -            -     b[15:0]    b[47:32]  -      -    
-  -                         -     -     -      word_align                                0x0005602b       1     RW       uint32     b[15:0]           -  -      -    
-  RAM_SS_SS_WIDE            2     6     RAM    data                                      0x00058000     976     RW       uint32      b[9:0]           -  8192   1024 
-  RAM_BF_WEIGHTS            2     12    RAM    data                                      0x0005c000     976     RW    cint16_ir     b[31:0]           -  16384  1024 
-  REG_BF_SCALE              2     1     REG    scale                                     0x00064000       1     RW       uint32     b[15:0]           -  2      2    
-  -                         -     -     -      unused                                    0x00064001       1     RW       uint32     b[31:0]           -  -      -    
-  REG_HDR_DAT               2     1     REG    bsn                                       0x00066000       1     RW       uint64     b[31:0]     b[31:0]  64     64   
-  -                         -     -     -      -                                         0x00066001       -      -            -     b[31:0]    b[63:32]  -      -    
-  -                         -     -     -      sdp_block_period                          0x00066002       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      sdp_nof_beamlets_per_block                0x00066003       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      sdp_nof_blocks_per_packet                 0x00066004       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      sdp_beamlet_index                         0x00066005       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      sdp_beamlet_scale                         0x00066006       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      sdp_reserved                              0x00066007       1     RW       uint64     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      -                                         0x00066008       -      -            -      b[7:0]    b[39:32]  -      -    
-  -                         -     -     -      sdp_source_info_gn_index                  0x00066009       1     RW       uint32      b[4:0]           -  -      -    
-  -                         -     -     -      sdp_source_info_beamlet_width             0x0006600a       1     RW       uint32      b[7:5]           -  -      -    
-  -                         -     -     -      sdp_source_info_repositioning_flag        0x0006600b       1     RW       uint32      b[9:9]           -  -      -    
-  -                         -     -     -      sdp_source_info_payload_error             0x0006600c       1     RW       uint32    b[10:10]           -  -      -    
-  -                         -     -     -      sdp_source_info_fsub_type                 0x0006600d       1     RW       uint32    b[11:11]           -  -      -    
-  -                         -     -     -      sdp_source_info_f_adc                     0x0006600e       1     RW       uint32    b[12:12]           -  -      -    
-  -                         -     -     -      sdp_source_info_nyquist_zone_index        0x0006600f       1     RW       uint32    b[14:13]           -  -      -    
-  -                         -     -     -      sdp_source_info_antenna_band_index        0x00066010       1     RW       uint32    b[15:15]           -  -      -    
-  -                         -     -     -      sdp_station_id                            0x00066011       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      sdp_observation_id                        0x00066012       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      sdp_version_id                            0x00066013       1     RO       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      sdp_marker                                0x00066014       1     RO       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      udp_checksum                              0x00066015       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      udp_length                                0x00066016       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      udp_destination_port                      0x00066017       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      udp_source_port                           0x00066018       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_destination_address                    0x00066019       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      ip_source_address                         0x0006601a       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      ip_header_checksum                        0x0006601b       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_protocol                               0x0006601c       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      ip_time_to_live                           0x0006601d       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      ip_fragment_offset                        0x0006601e       1     RW       uint32     b[12:0]           -  -      -    
-  -                         -     -     -      ip_flags                                  0x0006601f       1     RW       uint32      b[2:0]           -  -      -    
-  -                         -     -     -      ip_identification                         0x00066020       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_total_length                           0x00066021       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_services                               0x00066022       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      ip_header_length                          0x00066023       1     RW       uint32      b[3:0]           -  -      -    
-  -                         -     -     -      ip_version                                0x00066024       1     RW       uint32      b[3:0]           -  -      -    
-  -                         -     -     -      eth_type                                  0x00066025       1     RO       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      eth_source_mac                            0x00066026       1     RO       uint64     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      -                                         0x00066027       -      -            -     b[15:0]    b[47:32]  -      -    
-  -                         -     -     -      eth_destination_mac                       0x00066028       1     RW       uint64     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      -                                         0x00066029       -      -            -     b[15:0]    b[47:32]  -      -    
-  REG_DP_XONOFF             2     1     REG    enable_stream                             0x00068000       1     RW       uint32      b[0:0]           -  2      2    
-  RAM_ST_BST                2     1     RAM    data                                      0x0006a000    1952     RW       uint64     b[31:0]     b[31:0]  2048   2048 
-  -                         -     -     -      -                                         0x00068001       -      -            -     b[21:0]    b[53:32]  -      -    
-  REG_STAT_ENABLE_BST       2     1     REG    enable                                    0x0006c000       1     RW       uint32      b[0:0]           -  2      2    
-  REG_STAT_HDR_DAT_BST      2     1     REG    bsn                                       0x0006e000       1     RW       uint64     b[31:0]     b[31:0]  64     64   
+  RAM_ST_XSQ                1     9     RAM    data                                      0x00050000     144     RW    cint64_ir     b[31:0]     b[31:0]  -      1028 
+  -                         -     -     -      -                                         0x00050001       -      -            -     b[31:0]    b[63:32]  -      -    
+  REG_CROSSLETS_INFO        1     1     REG    offset                                    0x00058000      15     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      step                                      0x0005800f       1     RW       uint32     b[31:0]           -  -      -    
+  REG_STAT_ENABLE_XST       1     1     REG    enable                                    0x0005a000       1     RW       uint32      b[0:0]           -  -      -    
+  REG_STAT_HDR_DAT_XST      1     1     REG    bsn                                       0x0005c000       1     RW       uint64     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      -                                         0x0005c001       -      -            -     b[31:0]    b[63:32]  -      -    
+  -                         -     -     -      block_period                              0x0005c002       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      nof_statistics_per_packet                 0x0005c003       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      nof_bytes_per_statistic                   0x0005c004       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      nof_signal_inputs                         0x0005c005       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      sdp_data_id                               0x0005c006       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      sdp_data_id_xst_signal_input_b_index      0x0005c006       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      sdp_data_id_xst_signal_input_a_index      0x0005c006       1     RW       uint32     b[15:8]           -  -      -    
+  -                         -     -     -      sdp_data_id_xst_subband_index             0x0005c006       1     RW       uint32    b[24:16]           -  -      -    
+  -                         -     -     -      sdp_data_id_xst_reserved                  0x0005c006       1     RW       uint32    b[31:25]           -  -      -    
+  -                         -     -     -      sdp_integration_interval                  0x0005c007       1     RW       uint32     b[23:0]           -  -      -    
+  -                         -     -     -      sdp_reserved                              0x0005c008       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      sdp_source_info_gn_index                  0x0005c009       1     RW       uint32      b[4:0]           -  -      -    
+  -                         -     -     -      sdp_source_info_reserved                  0x0005c00a       1     RW       uint32      b[7:5]           -  -      -    
+  -                         -     -     -      sdp_source_info_subband_calibrated_flag   0x0005c00b       1     RW       uint32      b[8:8]           -  -      -    
+  -                         -     -     -      sdp_source_info_beam_repositioning_flag   0x0005c00c       1     RW       uint32      b[9:9]           -  -      -    
+  -                         -     -     -      sdp_source_info_payload_error             0x0005c00d       1     RW       uint32    b[10:10]           -  -      -    
+  -                         -     -     -      sdp_source_info_fsub_type                 0x0005c00e       1     RW       uint32    b[11:11]           -  -      -    
+  -                         -     -     -      sdp_source_info_f_adc                     0x0005c00f       1     RW       uint32    b[12:12]           -  -      -    
+  -                         -     -     -      sdp_source_info_nyquist_zone_index        0x0005c010       1     RW       uint32    b[14:13]           -  -      -    
+  -                         -     -     -      sdp_source_info_antenna_band_index        0x0005c011       1     RW       uint32    b[15:15]           -  -      -    
+  -                         -     -     -      sdp_station_id                            0x0005c012       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      sdp_observation_id                        0x0005c013       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      sdp_version_id                            0x0005c014       1     RO       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      sdp_marker                                0x0005c015       1     RO       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      udp_checksum                              0x0005c016       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      udp_length                                0x0005c017       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      udp_destination_port                      0x0005c018       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      udp_source_port                           0x0005c019       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_destination_address                    0x0005c01a       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      ip_source_address                         0x0005c01b       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      ip_header_checksum                        0x0005c01c       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_protocol                               0x0005c01d       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      ip_time_to_live                           0x0005c01e       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      ip_fragment_offset                        0x0005c01f       1     RW       uint32     b[12:0]           -  -      -    
+  -                         -     -     -      ip_flags                                  0x0005c020       1     RW       uint32      b[2:0]           -  -      -    
+  -                         -     -     -      ip_identification                         0x0005c021       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_total_length                           0x0005c022       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_services                               0x0005c023       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      ip_header_length                          0x0005c024       1     RW       uint32      b[3:0]           -  -      -    
+  -                         -     -     -      ip_version                                0x0005c025       1     RW       uint32      b[3:0]           -  -      -    
+  -                         -     -     -      eth_type                                  0x0005c026       1     RO       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      eth_source_mac                            0x0005c027       1     RO       uint64     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      -                                         0x0005c028       -      -            -     b[15:0]    b[47:32]  -      -    
+  -                         -     -     -      eth_destination_mac                       0x0005c029       1     RW       uint64     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      -                                         0x0005c02a       -      -            -     b[15:0]    b[47:32]  -      -    
+  -                         -     -     -      word_align                                0x0005c02b       1     RW       uint32     b[15:0]           -  -      -    
+  RAM_SS_SS_WIDE            2     6     RAM    data                                      0x0005e000     976     RW       uint32      b[9:0]           -  8192   1024 
+  RAM_BF_WEIGHTS            2     12    RAM    data                                      0x00064000     976     RW    cint16_ir     b[31:0]           -  16384  1024 
+  REG_BF_SCALE              2     1     REG    scale                                     0x0006c000       1     RW       uint32     b[15:0]           -  2      2    
+  -                         -     -     -      unused                                    0x0006c001       1     RW       uint32     b[31:0]           -  -      -    
+  REG_HDR_DAT               2     1     REG    bsn                                       0x0006e000       1     RW       uint64     b[31:0]     b[31:0]  64     64   
   -                         -     -     -      -                                         0x0006e001       -      -            -     b[31:0]    b[63:32]  -      -    
-  -                         -     -     -      block_period                              0x0006e002       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      nof_statistics_per_packet                 0x0006e003       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      nof_bytes_per_statistic                   0x0006e004       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      nof_signal_inputs                         0x0006e005       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      sdp_data_id                               0x0006e006       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      sdp_data_id_bst_beamlet_index             0x0006e006       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      sdp_data_id_bst_reserved                  0x0006e006       1     RW       uint32    b[31:16]           -  -      -    
-  -                         -     -     -      sdp_integration_interval                  0x0006e007       1     RW       uint32     b[23:0]           -  -      -    
-  -                         -     -     -      sdp_reserved                              0x0006e008       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      sdp_block_period                          0x0006e002       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      sdp_nof_beamlets_per_block                0x0006e003       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      sdp_nof_blocks_per_packet                 0x0006e004       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      sdp_beamlet_index                         0x0006e005       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      sdp_beamlet_scale                         0x0006e006       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      sdp_reserved                              0x0006e007       1     RW       uint64     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      -                                         0x0006e008       -      -            -      b[7:0]    b[39:32]  -      -    
   -                         -     -     -      sdp_source_info_gn_index                  0x0006e009       1     RW       uint32      b[4:0]           -  -      -    
-  -                         -     -     -      sdp_source_info_reserved                  0x0006e00a       1     RW       uint32      b[7:5]           -  -      -    
-  -                         -     -     -      sdp_source_info_subband_calibrated_flag   0x0006e00b       1     RW       uint32      b[8:8]           -  -      -    
-  -                         -     -     -      sdp_source_info_beam_repositioning_flag   0x0006e00c       1     RW       uint32      b[9:9]           -  -      -    
-  -                         -     -     -      sdp_source_info_payload_error             0x0006e00d       1     RW       uint32    b[10:10]           -  -      -    
-  -                         -     -     -      sdp_source_info_fsub_type                 0x0006e00e       1     RW       uint32    b[11:11]           -  -      -    
-  -                         -     -     -      sdp_source_info_f_adc                     0x0006e00f       1     RW       uint32    b[12:12]           -  -      -    
-  -                         -     -     -      sdp_source_info_nyquist_zone_index        0x0006e010       1     RW       uint32    b[14:13]           -  -      -    
-  -                         -     -     -      sdp_source_info_antenna_band_index        0x0006e011       1     RW       uint32    b[15:15]           -  -      -    
-  -                         -     -     -      sdp_station_id                            0x0006e012       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      sdp_observation_id                        0x0006e013       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      sdp_version_id                            0x0006e014       1     RO       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      sdp_marker                                0x0006e015       1     RO       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      udp_checksum                              0x0006e016       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      udp_length                                0x0006e017       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      udp_destination_port                      0x0006e018       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      udp_source_port                           0x0006e019       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_destination_address                    0x0006e01a       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      ip_source_address                         0x0006e01b       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      ip_header_checksum                        0x0006e01c       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_protocol                               0x0006e01d       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      ip_time_to_live                           0x0006e01e       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      ip_fragment_offset                        0x0006e01f       1     RW       uint32     b[12:0]           -  -      -    
-  -                         -     -     -      ip_flags                                  0x0006e020       1     RW       uint32      b[2:0]           -  -      -    
-  -                         -     -     -      ip_identification                         0x0006e021       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_total_length                           0x0006e022       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      ip_services                               0x0006e023       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      ip_header_length                          0x0006e024       1     RW       uint32      b[3:0]           -  -      -    
-  -                         -     -     -      ip_version                                0x0006e025       1     RW       uint32      b[3:0]           -  -      -    
-  -                         -     -     -      eth_type                                  0x0006e026       1     RO       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      eth_source_mac                            0x0006e027       1     RO       uint64     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      -                                         0x0006e028       -      -            -     b[15:0]    b[47:32]  -      -    
-  -                         -     -     -      eth_destination_mac                       0x0006e029       1     RW       uint64     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      -                                         0x0006e02a       -      -            -     b[15:0]    b[47:32]  -      -    
-  -                         -     -     -      word_align                                0x0006e02b       1     RW       uint32     b[15:0]           -  -      -    
-  REG_NW_10GBE_MAC          1     1     REG    rx_transfer_control                       0x00070000       1     RW       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      rx_transfer_status                        0x00070001       1     RO       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      tx_transfer_control                       0x00070002       1     RW       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      rx_padcrc_control                         0x00070040       1     RW       uint32      b[1:0]           -  -      -    
-  -                         -     -     -      rx_crccheck_control                       0x00070080       1     RW       uint32      b[1:0]           -  -      -    
-  -                         -     -     -      rx_pktovrflow_error                       0x000700c0       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x000700c1       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_pktovrflow_etherstatsdropevents        0x000700c2       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x000700c3       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_lane_decoder_preamble_control          0x00070100       1     RW       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      rx_preamble_inserter_control              0x00070140       1     RW       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      rx_frame_control                          0x00070800       1     RW       uint32     b[19:0]           -  -      -    
-  -                         -     -     -      rx_frame_maxlength                        0x00070801       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      rx_frame_addr0                            0x00070802       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      rx_frame_addr1                            0x00070803       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      rx_frame_spaddr0_0                        0x00070804       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      rx_frame_spaddr0_1                        0x00070805       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      rx_frame_spaddr1_0                        0x00070806       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      rx_frame_spaddr1_1                        0x00070807       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      rx_frame_spaddr2_0                        0x00070808       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      rx_frame_spaddr2_1                        0x00070809       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      rx_frame_spaddr3_0                        0x0007080a       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      rx_frame_spaddr3_1                        0x0007080b       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      rx_pfc_control                            0x00070818       1     RW       uint32     b[16:0]           -  -      -    
-  -                         -     -     -      rx_stats_clr                              0x00070c00       1     RW       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      rx_stats_framesok                         0x00070c02       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c03       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_frameserr                        0x00070c04       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c05       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_framescrcerr                     0x00070c06       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c07       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_octetsok                         0x00070c08       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c09       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_pausemacctrl_frames              0x00070c0a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c0b       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_iferrors                         0x00070c0c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c0d       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_unicast_framesok                 0x00070c0e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c0f       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_unicast_frameserr                0x00070c10       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c11       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_multicastframesok                0x00070c12       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c13       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_multicast_frameserr              0x00070c14       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c15       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_broadcastframesok                0x00070c16       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c17       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_broadcast_frameserr              0x00070c18       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c19       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstatsoctets                 0x00070c1a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c1b       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstatspkts                   0x00070c1c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c1d       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstats_undersizepkts         0x00070c1e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c1f       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstats_oversizepkts          0x00070c20       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c21       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstats_pkts64octets          0x00070c22       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c23       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstats_pkts65to127octets     0x00070c24       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c25       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstats_pkts128to255octets    0x00070c26       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c27       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstats_pkts256to511octets    0x00070c28       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c29       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstats_pkts512to1023octets   0x00070c2a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c2b       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstat_pkts1024to1518octets   0x00070c2c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c2d       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstats_pkts1519toxoctets     0x00070c2e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c2f       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstats_fragments             0x00070c30       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c31       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstats_jabbers               0x00070c32       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c33       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_etherstatscrcerr                 0x00070c34       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c35       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_unicastmacctrlframes             0x00070c36       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c37       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_multicastmac_ctrlframes          0x00070c38       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c39       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_broadcastmac_ctrlframes          0x00070c3a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c3b       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      rx_stats_pfcmacctrlframes                 0x00070c3c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00070c3d       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_transfer_status                        0x00071001       1     RO       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      tx_padins_control                         0x00071040       1     RW       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      tx_crcins_control                         0x00071080       1     RW       uint32      b[1:0]           -  -      -    
-  -                         -     -     -      tx_pktunderflow_error                     0x000710c0       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x000710c1       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_preamble_control                       0x00071100       1     RW       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      tx_pauseframe_control                     0x00071140       1     RW       uint32      b[1:0]           -  -      -    
-  -                         -     -     -      tx_pauseframe_quanta                      0x00071141       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      tx_pauseframe_enable                      0x00071142       1     RW       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      pfc_pause_quanta_0                        0x00071180       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_pause_quanta_1                        0x00071181       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_pause_quanta_2                        0x00071182       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_pause_quanta_3                        0x00071183       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_pause_quanta_4                        0x00071184       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_pause_quanta_5                        0x00071185       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_pause_quanta_6                        0x00071186       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_pause_quanta_7                        0x00071187       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_holdoff_quanta_0                      0x00071190       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_holdoff_quanta_1                      0x00071191       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_holdoff_quanta_2                      0x00071192       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_holdoff_quanta_3                      0x00071193       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_holdoff_quanta_4                      0x00071194       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_holdoff_quanta_5                      0x00071195       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_holdoff_quanta_6                      0x00071196       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      pfc_holdoff_quanta_7                      0x00071197       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      tx_pfc_priority_enable                    0x000711a0       1     RW       uint32      b[7:0]           -  -      -    
-  -                         -     -     -      tx_addrins_control                        0x00071200       1     RW       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      tx_addrins_macaddr0                       0x00071201       1     RW       uint32     b[31:0]           -  -      -    
-  -                         -     -     -      tx_addrins_macaddr1                       0x00071202       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      tx_frame_maxlength                        0x00071801       1     RW       uint32     b[15:0]           -  -      -    
-  -                         -     -     -      tx_stats_clr                              0x00071c00       1     RW       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      tx_stats_framesok                         0x00071c02       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c03       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_frameserr                        0x00071c04       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c05       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_framescrcerr                     0x00071c06       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c07       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_octetsok                         0x00071c08       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c09       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_pausemacctrl_frames              0x00071c0a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c0b       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_iferrors                         0x00071c0c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c0d       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_unicast_framesok                 0x00071c0e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c0f       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_unicast_frameserr                0x00071c10       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c11       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_multicastframesok                0x00071c12       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c13       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_multicast_frameserr              0x00071c14       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c15       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_broadcastframesok                0x00071c16       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c17       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_broadcast_frameserr              0x00071c18       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c19       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstatsoctets                 0x00071c1a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c1b       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstatspkts                   0x00071c1c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c1d       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstats_undersizepkts         0x00071c1e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c1f       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstats_oversizepkts          0x00071c20       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c21       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstats_pkts64octets          0x00071c22       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c23       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstats_pkts65to127octets     0x00071c24       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c25       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstats_pkts128to255octets    0x00071c26       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c27       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstats_pkts256to511octets    0x00071c28       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c29       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstats_pkts512to1023octets   0x00071c2a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c2b       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstat_pkts1024to1518octets   0x00071c2c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c2d       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstats_pkts1519toxoctets     0x00071c2e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c2f       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstats_fragments             0x00071c30       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c31       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstats_jabbers               0x00071c32       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c33       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_etherstatscrcerr                 0x00071c34       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c35       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_unicastmacctrlframes             0x00071c36       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c37       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_multicastmac_ctrlframes          0x00071c38       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c39       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_broadcastmac_ctrlframes          0x00071c3a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c3b       -      -            -     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      tx_stats_pfcmacctrlframes                 0x00071c3c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
-  -                         -     -     -      -                                         0x00071c3d       -      -            -     b[31:0]     b[31:0]  -      -    
-  REG_NW_10GBE_ETH10G       1     1     REG    tx_snk_out_xon                            0x00072000       1     RO       uint32      b[0:0]           -  -      -    
-  -                         -     -     -      xgmii_tx_ready                            0x00072000       1     RO       uint32      b[1:1]           -  -      -    
-  -                         -     -     -      xgmii_link_status                         0x00072000       1     RO       uint32      b[3:2]           -  -      -    
\ No newline at end of file
+  -                         -     -     -      sdp_source_info_beamlet_width             0x0006e00a       1     RW       uint32      b[7:5]           -  -      -    
+  -                         -     -     -      sdp_source_info_repositioning_flag        0x0006e00b       1     RW       uint32      b[9:9]           -  -      -    
+  -                         -     -     -      sdp_source_info_payload_error             0x0006e00c       1     RW       uint32    b[10:10]           -  -      -    
+  -                         -     -     -      sdp_source_info_fsub_type                 0x0006e00d       1     RW       uint32    b[11:11]           -  -      -    
+  -                         -     -     -      sdp_source_info_f_adc                     0x0006e00e       1     RW       uint32    b[12:12]           -  -      -    
+  -                         -     -     -      sdp_source_info_nyquist_zone_index        0x0006e00f       1     RW       uint32    b[14:13]           -  -      -    
+  -                         -     -     -      sdp_source_info_antenna_band_index        0x0006e010       1     RW       uint32    b[15:15]           -  -      -    
+  -                         -     -     -      sdp_station_id                            0x0006e011       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      sdp_observation_id                        0x0006e012       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      sdp_version_id                            0x0006e013       1     RO       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      sdp_marker                                0x0006e014       1     RO       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      udp_checksum                              0x0006e015       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      udp_length                                0x0006e016       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      udp_destination_port                      0x0006e017       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      udp_source_port                           0x0006e018       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_destination_address                    0x0006e019       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      ip_source_address                         0x0006e01a       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      ip_header_checksum                        0x0006e01b       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_protocol                               0x0006e01c       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      ip_time_to_live                           0x0006e01d       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      ip_fragment_offset                        0x0006e01e       1     RW       uint32     b[12:0]           -  -      -    
+  -                         -     -     -      ip_flags                                  0x0006e01f       1     RW       uint32      b[2:0]           -  -      -    
+  -                         -     -     -      ip_identification                         0x0006e020       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_total_length                           0x0006e021       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_services                               0x0006e022       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      ip_header_length                          0x0006e023       1     RW       uint32      b[3:0]           -  -      -    
+  -                         -     -     -      ip_version                                0x0006e024       1     RW       uint32      b[3:0]           -  -      -    
+  -                         -     -     -      eth_type                                  0x0006e025       1     RO       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      eth_source_mac                            0x0006e026       1     RO       uint64     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      -                                         0x0006e027       -      -            -     b[15:0]    b[47:32]  -      -    
+  -                         -     -     -      eth_destination_mac                       0x0006e028       1     RW       uint64     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      -                                         0x0006e029       -      -            -     b[15:0]    b[47:32]  -      -    
+  REG_DP_XONOFF             2     1     REG    enable_stream                             0x00070000       1     RW       uint32      b[0:0]           -  2      2    
+  RAM_ST_BST                2     1     RAM    data                                      0x00072000     976     RW       uint64     b[31:0]     b[31:0]  2048   2048 
+  -                         -     -     -      -                                         0x00072001       -      -            -     b[21:0]    b[53:32]  -      -    
+  REG_STAT_ENABLE_BST       2     1     REG    enable                                    0x00074000       1     RW       uint32      b[0:0]           -  2      2    
+  REG_STAT_HDR_DAT_BST      2     1     REG    bsn                                       0x00076000       1     RW       uint64     b[31:0]     b[31:0]  64     64   
+  -                         -     -     -      -                                         0x00076001       -      -            -     b[31:0]    b[63:32]  -      -    
+  -                         -     -     -      block_period                              0x00076002       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      nof_statistics_per_packet                 0x00076003       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      nof_bytes_per_statistic                   0x00076004       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      nof_signal_inputs                         0x00076005       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      sdp_data_id                               0x00076006       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      sdp_data_id_bst_beamlet_index             0x00076006       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      sdp_data_id_bst_reserved                  0x00076006       1     RW       uint32    b[31:16]           -  -      -    
+  -                         -     -     -      sdp_integration_interval                  0x00076007       1     RW       uint32     b[23:0]           -  -      -    
+  -                         -     -     -      sdp_reserved                              0x00076008       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      sdp_source_info_gn_index                  0x00076009       1     RW       uint32      b[4:0]           -  -      -    
+  -                         -     -     -      sdp_source_info_reserved                  0x0007600a       1     RW       uint32      b[7:5]           -  -      -    
+  -                         -     -     -      sdp_source_info_subband_calibrated_flag   0x0007600b       1     RW       uint32      b[8:8]           -  -      -    
+  -                         -     -     -      sdp_source_info_beam_repositioning_flag   0x0007600c       1     RW       uint32      b[9:9]           -  -      -    
+  -                         -     -     -      sdp_source_info_payload_error             0x0007600d       1     RW       uint32    b[10:10]           -  -      -    
+  -                         -     -     -      sdp_source_info_fsub_type                 0x0007600e       1     RW       uint32    b[11:11]           -  -      -    
+  -                         -     -     -      sdp_source_info_f_adc                     0x0007600f       1     RW       uint32    b[12:12]           -  -      -    
+  -                         -     -     -      sdp_source_info_nyquist_zone_index        0x00076010       1     RW       uint32    b[14:13]           -  -      -    
+  -                         -     -     -      sdp_source_info_antenna_band_index        0x00076011       1     RW       uint32    b[15:15]           -  -      -    
+  -                         -     -     -      sdp_station_id                            0x00076012       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      sdp_observation_id                        0x00076013       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      sdp_version_id                            0x00076014       1     RO       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      sdp_marker                                0x00076015       1     RO       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      udp_checksum                              0x00076016       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      udp_length                                0x00076017       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      udp_destination_port                      0x00076018       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      udp_source_port                           0x00076019       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_destination_address                    0x0007601a       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      ip_source_address                         0x0007601b       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      ip_header_checksum                        0x0007601c       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_protocol                               0x0007601d       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      ip_time_to_live                           0x0007601e       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      ip_fragment_offset                        0x0007601f       1     RW       uint32     b[12:0]           -  -      -    
+  -                         -     -     -      ip_flags                                  0x00076020       1     RW       uint32      b[2:0]           -  -      -    
+  -                         -     -     -      ip_identification                         0x00076021       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_total_length                           0x00076022       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      ip_services                               0x00076023       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      ip_header_length                          0x00076024       1     RW       uint32      b[3:0]           -  -      -    
+  -                         -     -     -      ip_version                                0x00076025       1     RW       uint32      b[3:0]           -  -      -    
+  -                         -     -     -      eth_type                                  0x00076026       1     RO       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      eth_source_mac                            0x00076027       1     RO       uint64     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      -                                         0x00076028       -      -            -     b[15:0]    b[47:32]  -      -    
+  -                         -     -     -      eth_destination_mac                       0x00076029       1     RW       uint64     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      -                                         0x0007602a       -      -            -     b[15:0]    b[47:32]  -      -    
+  -                         -     -     -      word_align                                0x0007602b       1     RW       uint32     b[15:0]           -  -      -    
+  REG_NW_10GBE_MAC          1     1     REG    rx_transfer_control                       0x00078000       1     RW       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      rx_transfer_status                        0x00078001       1     RO       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      tx_transfer_control                       0x00078002       1     RW       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      rx_padcrc_control                         0x00078040       1     RW       uint32      b[1:0]           -  -      -    
+  -                         -     -     -      rx_crccheck_control                       0x00078080       1     RW       uint32      b[1:0]           -  -      -    
+  -                         -     -     -      rx_pktovrflow_error                       0x000780c0       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x000780c1       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_pktovrflow_etherstatsdropevents        0x000780c2       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x000780c3       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_lane_decoder_preamble_control          0x00078100       1     RW       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      rx_preamble_inserter_control              0x00078140       1     RW       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      rx_frame_control                          0x00078800       1     RW       uint32     b[19:0]           -  -      -    
+  -                         -     -     -      rx_frame_maxlength                        0x00078801       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      rx_frame_addr0                            0x00078802       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      rx_frame_addr1                            0x00078803       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      rx_frame_spaddr0_0                        0x00078804       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      rx_frame_spaddr0_1                        0x00078805       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      rx_frame_spaddr1_0                        0x00078806       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      rx_frame_spaddr1_1                        0x00078807       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      rx_frame_spaddr2_0                        0x00078808       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      rx_frame_spaddr2_1                        0x00078809       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      rx_frame_spaddr3_0                        0x0007880a       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      rx_frame_spaddr3_1                        0x0007880b       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      rx_pfc_control                            0x00078818       1     RW       uint32     b[16:0]           -  -      -    
+  -                         -     -     -      rx_stats_clr                              0x00078c00       1     RW       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      rx_stats_framesok                         0x00078c02       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c03       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_frameserr                        0x00078c04       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c05       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_framescrcerr                     0x00078c06       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c07       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_octetsok                         0x00078c08       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c09       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_pausemacctrl_frames              0x00078c0a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c0b       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_iferrors                         0x00078c0c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c0d       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_unicast_framesok                 0x00078c0e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c0f       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_unicast_frameserr                0x00078c10       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c11       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_multicastframesok                0x00078c12       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c13       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_multicast_frameserr              0x00078c14       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c15       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_broadcastframesok                0x00078c16       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c17       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_broadcast_frameserr              0x00078c18       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c19       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstatsoctets                 0x00078c1a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c1b       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstatspkts                   0x00078c1c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c1d       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstats_undersizepkts         0x00078c1e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c1f       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstats_oversizepkts          0x00078c20       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c21       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstats_pkts64octets          0x00078c22       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c23       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstats_pkts65to127octets     0x00078c24       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c25       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstats_pkts128to255octets    0x00078c26       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c27       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstats_pkts256to511octets    0x00078c28       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c29       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstats_pkts512to1023octets   0x00078c2a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c2b       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstat_pkts1024to1518octets   0x00078c2c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c2d       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstats_pkts1519toxoctets     0x00078c2e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c2f       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstats_fragments             0x00078c30       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c31       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstats_jabbers               0x00078c32       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c33       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_etherstatscrcerr                 0x00078c34       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c35       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_unicastmacctrlframes             0x00078c36       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c37       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_multicastmac_ctrlframes          0x00078c38       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c39       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_broadcastmac_ctrlframes          0x00078c3a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c3b       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      rx_stats_pfcmacctrlframes                 0x00078c3c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00078c3d       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_transfer_status                        0x00079001       1     RO       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      tx_padins_control                         0x00079040       1     RW       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      tx_crcins_control                         0x00079080       1     RW       uint32      b[1:0]           -  -      -    
+  -                         -     -     -      tx_pktunderflow_error                     0x000790c0       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x000790c1       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_preamble_control                       0x00079100       1     RW       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      tx_pauseframe_control                     0x00079140       1     RW       uint32      b[1:0]           -  -      -    
+  -                         -     -     -      tx_pauseframe_quanta                      0x00079141       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      tx_pauseframe_enable                      0x00079142       1     RW       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      pfc_pause_quanta_0                        0x00079180       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_pause_quanta_1                        0x00079181       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_pause_quanta_2                        0x00079182       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_pause_quanta_3                        0x00079183       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_pause_quanta_4                        0x00079184       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_pause_quanta_5                        0x00079185       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_pause_quanta_6                        0x00079186       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_pause_quanta_7                        0x00079187       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_holdoff_quanta_0                      0x00079190       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_holdoff_quanta_1                      0x00079191       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_holdoff_quanta_2                      0x00079192       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_holdoff_quanta_3                      0x00079193       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_holdoff_quanta_4                      0x00079194       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_holdoff_quanta_5                      0x00079195       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_holdoff_quanta_6                      0x00079196       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      pfc_holdoff_quanta_7                      0x00079197       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      tx_pfc_priority_enable                    0x000791a0       1     RW       uint32      b[7:0]           -  -      -    
+  -                         -     -     -      tx_addrins_control                        0x00079200       1     RW       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      tx_addrins_macaddr0                       0x00079201       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      tx_addrins_macaddr1                       0x00079202       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      tx_frame_maxlength                        0x00079801       1     RW       uint32     b[15:0]           -  -      -    
+  -                         -     -     -      tx_stats_clr                              0x00079c00       1     RW       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      tx_stats_framesok                         0x00079c02       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c03       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_frameserr                        0x00079c04       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c05       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_framescrcerr                     0x00079c06       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c07       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_octetsok                         0x00079c08       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c09       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_pausemacctrl_frames              0x00079c0a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c0b       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_iferrors                         0x00079c0c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c0d       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_unicast_framesok                 0x00079c0e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c0f       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_unicast_frameserr                0x00079c10       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c11       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_multicastframesok                0x00079c12       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c13       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_multicast_frameserr              0x00079c14       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c15       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_broadcastframesok                0x00079c16       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c17       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_broadcast_frameserr              0x00079c18       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c19       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstatsoctets                 0x00079c1a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c1b       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstatspkts                   0x00079c1c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c1d       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstats_undersizepkts         0x00079c1e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c1f       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstats_oversizepkts          0x00079c20       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c21       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstats_pkts64octets          0x00079c22       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c23       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstats_pkts65to127octets     0x00079c24       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c25       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstats_pkts128to255octets    0x00079c26       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c27       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstats_pkts256to511octets    0x00079c28       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c29       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstats_pkts512to1023octets   0x00079c2a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c2b       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstat_pkts1024to1518octets   0x00079c2c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c2d       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstats_pkts1519toxoctets     0x00079c2e       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c2f       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstats_fragments             0x00079c30       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c31       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstats_jabbers               0x00079c32       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c33       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_etherstatscrcerr                 0x00079c34       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c35       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_unicastmacctrlframes             0x00079c36       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c37       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_multicastmac_ctrlframes          0x00079c38       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c39       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_broadcastmac_ctrlframes          0x00079c3a       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c3b       -      -            -     b[31:0]     b[31:0]  -      -    
+  -                         -     -     -      tx_stats_pfcmacctrlframes                 0x00079c3c       1     RO       uint64      b[3:0]    b[35:32]  -      -    
+  -                         -     -     -      -                                         0x00079c3d       -      -            -     b[31:0]     b[31:0]  -      -    
+  REG_NW_10GBE_ETH10G       1     1     REG    tx_snk_out_xon                            0x0007a000       1     RO       uint32      b[0:0]           -  -      -    
+  -                         -     -     -      xgmii_tx_ready                            0x0007a000       1     RO       uint32      b[1:1]           -  -      -    
+  -                         -     -     -      xgmii_link_status                         0x0007a000       1     RO       uint32      b[3:2]           -  -      -    
\ No newline at end of file
diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.mmap.qsys.gold b/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.mmap.qsys.gold
index 6bc74963e33c556015d97fcc7dd158abb2b125be..bf8da8d17ff91054e84c11791953f980112008f7 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.mmap.qsys.gold
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.mmap.qsys.gold
@@ -112,7 +112,7 @@ number_of_columns = 13
   REG_DP_SHIFTRAM           1     12    REG    shift                                     0x00000c20       1     RW       uint32     b[11:0]           -  -      2    
   REG_BSN_SOURCE_V2         1     1     REG    dp_on                                     0x0002d030       1     RW       uint32      b[0:0]           -  -      -    
   -                         -     -     -      dp_on_pps                                 0x0002d030       1     RW       uint32      b[1:1]           -  -      -    
-  -                         -     -     -      nof_block_per_sync                        0x0002d031       1     RW       uint32     b[31:0]           -  -      -    
+  -                         -     -     -      nof_clk_per_sync                          0x0002d031       1     RW       uint32     b[31:0]           -  -      -    
   -                         -     -     -      bsn_init                                  0x0002d032       1     RW       uint64     b[31:0]     b[31:0]  -      -    
   -                         -     -     -      -                                         0x0002d033       -      -            -     b[31:0]    b[63:32]  -      -    
   -                         -     -     -      bsn_time_offset                           0x0002d034       1     RW       uint32      b[9:0]           -  -      -    
@@ -146,8 +146,8 @@ number_of_columns = 13
   RAM_FIL_COEFS             1     16    RAM    data                                      0x00024000    1024     RW       uint32     b[15:0]           -  -      1024 
   RAM_EQUALIZER_GAINS       1     6     RAM    data                                      0x00006000    1024     RW    cint16_ir     b[31:0]           -  -      1024 
   REG_DP_SELECTOR           1     1     REG    input_select                              0x0002d066       1     RW       uint32      b[0:0]           -  -      -    
-  RAM_ST_SST                1     6     RAM    data                                      0x00028000    2048     RW       uint64     b[31:0]     b[31:0]  -      2048 
-  -                         -     -     -      -                                         0x0002d067       -      -            -     b[21:0]    b[53:32]  -      -    
+  RAM_ST_SST                1     6     RAM    data                                      0x00028000    1024     RW       uint64     b[31:0]     b[31:0]  -      2048 
+  -                         -     -     -      -                                         0x00028001       -      -            -     b[21:0]    b[53:32]  -      -    
   REG_STAT_ENABLE_SST       1     1     REG    enable                                    0x0002d060       1     RW       uint32      b[0:0]           -  -      -    
   REG_STAT_HDR_DAT_SST      1     1     REG    bsn                                       0x00000c40       1     RW       uint64     b[31:0]     b[31:0]  -      -    
   -                         -     -     -      -                                         0x00000c41       -      -            -     b[31:0]    b[63:32]  -      -    
@@ -198,8 +198,8 @@ number_of_columns = 13
   REG_BSN_SCHEDULER_XSUB    1     1     REG    scheduled_bsn                             0x0002d05c       1     RW       uint64     b[31:0]     b[31:0]  -      -    
   -                         -     -     -      -                                         0x0002d05d       -      -            -     b[31:0]    b[63:32]  -      -    
   REG_DP_SYNC_INSERT_V2     1     1     REG    nof_blk_per_sync                          0x0002d05e       1     RW       uint32     b[31:0]           -  -      -    
-  RAM_ST_XSQ                1     1     RAM    data                                      0x00018000     576     RW    cint64_ir     b[31:0]     b[31:0]  -      -    
-  -                         -     -     -      -                                         0x0002d05f       -      -            -     b[31:0]    b[63:32]  -      -    
+  RAM_ST_XSQ                1     9     RAM    data                                      0x00018000     144     RW    cint64_ir     b[31:0]     b[31:0]  -      1028 
+  -                         -     -     -      -                                         0x00018001       -      -            -     b[31:0]    b[63:32]  -      -    
   REG_CROSSLETS_INFO        1     1     REG    offset                                    0x0002d000      15     RW       uint32     b[31:0]           -  -      -    
   -                         -     -     -      step                                      0x0002d00f       1     RW       uint32     b[31:0]           -  -      -    
   REG_STAT_ENABLE_XST       1     1     REG    enable                                    0x00000c02       1     RW       uint32      b[0:0]           -  -      -    
@@ -298,8 +298,8 @@ number_of_columns = 13
   -                         -     -     -      eth_destination_mac                       0x00000ca8       1     RW       uint64     b[31:0]     b[31:0]  -      -    
   -                         -     -     -      -                                         0x00000ca9       -      -            -     b[15:0]    b[47:32]  -      -    
   REG_DP_XONOFF             2     1     REG    enable_stream                             0x0002d054       1     RW       uint32      b[0:0]           -  2      2    
-  RAM_ST_BST                2     1     RAM    data                                      0x00001000    1952     RW       uint64     b[31:0]     b[31:0]  2048   2048 
-  -                         -     -     -      -                                         0x0002d055       -      -            -     b[21:0]    b[53:32]  -      -    
+  RAM_ST_BST                2     1     RAM    data                                      0x00001000     976     RW       uint64     b[31:0]     b[31:0]  2048   2048 
+  -                         -     -     -      -                                         0x00001001       -      -            -     b[21:0]    b[53:32]  -      -    
   REG_STAT_ENABLE_BST       2     1     REG    enable                                    0x0002d050       1     RW       uint32      b[0:0]           -  2      2    
   REG_STAT_HDR_DAT_BST      2     1     REG    bsn                                       0x00000080       1     RW       uint64     b[31:0]     b[31:0]  64     64   
   -                         -     -     -      -                                         0x00000081       -      -            -     b[31:0]    b[63:32]  -      -    
diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/quartus/qsys_lofar2_unb2b_sdp_station.qsys b/applications/lofar2/designs/lofar2_unb2b_sdp_station/quartus/qsys_lofar2_unb2b_sdp_station.qsys
index dc294ad5df439e9258503f0955bda54f6310c130..d6f321e7ef38e0d597aceea0693177e2c39b7e8e 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/quartus/qsys_lofar2_unb2b_sdp_station.qsys
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/quartus/qsys_lofar2_unb2b_sdp_station.qsys
@@ -99,7 +99,7 @@
    {
       datum baseAddress
       {
-         value = "737752";
+         value = "737760";
          type = "String";
       }
    }
@@ -144,7 +144,7 @@
    {
       datum baseAddress
       {
-         value = "737672";
+         value = "737688";
          type = "String";
       }
    }
@@ -157,7 +157,7 @@
       }
       datum sopceditor_expanded
       {
-         value = "0";
+         value = "1";
          type = "boolean";
       }
    }
@@ -165,7 +165,7 @@
    {
       datum baseAddress
       {
-         value = "737744";
+         value = "737648";
          type = "String";
       }
    }
@@ -426,7 +426,7 @@
    {
       datum baseAddress
       {
-         value = "737696";
+         value = "737712";
          type = "String";
       }
    }
@@ -442,7 +442,7 @@
    {
       datum baseAddress
       {
-         value = "737648";
+         value = "737664";
          type = "String";
       }
    }
@@ -506,7 +506,7 @@
    {
       datum baseAddress
       {
-         value = "737688";
+         value = "737704";
          type = "String";
       }
    }
@@ -538,7 +538,7 @@
    {
       datum baseAddress
       {
-         value = "737656";
+         value = "737672";
          type = "String";
       }
    }
@@ -575,7 +575,7 @@
    {
       datum baseAddress
       {
-         value = "737736";
+         value = "737752";
          type = "String";
       }
    }
@@ -596,7 +596,7 @@
    {
       datum baseAddress
       {
-         value = "737728";
+         value = "737744";
          type = "String";
       }
    }
@@ -691,7 +691,7 @@
    {
       datum baseAddress
       {
-         value = "737720";
+         value = "737736";
          type = "String";
       }
    }
@@ -712,7 +712,7 @@
    {
       datum baseAddress
       {
-         value = "737712";
+         value = "737728";
          type = "String";
       }
    }
@@ -728,7 +728,7 @@
    {
       datum baseAddress
       {
-         value = "737680";
+         value = "737696";
          type = "String";
       }
    }
@@ -797,7 +797,7 @@
    {
       datum baseAddress
       {
-         value = "737704";
+         value = "737720";
          type = "String";
       }
    }
@@ -829,7 +829,7 @@
    {
       datum baseAddress
       {
-         value = "737664";
+         value = "737680";
          type = "String";
       }
    }
@@ -1291,11 +1291,6 @@
    internal="pio_wdi.external_connection"
    type="conduit"
    dir="end" />
- <interface
-   name="reg_stat_hdr_dat_xst_readdata"
-   internal="reg_stat_hdr_dat_xst.readdata"
-   type="conduit"
-   dir="end" />
  <interface
    name="ram_bf_weights_address"
    internal="ram_bf_weights.address"
@@ -2671,6 +2666,11 @@
    internal="reg_stat_hdr_dat_xst.read"
    type="conduit"
    dir="end" />
+ <interface
+   name="reg_stat_hdr_dat_xst_readdata"
+   internal="reg_stat_hdr_dat_xst.readdata"
+   type="conduit"
+   dir="end" />
  <interface
    name="reg_stat_hdr_dat_xst_reset"
    internal="reg_stat_hdr_dat_xst.reset"
@@ -5805,7 +5805,7 @@
                     <consumedSystemInfos>
                         <entry>
                             <key>ADDRESS_MAP</key>
-                            <value>&lt;address-map&gt;&lt;slave name='pio_system_info.mem' start='0x0' end='0x80' datawidth='32' /&gt;&lt;slave name='reg_diag_data_buffer_bsn.mem' start='0x80' end='0x100' datawidth='32' /&gt;&lt;slave name='reg_stat_hdr_dat_xst.mem' start='0x100' end='0x200' datawidth='32' /&gt;&lt;slave name='reg_stat_hdr_dat_bst.mem' start='0x200' end='0x400' datawidth='32' /&gt;&lt;slave name='reg_bsn_monitor_input.mem' start='0x400' end='0x800' datawidth='32' /&gt;&lt;slave name='ram_scrap.mem' start='0x800' end='0x1000' datawidth='32' /&gt;&lt;slave name='avs_eth_0.mms_tse' start='0x1000' end='0x2000' datawidth='32' /&gt;&lt;slave name='avs_eth_0.mms_ram' start='0x2000' end='0x3000' datawidth='32' /&gt;&lt;slave name='reg_wdi.mem' start='0x3000' end='0x3008' datawidth='32' /&gt;&lt;slave name='reg_stat_enable_xst.mem' start='0x3008' end='0x3010' datawidth='32' /&gt;&lt;slave name='pio_wdi.s1' start='0x3010' end='0x3020' datawidth='32' /&gt;&lt;slave name='timer_0.s1' start='0x3020' end='0x3040' datawidth='16' /&gt;&lt;slave name='avs_eth_0.mms_reg' start='0x3040' end='0x3080' datawidth='32' /&gt;&lt;slave name='reg_dp_shiftram.mem' start='0x3080' end='0x3100' datawidth='32' /&gt;&lt;slave name='reg_stat_hdr_dat_sst.mem' start='0x3100' end='0x3200' datawidth='32' /&gt;&lt;slave name='reg_hdr_dat.mem' start='0x3200' end='0x3400' datawidth='32' /&gt;&lt;slave name='reg_wg.mem' start='0x3400' end='0x3500' datawidth='32' /&gt;&lt;slave name='reg_aduh_monitor.mem' start='0x3500' end='0x3600' datawidth='32' /&gt;&lt;slave name='reg_unb_pmbus.mem' start='0x3600' end='0x3700' datawidth='32' /&gt;&lt;slave name='reg_unb_sens.mem' start='0x3700' end='0x3800' datawidth='32' /&gt;&lt;slave name='cpu_0.debug_mem_slave' start='0x3800' end='0x4000' datawidth='32' /&gt;&lt;slave name='ram_st_bst.mem' start='0x4000' end='0x8000' datawidth='32' /&gt;&lt;slave name='reg_nw_10gbe_mac.mem' start='0x8000' end='0x10000' datawidth='32' /&gt;&lt;slave name='rom_system_info.mem' start='0x10000' end='0x18000' datawidth='32' /&gt;&lt;slave name='ram_equalizer_gains.mem' start='0x18000' end='0x20000' datawidth='32' /&gt;&lt;slave name='onchip_memory2_0.s1' start='0x20000' end='0x40000' datawidth='32' /&gt;&lt;slave name='ram_bf_weights.mem' start='0x40000' end='0x60000' datawidth='32' /&gt;&lt;slave name='ram_st_xsq.mem' start='0x60000' end='0x70000' datawidth='32' /&gt;&lt;slave name='ram_ss_ss_wide.mem' start='0x70000' end='0x80000' datawidth='32' /&gt;&lt;slave name='ram_wg.mem' start='0x80000' end='0x90000' datawidth='32' /&gt;&lt;slave name='ram_fil_coefs.mem' start='0x90000' end='0xA0000' datawidth='32' /&gt;&lt;slave name='ram_st_sst.mem' start='0xA0000' end='0xB0000' datawidth='32' /&gt;&lt;slave name='jesd204b.mem' start='0xB0000' end='0xB4000' datawidth='32' /&gt;&lt;slave name='reg_crosslets_info.mem' start='0xB4000' end='0xB4040' datawidth='32' /&gt;&lt;slave name='reg_sdp_info.mem' start='0xB4040' end='0xB4080' datawidth='32' /&gt;&lt;slave name='reg_fpga_voltage_sens.mem' start='0xB4080' end='0xB40C0' datawidth='32' /&gt;&lt;slave name='reg_bsn_source_v2.mem' start='0xB40C0' end='0xB40E0' datawidth='32' /&gt;&lt;slave name='reg_fpga_temp_sens.mem' start='0xB40E0' end='0xB4100' datawidth='32' /&gt;&lt;slave name='reg_epcs.mem' start='0xB4100' end='0xB4120' datawidth='32' /&gt;&lt;slave name='reg_remu.mem' start='0xB4120' end='0xB4140' datawidth='32' /&gt;&lt;slave name='reg_stat_enable_bst.mem' start='0xB4140' end='0xB4150' datawidth='32' /&gt;&lt;slave name='reg_dp_xonoff.mem' start='0xB4150' end='0xB4160' datawidth='32' /&gt;&lt;slave name='reg_bf_scale.mem' start='0xB4160' end='0xB4170' datawidth='32' /&gt;&lt;slave name='reg_bsn_scheduler_xsub.mem' start='0xB4170' end='0xB4178' datawidth='32' /&gt;&lt;slave name='reg_dp_sync_insert_v2.mem' start='0xB4178' end='0xB4180' datawidth='32' /&gt;&lt;slave name='reg_stat_enable_sst.mem' start='0xB4180' end='0xB4188' datawidth='32' /&gt;&lt;slave name='pio_jesd_ctrl.mem' start='0xB4188' end='0xB4190' datawidth='32' /&gt;&lt;slave name='reg_nw_10gbe_eth10g.mem' start='0xB4190' end='0xB4198' datawidth='32' /&gt;&lt;slave name='reg_dp_selector.mem' start='0xB4198' end='0xB41A0' datawidth='32' /&gt;&lt;slave name='reg_bsn_scheduler.mem' start='0xB41A0' end='0xB41A8' datawidth='32' /&gt;&lt;slave name='reg_si.mem' start='0xB41A8' end='0xB41B0' datawidth='32' /&gt;&lt;slave name='reg_mmdp_data.mem' start='0xB41B0' end='0xB41B8' datawidth='32' /&gt;&lt;slave name='reg_mmdp_ctrl.mem' start='0xB41B8' end='0xB41C0' datawidth='32' /&gt;&lt;slave name='reg_dpmm_data.mem' start='0xB41C0' end='0xB41C8' datawidth='32' /&gt;&lt;slave name='reg_dpmm_ctrl.mem' start='0xB41C8' end='0xB41D0' datawidth='32' /&gt;&lt;slave name='pio_pps.mem' start='0xB41D0' end='0xB41D8' datawidth='32' /&gt;&lt;slave name='jtag_uart_0.avalon_jtag_slave' start='0xB41D8' end='0xB41E0' datawidth='32' /&gt;&lt;slave name='ram_diag_data_buffer_bsn.mem' start='0x800000' end='0x1000000' datawidth='32' /&gt;&lt;/address-map&gt;</value>
+                            <value>&lt;address-map&gt;&lt;slave name='pio_system_info.mem' start='0x0' end='0x80' datawidth='32' /&gt;&lt;slave name='reg_diag_data_buffer_bsn.mem' start='0x80' end='0x100' datawidth='32' /&gt;&lt;slave name='reg_stat_hdr_dat_xst.mem' start='0x100' end='0x200' datawidth='32' /&gt;&lt;slave name='reg_stat_hdr_dat_bst.mem' start='0x200' end='0x400' datawidth='32' /&gt;&lt;slave name='reg_bsn_monitor_input.mem' start='0x400' end='0x800' datawidth='32' /&gt;&lt;slave name='ram_scrap.mem' start='0x800' end='0x1000' datawidth='32' /&gt;&lt;slave name='avs_eth_0.mms_tse' start='0x1000' end='0x2000' datawidth='32' /&gt;&lt;slave name='avs_eth_0.mms_ram' start='0x2000' end='0x3000' datawidth='32' /&gt;&lt;slave name='reg_wdi.mem' start='0x3000' end='0x3008' datawidth='32' /&gt;&lt;slave name='reg_stat_enable_xst.mem' start='0x3008' end='0x3010' datawidth='32' /&gt;&lt;slave name='pio_wdi.s1' start='0x3010' end='0x3020' datawidth='32' /&gt;&lt;slave name='timer_0.s1' start='0x3020' end='0x3040' datawidth='16' /&gt;&lt;slave name='avs_eth_0.mms_reg' start='0x3040' end='0x3080' datawidth='32' /&gt;&lt;slave name='reg_dp_shiftram.mem' start='0x3080' end='0x3100' datawidth='32' /&gt;&lt;slave name='reg_stat_hdr_dat_sst.mem' start='0x3100' end='0x3200' datawidth='32' /&gt;&lt;slave name='reg_hdr_dat.mem' start='0x3200' end='0x3400' datawidth='32' /&gt;&lt;slave name='reg_wg.mem' start='0x3400' end='0x3500' datawidth='32' /&gt;&lt;slave name='reg_aduh_monitor.mem' start='0x3500' end='0x3600' datawidth='32' /&gt;&lt;slave name='reg_unb_pmbus.mem' start='0x3600' end='0x3700' datawidth='32' /&gt;&lt;slave name='reg_unb_sens.mem' start='0x3700' end='0x3800' datawidth='32' /&gt;&lt;slave name='cpu_0.debug_mem_slave' start='0x3800' end='0x4000' datawidth='32' /&gt;&lt;slave name='ram_st_bst.mem' start='0x4000' end='0x8000' datawidth='32' /&gt;&lt;slave name='reg_nw_10gbe_mac.mem' start='0x8000' end='0x10000' datawidth='32' /&gt;&lt;slave name='rom_system_info.mem' start='0x10000' end='0x18000' datawidth='32' /&gt;&lt;slave name='ram_equalizer_gains.mem' start='0x18000' end='0x20000' datawidth='32' /&gt;&lt;slave name='onchip_memory2_0.s1' start='0x20000' end='0x40000' datawidth='32' /&gt;&lt;slave name='ram_bf_weights.mem' start='0x40000' end='0x60000' datawidth='32' /&gt;&lt;slave name='ram_st_xsq.mem' start='0x60000' end='0x70000' datawidth='32' /&gt;&lt;slave name='ram_ss_ss_wide.mem' start='0x70000' end='0x80000' datawidth='32' /&gt;&lt;slave name='ram_wg.mem' start='0x80000' end='0x90000' datawidth='32' /&gt;&lt;slave name='ram_fil_coefs.mem' start='0x90000' end='0xA0000' datawidth='32' /&gt;&lt;slave name='ram_st_sst.mem' start='0xA0000' end='0xB0000' datawidth='32' /&gt;&lt;slave name='jesd204b.mem' start='0xB0000' end='0xB4000' datawidth='32' /&gt;&lt;slave name='reg_crosslets_info.mem' start='0xB4000' end='0xB4040' datawidth='32' /&gt;&lt;slave name='reg_sdp_info.mem' start='0xB4040' end='0xB4080' datawidth='32' /&gt;&lt;slave name='reg_fpga_voltage_sens.mem' start='0xB4080' end='0xB40C0' datawidth='32' /&gt;&lt;slave name='reg_bsn_source_v2.mem' start='0xB40C0' end='0xB40E0' datawidth='32' /&gt;&lt;slave name='reg_fpga_temp_sens.mem' start='0xB40E0' end='0xB4100' datawidth='32' /&gt;&lt;slave name='reg_epcs.mem' start='0xB4100' end='0xB4120' datawidth='32' /&gt;&lt;slave name='reg_remu.mem' start='0xB4120' end='0xB4140' datawidth='32' /&gt;&lt;slave name='reg_stat_enable_bst.mem' start='0xB4140' end='0xB4150' datawidth='32' /&gt;&lt;slave name='reg_dp_xonoff.mem' start='0xB4150' end='0xB4160' datawidth='32' /&gt;&lt;slave name='reg_bf_scale.mem' start='0xB4160' end='0xB4170' datawidth='32' /&gt;&lt;slave name='pio_pps.mem' start='0xB4170' end='0xB4180' datawidth='32' /&gt;&lt;slave name='reg_bsn_scheduler_xsub.mem' start='0xB4180' end='0xB4188' datawidth='32' /&gt;&lt;slave name='reg_dp_sync_insert_v2.mem' start='0xB4188' end='0xB4190' datawidth='32' /&gt;&lt;slave name='reg_stat_enable_sst.mem' start='0xB4190' end='0xB4198' datawidth='32' /&gt;&lt;slave name='pio_jesd_ctrl.mem' start='0xB4198' end='0xB41A0' datawidth='32' /&gt;&lt;slave name='reg_nw_10gbe_eth10g.mem' start='0xB41A0' end='0xB41A8' datawidth='32' /&gt;&lt;slave name='reg_dp_selector.mem' start='0xB41A8' end='0xB41B0' datawidth='32' /&gt;&lt;slave name='reg_bsn_scheduler.mem' start='0xB41B0' end='0xB41B8' datawidth='32' /&gt;&lt;slave name='reg_si.mem' start='0xB41B8' end='0xB41C0' datawidth='32' /&gt;&lt;slave name='reg_mmdp_data.mem' start='0xB41C0' end='0xB41C8' datawidth='32' /&gt;&lt;slave name='reg_mmdp_ctrl.mem' start='0xB41C8' end='0xB41D0' datawidth='32' /&gt;&lt;slave name='reg_dpmm_data.mem' start='0xB41D0' end='0xB41D8' datawidth='32' /&gt;&lt;slave name='reg_dpmm_ctrl.mem' start='0xB41D8' end='0xB41E0' datawidth='32' /&gt;&lt;slave name='jtag_uart_0.avalon_jtag_slave' start='0xB41E0' end='0xB41E8' datawidth='32' /&gt;&lt;slave name='ram_diag_data_buffer_bsn.mem' start='0x800000' end='0x1000000' datawidth='32' /&gt;&lt;/address-map&gt;</value>
                         </entry>
                         <entry>
                             <key>ADDRESS_WIDTH</key>
@@ -8448,7 +8448,7 @@
                         <name>coe_address_export</name>
                         <role>export</role>
                         <direction>Output</direction>
-                        <width>1</width>
+                        <width>2</width>
                         <lowerBound>0</lowerBound>
                         <vhdlType>STD_LOGIC_VECTOR</vhdlType>
                     </port>
@@ -8512,7 +8512,7 @@
                         <name>avs_mem_address</name>
                         <role>address</role>
                         <direction>Input</direction>
-                        <width>1</width>
+                        <width>2</width>
                         <lowerBound>0</lowerBound>
                         <vhdlType>STD_LOGIC_VECTOR</vhdlType>
                     </port>
@@ -8581,7 +8581,7 @@
                         </entry>
                         <entry>
                             <key>addressSpan</key>
-                            <value>8</value>
+                            <value>16</value>
                         </entry>
                         <entry>
                             <key>addressUnits</key>
@@ -8987,11 +8987,11 @@
                     <suppliedSystemInfos>
                         <entry>
                             <key>ADDRESS_MAP</key>
-                            <value>&lt;address-map&gt;&lt;slave name='mem' start='0x0' end='0x8' datawidth='32' /&gt;&lt;/address-map&gt;</value>
+                            <value>&lt;address-map&gt;&lt;slave name='mem' start='0x0' end='0x10' datawidth='32' /&gt;&lt;/address-map&gt;</value>
                         </entry>
                         <entry>
                             <key>ADDRESS_WIDTH</key>
-                            <value>3</value>
+                            <value>4</value>
                         </entry>
                         <entry>
                             <key>MAX_SLAVE_DATA_WIDTH</key>
@@ -39356,7 +39356,7 @@
    version="18.0"
    start="cpu_0.data_master"
    end="jtag_uart_0.avalon_jtag_slave">
-  <parameter name="baseAddress" value="0x000b41d8" />
+  <parameter name="baseAddress" value="0x000b41e0" />
  </connection>
  <connection
    kind="avalon"
@@ -39391,7 +39391,7 @@
    version="18.0"
    start="cpu_0.data_master"
    end="pio_pps.mem">
-  <parameter name="baseAddress" value="0x000b41d0" />
+  <parameter name="baseAddress" value="0x000b4170" />
  </connection>
  <connection
    kind="avalon"
@@ -39419,28 +39419,28 @@
    version="18.0"
    start="cpu_0.data_master"
    end="reg_dpmm_ctrl.mem">
-  <parameter name="baseAddress" value="0x000b41c8" />
+  <parameter name="baseAddress" value="0x000b41d8" />
  </connection>
  <connection
    kind="avalon"
    version="18.0"
    start="cpu_0.data_master"
    end="reg_dpmm_data.mem">
-  <parameter name="baseAddress" value="0x000b41c0" />
+  <parameter name="baseAddress" value="0x000b41d0" />
  </connection>
  <connection
    kind="avalon"
    version="18.0"
    start="cpu_0.data_master"
    end="reg_mmdp_ctrl.mem">
-  <parameter name="baseAddress" value="0x000b41b8" />
+  <parameter name="baseAddress" value="0x000b41c8" />
  </connection>
  <connection
    kind="avalon"
    version="18.0"
    start="cpu_0.data_master"
    end="reg_mmdp_data.mem">
-  <parameter name="baseAddress" value="0x000b41b0" />
+  <parameter name="baseAddress" value="0x000b41c0" />
  </connection>
  <connection
    kind="avalon"
@@ -39475,7 +39475,7 @@
    version="18.0"
    start="cpu_0.data_master"
    end="reg_si.mem">
-  <parameter name="baseAddress" value="0x000b41a8" />
+  <parameter name="baseAddress" value="0x000b41b8" />
  </connection>
  <connection
    kind="avalon"
@@ -39517,7 +39517,7 @@
    version="18.0"
    start="cpu_0.data_master"
    end="reg_bsn_scheduler.mem">
-  <parameter name="baseAddress" value="0x000b41a0" />
+  <parameter name="baseAddress" value="0x000b41b0" />
  </connection>
  <connection
    kind="avalon"
@@ -39552,7 +39552,7 @@
    version="18.0"
    start="cpu_0.data_master"
    end="reg_dp_selector.mem">
-  <parameter name="baseAddress" value="0x000b4198" />
+  <parameter name="baseAddress" value="0x000b41a8" />
  </connection>
  <connection
    kind="avalon"
@@ -39615,7 +39615,7 @@
    version="18.0"
    start="cpu_0.data_master"
    end="reg_nw_10gbe_eth10g.mem">
-  <parameter name="baseAddress" value="0x000b4190" />
+  <parameter name="baseAddress" value="0x000b41a0" />
  </connection>
  <connection
    kind="avalon"
@@ -39643,14 +39643,14 @@
    version="18.0"
    start="cpu_0.data_master"
    end="pio_jesd_ctrl.mem">
-  <parameter name="baseAddress" value="0x000b4188" />
+  <parameter name="baseAddress" value="0x000b4198" />
  </connection>
  <connection
    kind="avalon"
    version="18.0"
    start="cpu_0.data_master"
    end="reg_stat_enable_sst.mem">
-  <parameter name="baseAddress" value="0x000b4180" />
+  <parameter name="baseAddress" value="0x000b4190" />
  </connection>
  <connection
    kind="avalon"
@@ -39678,7 +39678,7 @@
    version="18.0"
    start="cpu_0.data_master"
    end="reg_dp_sync_insert_v2.mem">
-  <parameter name="baseAddress" value="0x000b4178" />
+  <parameter name="baseAddress" value="0x000b4188" />
  </connection>
  <connection
    kind="avalon"
@@ -39692,7 +39692,7 @@
    version="18.0"
    start="cpu_0.data_master"
    end="reg_bsn_scheduler_xsub.mem">
-  <parameter name="baseAddress" value="0x000b4170" />
+  <parameter name="baseAddress" value="0x000b4180" />
  </connection>
  <connection
    kind="avalon"
diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/mmm_lofar2_unb2b_sdp_station.vhd b/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/mmm_lofar2_unb2b_sdp_station.vhd
index 01eded088e51e68dc9d9440f268f0ca389260c00..e0ec6e62de04ecc0ccf238b673762acbd6f07454 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/mmm_lofar2_unb2b_sdp_station.vhd
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/mmm_lofar2_unb2b_sdp_station.vhd
@@ -479,9 +479,7 @@ BEGIN
 
       pio_pps_reset_export                      => OPEN,
       pio_pps_clk_export                        => OPEN,
---    ToDo: This has changed in the peripherals package
-      pio_pps_address_export                    => reg_ppsh_mosi.address(0 DOWNTO 0),
---      pio_pps_address_export                    => reg_ppsh_mosi.address(c_unb2b_board_peripherals_mm_reg_default.reg_ppsh_adr_w-1 DOWNTO 0),
+      pio_pps_address_export                    => reg_ppsh_mosi.address(c_unb2b_board_peripherals_mm_reg_default.reg_ppsh_adr_w-1 DOWNTO 0),
       pio_pps_write_export                      => reg_ppsh_mosi.wr,
       pio_pps_writedata_export                  => reg_ppsh_mosi.wrdata(c_word_w-1 DOWNTO 0),
       pio_pps_read_export                       => reg_ppsh_mosi.rd,
diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/qsys_lofar2_unb2b_sdp_station_pkg.vhd b/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/qsys_lofar2_unb2b_sdp_station_pkg.vhd
index 461075358e25bed8e93cef89b6783e17d3a64ca5..181b0649ce2ec4ba52ea38891fdbb873192a6a20 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/qsys_lofar2_unb2b_sdp_station_pkg.vhd
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/src/vhdl/qsys_lofar2_unb2b_sdp_station_pkg.vhd
@@ -62,7 +62,7 @@ PACKAGE qsys_lofar2_unb2b_sdp_station_pkg IS
             pio_jesd_ctrl_reset_export                : out std_logic;                                        -- export
             pio_jesd_ctrl_write_export                : out std_logic;                                        -- export
             pio_jesd_ctrl_writedata_export            : out std_logic_vector(31 downto 0);                    -- export
-            pio_pps_address_export                    : out std_logic_vector(0 downto 0);                     -- export
+            pio_pps_address_export                    : out std_logic_vector(1 downto 0);                     -- export
             pio_pps_clk_export                        : out std_logic;                                        -- export
             pio_pps_read_export                       : out std_logic;                                        -- export
             pio_pps_readdata_export                   : in  std_logic_vector(31 downto 0) := (others => 'X'); -- export
diff --git a/applications/lofar2/doc/prestudy/station2_sdp_hdl_components.txt b/applications/lofar2/doc/prestudy/station2_sdp_hdl_components.txt
index 86d425c6093b5ff9422589b1dcfc389045216be6..3499fd5fbbb8aab21490ef20541163e2c888c6fe 100755
--- a/applications/lofar2/doc/prestudy/station2_sdp_hdl_components.txt
+++ b/applications/lofar2/doc/prestudy/station2_sdp_hdl_components.txt
@@ -142,260 +142,270 @@ inputs have the same 64 bit sync and BSN.
 *******************************************************************************
 
 Assumptions:
-- Per input the Rx packets arrive in order
+- Done: Per input the Rx packets arrive in order
   . a packet contains one or more blocks, on the ring every packet contains one block
-- Only allow correct blocks to enter the FPGA processing
+- Done: Only allow correct blocks to enter the FPGA processing
   . the block validation is based on Rx packet CRC and BSN at sync
-- Usage schemes:
-  . N = 2 inputs aligner with 1 local data and 1   remote data
-  . N > 2 inputs aligner with 1 local data and N-1 remote data
-  . N >=2 inputs aligner with 0 local data and N   remote data (not used on ring, but was used in
+- Done: Usage schemes:
+  . Ignore: N = 2 inputs aligner with 1 local data and 1   remote data
+  . Ignore: N > 2 inputs aligner with 1 local data and N-1 remote data
+  . Ignore: N >=2 inputs aligner with 0 local data and N   remote data (not used on ring, but was used in
     APERTIF)
-  . Treat all inputs equal, so no special role for a local input to suit more general usage
-- The local sync and BSN sources on all FPGAs are synchronous, to avoid additional BSN latency
+  . Do not: Treat all inputs equal, so no special role for a local input to suit more general usage.
+  . Done: Allow using input 0 as reference ouput. This can be a functional local input or an
+          artificial local input.
+- Done: The local sync and BSN sources on all FPGAs are synchronous, to avoid additional BSN latency
   between inputs.
-- Static input enable or disable via M&C
-  - it is possible to enable or disable any combination of inputs
-  - if all inputs are disabled then the output stops.
-  - if the input enable or disable setting is changed, then the BSN aligner restarts trying to
+- Done: Static input enable or disable via M&C
+  - Done: it is possible to enable or disable any combination of inputs
+  - Done: if all inputs are disabled then the output stops.
+  - Ignore: if the input enable or disable setting is changed, then the BSN aligner restarts trying to
     achieve alignment.
-  - disabled inputs are output with zero or flagged data
-  - for the ring with 1 local and 1 remote input the static input enable/disable supports the
+  - Done: disabled inputs are output with zero or flagged data
+  - Ignore: for the ring with 1 local and 1 remote input the static input enable/disable supports the
     align modes:
     . disabled,
     . local only,
     . remote only,
     . local and remote
-- Input latency:
-  . the input latencies are fixed by design, so inputs have a maximum BSN latency g_bsn_latency
+- Done: Input latency:
+  . Done: the input latencies are fixed by design, so inputs have a maximum BSN latency g_bsn_latency
     that is fixed and that does not have to be programmable via M&C.
-  . If all hops on the ring are active then the total latency will be (N-1)*t_hop, where t_hop is
+  . Ignore: If all hops on the ring are active then the total latency will be (N-1)*t_hop, where t_hop is
     the transport latency of each hop. The total transport latency on the ring is (N-1)*t_hop.
     The total ring latency is covered by g_bsn_latency > (N-1)*t_hop.
-- Lost input blocks:
-  . accept that the corresponding output is lost too, or output filler block to replace lost block
-  . should not cause subsequent blocks to get lost too
-  . must not induce a burst of output blocks due output catch up after late lost block detection
-  . If often blocks on one input get lost, then it is not acceptable that the output is lost.
-    - insert filler block to replace the lost input blocks, or
-    - support dynamic input enable/disable control
-- Only output correct blocks, either with the received input block or with flagged filler block
-- The output passes on the sync and therefore it does not have to pass on the BSN
-- The output should support flow control to:
-  . smoothen bursts (only an issue with remote drive output)
-  . provide output throttling (requires output FIFOs or data blocks that have sufficient gaps)
-- Stopped input:
-  . If after some block periods (e.g. g_bsn_latency) there is no more block pending at any input,
+- Done: Lost input blocks:
+  . Ignore: accept that the corresponding output is lost too, or output filler block to replace lost block
+  . Done: should not cause subsequent blocks to get lost too
+  . Done: must not induce a burst of output blocks due output catch up after late lost block detection
+  . Done: If often blocks on one input get lost, then it is not acceptable that the output is lost.
+    - Done: insert filler block to replace the lost input blocks, or
+    - Do not: support dynamic input enable/disable control
+- Done: Only output correct blocks, either with the received input block or with flagged filler block
+- Done: The output passes on the sync and should also pass on BSN to be able to identify lost blocks
+- Done: The output should support flow control to:
+  . Done: smoothen bursts (only an issue with remote drive output)
+  . Ignore: provide output throttling (requires output FIFOs or data blocks that have sufficient gaps)
+- Done: Stopped input:
+  . Ignore: If after some block periods (e.g. g_bsn_latency) there is no more block pending at any input,
     then the output stops and the BSN aligner should restart trying to achieve alignment.    
 
 
 
 
-Notes:
-- In LOFAR and APERTIF the BSN aligner does loose more blocks due to input flush and realign
-- a BSN aligner can align at any BSN, using a sync aligner that can only align at the sync, would
+Done: Notes:
+- Done: In LOFAR and APERTIF the BSN aligner does loose more blocks due to input flush and realign
+- Done: a BSN aligner can align at any BSN, using a sync aligner that can only align at the sync, would
   cause loosing an entire sync interval to realign, which is not acceptable
-- in APERTIF the sync_checker looses entire sync intervals to ensure filled sync intervals
-- In LOFAR and APERTIF the output is driven by the remote input to add minimal latency, however
+- Ignore: in APERTIF the sync_checker looses entire sync intervals to ensure filled sync intervals
+- Done: In LOFAR and APERTIF the output is driven by the remote input to add minimal latency, however
   this results in loosing more packets and having to realign if input packets get lost.
-- In dp_bsn_align the artifical local data stream was used to ensure that the output block size
+- Ignore: In dp_bsn_align the artifical local data stream was used to ensure that the output block size
   was correct, by using extra CRC checking (ETH CRC and DP CRC) and store and forward in Rx it is
   already certain that only correct input packets arrive at the BSN aligner input. Therefore an
   artifical local data stream is not needed.
 
 
 Design options:
-- Lost packet detection
-  . Rely on next received packet:
+- Done: Lost packet detection
+  . Do not: Rely on next received packet:
     - check per input that the BSN increments +1
     - requires a timeout or overflow detection on other inputs to detect a burst of lost packets
     - after a burst of lost packets, typically the output cannot catch up anymore, so then the BSN
       aligner needs to flush its input buffer and restart.
-  . Per packet using a local block reference.
+  . Done: Per packet using a local block reference.
     The local block reference is offset by at least g_bsn_latency relative to the local BSN
     source, to ensure that all inputs should have a new block pending for output. This is
     possible, because the input latencies are static and within a fixed range:
     - in circular buffer the Wr flag for the lost block remains unset
     - in FIFO by no pending input or pending input with higher BSN then current output BSN
   
-  ==> Design decision:
-      - Use local block reference to define when to detect lost packets, because one lost block
+  ==> Done: Design decision:
+      - Done: Use local block reference to define when to detect lost packets, because one lost block
         should not cause subsequent blocks to get lost too.
 
 
-- Output driven by remote input block arrival or by local block reference
-  . in case of 1 remote input, the remote input does not need a FIFO if it drives the output
-  . in case of > 1 remote input, then the remote inputs also requires FIFOs
-  . using local input increases the latency from remote input to output, because fixed to the
+- Done: Output driven by remote input block arrival or by local block reference
+  . Ignore: in case of 1 remote input, the remote input does not need a FIFO if it drives the output
+  . Ignore: in case of > 1 remote input, then the remote inputs also requires FIFOs
+  . Ignore: using local input increases the latency from remote input to output, because fixed to the
     T_sub grid
-  . using local input at T_sub grid avoids bursts, this can also be handled using flow control
+  . Done: using local input at T_sub grid avoids bursts, this can also be handled using flow control
   . with local input driving the output the assumption is that if the local input has M packets,
     then all remote inputs will have delivered at least one frame, so there should be a sop
     pending from all.
-  . if there is no local input, then an artifical local input can be derived when BSN is equal on
+  . Done: if there is no local input, then an artifical local input can be derived when BSN is equal on
     all enabled remote inputs.
-  . if remote input is lost, then entire output is lost if remote drives output, because there is
+  . Ingore: if remote input is lost, then entire output is lost if remote drives output, because there is
     not enough spare time to still output the other input packets
-  . For remote driven output a slot can be output when for all active inputs there is a block.
+  . Done: For remote driven output a slot can be output when for all active inputs there is a block.
     However if one or a series of packets got lost, then the other inputs will overflow. Hence
     remote driven output needs a timeout to keep the output running, so a form of local driven
     output. Hence to avoid additional packet loss on other inputs or of subsequent packets in time
     it is necessary to have a local driven output. Therefore using a remote driven output is not
     feasible. 
 
-  ==> Design decision:
+  ==> Done: Design decision:
       - Use local block reference to define when aligned blocks should be output, because one lost
         block should not cause subsequent blocks to get lost too, which is more important then
         adding minimal latency and potentially saving BSN aligner input buffer memory.
 
 
-- Generation of local block reference to define the output pace:
-  . During initial input alignment it is important that all active inputs are indeed active, because together they
+- Done: Generation of local block reference to define the output pace:
+  . Ignore: During initial input alignment it is important that all active inputs are indeed active, because together they
     determine the latency difference between inputs. After initial alignment the data output can continue at at a
     fixed rate, driven by a local block reference:
-    - The local input or the remote input with the least latency could be used as local output block reference,
+    - Do not: The local input or the remote input with the least latency could be used as local output block reference,
       because (N-1)*d << 1. This requires having a local input or detecting the closest remote input.
-    - Alternatively a dedicated local block reference can be started with a certain time offset can be started
+    - Ignore: Alternatively a dedicated local block reference can be started with a certain time offset can be started
       after achieving input alignment. The time offset sets a margin that ensures that at subsequent block
       refererence pulses all inputs will have a new block pending if the block is not lost.
       
-  ==> Design decision:
-      - Generate local block reference when initial BSN alignment has been achieved and start it with a certain
+  ==> Done: Design decision:
+      - Do not: Generate local block reference when initial BSN alignment has been achieved and start it with a certain
         fixed offset.
+        Done: Alternatively start local block reference input with a certain fixed offset that is
+        fixed to the local sync, assuming that the inputs have started at that sync too.
+        This avoids the complication of having to wait for initial BSN alignment, but may
+        introduce some more latency.
         
 
-- Filler data insertion      
-  . Whether to drop a block or to replace it by a filler block depends on the application
+- Done: Filler data insertion
+  . Ignore: Whether to drop a block or to replace it by a filler block depends on the application
     - for BF drop all inputs, because beam is affected
     - for XC insert filler data, because visibilities of active inputs are still correct.
     - for the output via the Network insert filler data to keep the output at the nominal rate, such that
       the destination can distinguish between data blocks that got lost inside Station and packet loss on
       the Network.
-  . Filler blocks can be flagged using a sosi.channel bit as flag
-  . Filler data can be:
+  . Done: Filler blocks can be flagged using a sosi.channel bit as flag
+  . Done: Filler data can be:
     - undefined
     - forced to zero
     - random with similar noise level,
     - flagged data using most negative integer in real data
     - flagged data most negative integer in complex real part and imag part (or use imag part as cause identifier).
 
-  ==> Design decision:
-      - Replace lost blocks by filler blocks, to preserve the nominal output rate
-      - Flag the filler block via a sosi.channel bit, to distinguish the block
-      - Forced the filler data to some constant dependent on a generic, to support transparant operation
-        in e.g. an adder where x + 0 = x or a multiplier where x * 1 = x, or to support flagging per data
-        value using most negative integer value.
+  ==> Done: Design decision:
+      - Done: Replace lost blocks by filler blocks, to preserve the nominal output rate
+      - Done: Flag the filler block via a sosi.channel bit, to distinguish the block
+      - Done: Forced the filler data to some constant dependent on a generic, to support transparant operation
+        in e.g. an adder where x + 0 = x or a multiplier where x * 0 = 0 or x * 1 = x, or to support flagging
+        per data value using most negative integer value.
 
     
   
-. dynamic input enable/disable in case of lost packets
-  - Scheme:
-    . Fine per packet scheme:
+. Done: dynamic input enable/disable in case of lost packets
+  - Ignore: Scheme:
+    . Ignore: Fine per packet scheme:
       - Input packets arrive every block period, remote packets can arrive anywhere within a block period,
       - If one input stops, then g_sop_timeout occurs in s_align and then that input could be dynamically disabled in s_xoff.
         Inputs can dynamically be enabled if they arrive within two block periods, in s_align.
       - too nervous, too difficult to debug and monitor
-    . Coarse per sync interval scheme:
+    . Ignore: Coarse per sync interval scheme:
       - if an input has no lost packets during one (or more) sync interval then it can be dynamically enabled for the next sync interval
       - if an input has lost packets during one (or more) sync interval then it can be dynamically disabled for the next sync interval
       - This is a suitable scheme because it does not react too fast and it can be monitored via M&C.
       - Define number of sync intervals for dynamic input control as a generic
       - preferred because it is less active and easier to monitor
-  - Is dynamic input enable/disable necessary if a lost packet does not affect next packets?
-    . If lost data is replaced by filler data, then only static input enable/disable is necessary, because if an input
+  - Ignore: Is dynamic input enable/disable necessary if a lost packet does not affect next packets?
+    . Ignore: If lost data is replaced by filler data, then only static input enable/disable is necessary, because if an input
       becomes inactive it will be flagged and the output can still continue.
-    . If lost data causes all inputs to be discarded, then dynamic input enable/disable may be useful to avoid that a
+    . Ignore: If lost data causes all inputs to be discarded, then dynamic input enable/disable may be useful to avoid that a
       single input causes all output to stop.
       
-  ==> Design decision:
-      - It is not necessary to support dynamic input enable/disable, because lost blocks are replaced by filler blocks.
+  ==> Done: Design decision:
+      - Done:It is not necessary to support dynamic input enable/disable, because lost blocks are replaced by filler blocks.
 
 
-. Treat all inputs equal or use local input stream as reference to achieve input alignment:
-  - using the local data stream as reference stream can benefit from the fact that the local data stream has no
+. Done: Treat all inputs equal or use local input stream as reference to achieve input alignment:
+  - Done: using the local data stream as reference stream can benefit from the fact that the local data stream has no
     packet loss, because internally in the FPGA logic is error free.
-  - treating all streams equal is more general and also works when static input enable/disable disables the local
+  - Done: treating all streams equal is more general and also works when static input enable/disable disables the local
     input. 
     
-  ==> Design decision:
-      - Treat all inputs equal. Do not make use of the fact that the ring has a local input. In this way the BSN 
+  ==> Done: Design decision:
+      - Done: Treat all inputs equal. Do not make use of the fact that the ring has a local input. In this way the BSN
         aligner can also work when there are only remote inputs.
 
       
       
-. sync aligner instead of BSN aligner
-  - Using the sosi.sync one packet lost causes whole interval lost, this is too much impact.
+. Done: sync aligner instead of BSN aligner
+  - Done: Using the sosi.sync one packet lost causes whole interval lost, this is too much impact.
 
-  ==> Design decision:
-      Do not make or use a dp_sync_aligner, because loosing an entire sync interval is not acceptable.
+  ==> Done:Design decision:
+      Done: Do not make or use a dp_sync_aligner, because loosing an entire sync interval is not acceptable.
       
-. Assume circular buffer:
-  - advantage:
+. Done: Assume circular buffer:
+  - Done: advantage:
     . direct access to each word in block
     . no need to flush blocks, status bit per block tells whether it is filled
-  - buffer is filled and read after certain latency, because then all remote packets should have arrived
+  - Done: buffer is filled and read after certain latency, because then all remote packets should have arrived
     . provide CP for active input streams, is this needed ?
-  - use MM interface to read from head column (with block for all parallel streams)
-  - provide mm to dp component with bsn aligner (= dp_block_from_mm ?)
-  - provide MP for nof lost = nof filler blocks / stream ?
-    . err at eop indicates lost = filler data, sosi_info could have eop at sop like with crosslets_info
+  - Done: use MM interface to read from head column (with block for all parallel streams)
+  - Done: provide mm to dp component with bsn aligner (= dp_block_from_mm ?)
+  - - Done: provide MP for nof lost = nof filler blocks / stream ?
+    . Done: use channel field MSbit to indicate filler data at sop, sosi_info could have eop at sop like
+            with crosslets_info
+
       
 . Initial alignment:
-  - Assume the received packets on the inputs contain one block per packet.
-    The maximum input latency between blocks from two inputs is g_bsn_latency number of block periods. If the
+  - Ignore: Assume the received packets on the inputs contain one block per packet.
+    Ignore: The maximum input latency between blocks from two inputs is g_bsn_latency number of block periods. If the
     maximum input latency is less than one block period, then use g_bsn_latency = 1. 
-    Assume that all inputs are active and that all inputs start with empty input buffers. At each input packets
+    Do not: Assume that all inputs are active and that all inputs start with empty input buffers. At each input packets
     arrive and fill the input buffers.
-    The minimum size of the total input buffer memory is g_nof_inputs * g_bsn_latency blocks, because then
-    initial alignment can be declared as soon as there is a block pending in the input buffers with the same
-    BSN at all inputs.
-    After initial alignment the alignment can be maintained by using a local block reference to time the
-    subsequent output of aligned input blocks.    
-    As long as at least one input buffer still has blocks then output can continue using filler blocks. The
-    local block reference ensures that the buffers will read empty if they do not get new input, this ensures
-    that any input in the buffers can still be output at the correct instant. If all buffers are empty then
-    input realignment is needed.
-
-  - The initial alignment becomes easier if:
+    . Done: The minimum size of the total input buffer memory is g_nof_inputs * g_bsn_latency blocks, because then
+      initial alignment can be declared as soon as there is a block pending in the input buffers with the same
+      BSN at all inputs.
+    . Do not: After initial alignment the alignment can be maintained by using a local block reference to time the
+      subsequent output of aligned input blocks.
+    . Done: As long as at least one input buffer still has blocks then output can continue using filler blocks. The
+      local block reference ensures that the buffers will read empty if they do not get new input, this ensures
+      that any input in the buffers can still be output at the correct instant. If all buffers are empty then
+      input realignment is needed.
+
+  - Done: The alignment becomes easier if:
   
-    . it is not done on the entire 64 bit BSN, but only on a periodic fraction r of the BSN,
-    . the periodic BSN has a period that is a power of 2, so r = BSN[R-1:0].
-    . it is not done on any BSN, but only on a certain periodic BSN marked by an align_sync pulse at r = 0.
+    . Done: it is not done on the entire 64 bit BSN, but only on a periodic fraction r of the BSN,
+    . Done: the periodic BSN has a period that is a power of 2, so r = BSN[R-1:0].
+    . Ignore: it is not done on any BSN, but only on a certain periodic BSN marked by an align_sync pulse at r = 0.
 
-    The advantage of using a BSN fraction is that it smaller to handle and that it can be used
+    Done: The advantage of using a BSN fraction is that it smaller to handle and that it can be used
     as index to a  block in the input buffer. The fraction r of the BSN must be unique over the maximum input
     latency, so r >= g_bsn_latency. The calculation of the BSN fraction r becomes easier, by choosing a fraction
     that is a power of 2, so r = 2**ceil_log2(g_bsn_latency), to avoid integer division. The BSN fraction then
-    follows directly from the R = log2(r) LSbits of the BSN, so r = BSN[R-1:0]. The advantange of detecting the
-    alignment only at a certain periodic BSN is that the initial block index is then fixed at a certain r,
-    choose r = 0. it is convenient to mark the periodic BSN fraction at r = 0 by a sync pulse that is called the
-    align_sync.
-    The align_sync is only used within the BSN aligner. If alignment fails on an align_sync, due to a lost
-    packet, then the intial alignment retries on the next align_sync. The minimal period of the align_sync
-    must be large enough to ensure that the input buffers will only contain corresponding align_sync and no
-    align_sync from different intervals. Hence the align_sync period must be > BSN latency + buffer size. 
-    Without align_sync the buffer would need to be twice as large to ensure unambigous detection of alignment.
+    follows directly from the R = log2(r) LSbits of the BSN, so r = BSN[R-1:0].
+    Ignore: The advantange of detecting the alignment only at a certain periodic BSN is that the initial block
+    index is then fixed at a certain r, choose r = 0. it is convenient to mark the periodic BSN fraction at
+    r = 0 by a sync pulse that is called the align_sync.
+    Ignore: The align_sync is only used within the BSN aligner. If alignment fails on an align_sync, due to a lost
+    packet, then the intial alignment retries on the next align_sync.
+    Not true: The minimal period of the align_sync  must be large enough to ensure that the input buffers will only contain
+    corresponding align_sync and no align_sync from different intervals. Hence the align_sync period must be
+    > BSN latency + buffer size.
+    Not true: Without align_sync the buffer would need to be twice as large to ensure unambigous detection of alignment.
     The align_sync period must be short enough to have a fast initial alignment. The 1 s sync interval could
     be used as align_sync, but in LOFAR2.0 the 1 s sync BSN period is not a power of two and differs by 1 per
     sync interval, so the sync appears at different block indices. Furthermore a 1 s period is relatively long,
     using a dedicated and much shorter align_sync period allows fast initial alignment.
     
-  - For the ring the latency depends on the number of hops. Therefore require that initial BSN alignment is achieved
+  - Ignore: For the ring the latency depends on the number of hops. Therefore require that initial BSN alignment is achieved
     with all active input as defined by M&C, to ensure that the total input latency at each node on the ring is
     determined by the nominal operation.
     
-  ==> Design decision:
-    - Use input buffer size > g_bsn_latency to compensate for the maximum BSN latency difference between inputs
-    - Use an align_sync period > g_bsn_latency + buffer size to start initial alignment and to ensure, 
+  ==> Done: Design decision:
+    - Done: Use input buffer size > g_bsn_latency to compensate for the maximum BSN latency difference between inputs
+    - Do not: Use an align_sync period > g_bsn_latency + buffer size to start initial alignment and to ensure,
       together with the validation of the BSN at sync, the unambigous detection of input alignment on the same BSN
    
    
-. Input buffer type
+. Done: Input buffer type
   The input buffer can be structured as:
   
-  - a circular buffer that can be accessed at any address, or
-  - a FIFO buffer that is used first in first out. 
+  - Done: a circular buffer that can be accessed at any address, or
+  - Do not: a FIFO buffer that is used first in first out.
   
+  Done/ignore:
   In a circular buffer each input block will occupy a slot that is identified by the block index r. For each slot 
   there is a write (Wr) flag that is set when the block is written and cleared when the block is read for output
   or discarded. The slots in the circular buffer have the fixed block size, so therefore the sop and eop of the
@@ -414,7 +424,7 @@ Design options:
         3 4 5 6 7 A 1 2    . . . W    W . . 3    4 W . 3    4 5 W 3    4 5 6 W    W 5 6 7    A W 6 7    0 1 W 7
         2 3 4 5 6 7 A 1    . . W .    . . 2 W    W . 2 3    4 W 2 3    4 5 W 3    4 5 6 W    W 5 6 7    0 W 6 7
                                                                                              R            R      
-  
+  Do not:
   In a FIFO buffer each input block is written at the first free location, so in order of arrival. A lost packet
   does not show in the FIFO, so therefore the block index r needs to be passed along with the block through the
   FIFO and checked at the output. It is convenient to pass on the sop and eop information with the block through
@@ -433,43 +443,43 @@ Design options:
         2 3 4 5 6 7 A 1    . . . .    . . . .    . . . .    . . . .    . . . .    . . . .    W . . .    W . . .
                                                                                              R          R
         
-  Both the buffers need to pass on the sync information per block, to allow timestamp recovery from Station BSN 
+  Ignore:Both the buffers need to pass on the sync information per block, to allow timestamp recovery from Station BSN
   for the BSN aligner output.
   
   
-  The aspects of a circular buffer are:
-  - can handle out-of-order data, because it uses the BSN fraction as slot index. However on the ring in SDP all
+  Done: The aspects of a circular buffer are:
+  - Done: can handle out-of-order data, because it uses the BSN fraction as slot index. However on the ring in SDP all
     data will be in order.
-  - if initial alignment fails it automatically retries on the next align_sync.
-  - the BSN must be continuous and incrementing, because then the remainder of the BSN / buffer size can
+  - Ignore: if initial alignment fails it automatically retries on the next align_sync.
+  - Done: the BSN must be continuous and incrementing, because then the remainder of the BSN / buffer size can
     be used as Wr pointer. 
-  - to avoid integer division of the Station BSN the buffer size needs to be a power of 2
+  - Done: to avoid integer division of the Station BSN the buffer size needs to be a power of 2
   
-  The aspects of a FIFO buffer are:
-  - during initital alignment lost packets on one input will cause other inputs to overflow. 
-  - FIFO overflow can occur due to lost packets on an other input or when the initial alignment started while
+  Not used: The aspects of a FIFO buffer are:
+  - Ignore: during initital alignment lost packets on one input will cause other inputs to overflow.
+  - Ignore: FIFO overflow can occur due to lost packets on an other input or when the initial alignment started while
     align_sync from the different inputs are arriving. The align_sync period needs to be large enough to
     ensure that at a next attempt all align_sync will be for the corresponding BSN. The overflow requires a
     restart of the initial alignment by flushing the FIFOs.
-  - easy to use a buffer size that is not a power of 2, because the block index is not used as Wr pointer index.
+  - Ignore: easy to use a buffer size that is not a power of 2, because the block index is not used as Wr pointer index.
     Using a buffer size that is not a power of 2 can be significant to save RAM.
-  - Passing on the BSN fraction r via the FIFO may increase the number RAM, dependent on whether the combination
+  - Ignore: Passing on the BSN fraction r via the FIFO may increase the number RAM, dependent on whether the combination
     of data, sop, eop, sync, align_sync and r just fits in a multiple of the maximum data with of a block RAM
-  - The BSN index does not have to be incrementing, but is must be unique per BSN latency interval
+  - Ignore: The BSN index does not have to be incrementing, but is must be unique per BSN latency interval
   
 
-- Input / output control
-  . The BSN aligner can operate independently per input / output. The only interaction between inputs is needed
+- Ignore: Input / output control
+  . Ignore: The BSN aligner can operate independently per input / output. The only interaction between inputs is needed
     to detect that all inputs have a pending align_sync. The local block reference for block output can be
     shared for all outputs, or replicated per output.
-  . The 1 s sync does not have to be checked at the outputs, because if the sync is present on one output, then
+  . Ignore: The 1 s sync does not have to be checked at the outputs, because if the sync is present on one output, then
     it will be present on all outputs. 
 
       
 - Flushing:
-  . Circular buffer:
+  . Done: Circular buffer:
     - Clearing a Wr flag or all Wr flags is much faster than flush reading a FIFO.
-  . FIFO buffer:
+  . Ignore: FIFO buffer:
     - flush per packet or flush until empty?
     - flush per input per input or flush all inputs?
     - flush by reading, or by reset or by moving a Rd pointer
@@ -487,22 +497,22 @@ Design options:
       corresponded to the lost packet will need to be discarded anyway, because there is no time to output them still.
     - also useful to know BSNs at FIFO inputs? --> No, because FIFO packet count can be used to detect pending FIFO overflow.
   
-. Keep input buffers outside or inside BSN aligner component.
-  - for inputs with more latency the buffer can be smaller, this is easier to control with external buffers,
+. Ignore: Keep input buffers outside or inside BSN aligner component.
+  - Ignore: for inputs with more latency the buffer can be smaller, this is easier to control with external buffers,
     each input may have different g_bsn_latency, so then each input also has different align timeout, align_sync
     interval and input FIFO size.
-  - if the BSN aligner relies on FIFO input information, then it is better to have the FIFOs inside.
+  - Ignore: if the BSN aligner relies on FIFO input information, then it is better to have the FIFOs inside.
    
 
-- Fast integer division
+- Ignore: Fast integer division
   . Modulo 2**n - 1 can be calculated efficiently for binary numbers, by adding the n-bit digit parts. Similar as
     mpdulo 3 (= (10-1)/3) can be calculated by adding the decimal digits.
-  . Modulo n for constant n can be calculated efficiently suing multiplication by 1/n. The 1/n fraction must be 
+  . Modulo n for constant n can be calculated efficiently using multiplication by 1/n. The 1/n fraction must be
     represented with sufficient accuracy to determine the remainder. This implies using a 50 bit multiplier,
     because the Station BSN is 50 bit.
 
 
-. Circular buffers on CEP
+. Done: Circular buffers on CEP
   On CEP the beamlet data is written into a circular buffer based on the time stamp. A flag indicates whether data in the
   circular buffer is valid. The size of the circular buffer is in the order of hundreds of ms to cover the distance latency 
   of the international stations. An array of tupples lists the lenght of continuous blocks in the circular buffer, and 
@@ -511,7 +521,7 @@ Design options:
   also flags the initial channel data that is disturbed after a gap.
 
 
-. State machine for circular buffer
+. Ignore: State machine for circular buffer
     all:
       Receive and monitor input
       Derive align_sync from input BSN
@@ -536,7 +546,7 @@ Design options:
         output one block, use filler data for lost blocks, clear Wr flag of slot and increment Rd pointer --> s_sop
 
 
-. State machine for FIFO buffer
+. Do not: State machine for FIFO buffer
     all:
       Receive and monitor input
       Derive align_sync from input BSN
@@ -559,7 +569,7 @@ Design options:
       else
         output one block, use filler data for lost blocks --> s_sop
 
-  ==> Design decision:
+  ==> Done: Design decision:
       The circular buffer and FIFO are similar. The slight preference is to use a circular buffer, because it 
       handles overflow automatically and if the maximum input BSN latency is close to a power of 2, then the
       RAM usage of the circular buffer is near optimal, because it does not need to pass on the sop, eop and
@@ -567,7 +577,7 @@ Design options:
 
       
 
-Obsolete investigations:
+Ignore: Obsolete investigations:
     
 . APERTIF BSN max/min scheme of dp_bsn_align.vhd core:
   - State machine
diff --git a/applications/lofar2/doc/prestudy/station2_sdp_m_and_c.txt b/applications/lofar2/doc/prestudy/station2_sdp_m_and_c.txt
index 65b134f8b4b61b6fea6866d814b58da3bf2f4f14..c3caa48420577f11a63bae87f23026680f7acb19 100755
--- a/applications/lofar2/doc/prestudy/station2_sdp_m_and_c.txt
+++ b/applications/lofar2/doc/prestudy/station2_sdp_m_and_c.txt
@@ -17,11 +17,17 @@ may provide a monitoring point that allows the master to monitor the progress. O
 events that originate in the device it may be necessary to use the publish-subscribe pattern, whereby
 the slave self-generates an event message.
 
-The Station Control (SC) distinguishes between Control and Monitoring and Control (M&C). The Control in SC determines the behaviour of the Station in time. Via M&C the SC can control the Station Digital Processor (SDP) and monitor whether SDP behaves as expected. The SC uses OPC-UA over TCP/IP as standard Station M&C access interface. From SDP point of view all data access points are considered part of SDP M&C, however from SC point of view only a subset of these SDP M&C data points are part of Station M&C, and these are defined in the ICD SC-SDP.
-The SC M&C of SDP concerns two seperate parts:
+The Station Control (SC) distinguishes between Control and Monitoring and Control (M&C). The Control
+in SC determines the behaviour of the Station in time. Via M&C the SC can control the Station Digital
+Processor (SDP) and monitor whether SDP behaves as expected. The SC uses OPC-UA over TCP/IP as standard
+Station M&C access interface. From SDP point of view all data access points are considered part of
+SDP M&C, however from SC point of view only a subset of these SDP M&C data points are part of Station
+M&C, and these are defined in the ICD SC-SDP. The SC M&C of SDP concerns two seperate parts:
 
 * The SDP Hardware is controlled via OPC-UA in the Control subrack in the STCA (STCACO).
-* The SDP Firmware is controlled via OPC-UA in the SDP Translator (SDPT). The complete memory map of all data access points in the SDP Firmware is defined by a configuration file that can be read from the SDP Firmware.
+* The SDP Firmware is controlled via OPC-UA in the SDP Translator (SDPT). The complete memory map of
+  all data access points in the SDP Firmware is defined by a configuration file that can be read from
+  the SDP Firmware.
 
 *******************************************************************************
 * M&C of SDP firmware
@@ -41,7 +47,14 @@ Relevant L2 requirements for SDP monitoring points (BH):
 * Update scheme for the beamlet weigths
 *******************************************************************************
 
-For the beamformer weights an update period of about once every 4.5 s is fast enough for all astronomical observations [AD-2f] --> BH partioniong rationale for LOFAR2-4392. In LOFAR1 the beamlet weights were applied at every pulse per second (PPS), so every 1 s [RD-8]. The required update rate of the beamlet weigths depends on the beamlet pointing, however all beamlet weigths are controlled as a set, and the beamlets may point in any direction, so therefore the update rate needs to be at least once every 4.5 s. Using a faster update rate makes the beamformer more robust to occasionally loosing an update, because then the previous weigths will still apply well. Table 3.1 lists beamlet weight update schemes that are all suitable for a LOFAR2.0 Station.
+For the beamformer weights an update period of about once every 4.5 s is fast enough for all
+astronomical observations [AD-2f] --> BH partioniong rationale for LOFAR2-4392. In LOFAR1 the beamlet
+weights were applied at every pulse per second (PPS), so every 1 s [RD-8]. The required update rate
+of the beamlet weigths depends on the beamlet pointing, however all beamlet weigths are controlled
+as a set, and the beamlets may point in any direction, so therefore the update rate needs to be at
+least once every 4.5 s. Using a faster update rate makes the beamformer more robust to occasionally
+loosing an update, because then the previous weigths will still apply well. Table 3.1 lists beamlet
+weight update schemes that are all suitable for a LOFAR2.0 Station.
 
 Table  Possible beamlet weigths update scheme options for the SC-SDP ICD
 
@@ -52,13 +65,20 @@ Option Beamlet weights update scheme                       SDP weigths memory
 
 Comparison of the beamlet weigths update schemes in Table:
 
-* The advantage of scheme A and C compared to scheme B of LOFAR is that they are less time critica, because they are not tight to thefixed 1 s grid of the PPS.
-* The advantage of scheme A compared to scheme B and C is that it takes less weights memory in SDP, but the weights memory is not a critical resource for SDP
-* The advantage of scheme C compared to scheme A is that the weights can be send in advance, which relaxes the real time constraints on the SC to about 4.5 s.
+* The advantage of scheme A and C compared to scheme B of LOFAR is that they are less time critica,
+  because they are not tight to the fixed 1 s grid of the PPS.
+* The advantage of scheme A compared to scheme B and C is that it takes less weights memory in SDP,
+  but the weights memory is not a critical resource for SDP
+* The advantage of scheme C compared to scheme A is that the weights can be send in advance, which
+  relaxes the real time constraints on the SC to about 4.5 s.
 
-All schemes in Table can be applied via the SDP Translator as well as via the bypass control path. Scheme C is the most relaxed regarding the real time constrains on the SC and scheme C is quite feasible to realize in the SDP Firmware. Therefore assume that the SC-SDP ICD will specify using scheme C to update the beamlet weights (note that in [AD-2f] a mix of scheme A and scheme B was proposed, so SC sends control every 1 s and SDP applies immediately when received).
+All schemes in Table can be applied via the SDP Translator as well as via the bypass control path.
+Scheme C is the most relaxed regarding the real time constrains on the SC and scheme C is quite
+feasible to realize in the SDP Firmware. Therefore assume that the SC-SDP ICD will specify using
+scheme C to update the beamlet weights (note that in [AD-2f] a mix of scheme A and scheme B was
+proposed, so SC sends control every 1 s and SDP applies immediately when received).
 
-Design decision: Use option C.
+Design decision: Use option C. --> No, we use schema A because it is simplest and sufficient.
   
   
 *******************************************************************************
@@ -97,8 +117,8 @@ FPGAs in parallel. The synchronous M&C can be for a single PPS instant or for ev
     PPS and then read the monitoring to ensure that it relates to the same interval on all FPGAs.
     
 - Use single event BSN timestamp scheduler
-  . Gemini M&C protocol does not have timestamp activated control yet, therefore use separate BSN scheduler
-    control point.
+  . Gemini M&C protocol does not have timestamp activated control yet, therefore use separate BSN
+    scheduler control point.
   . SCU can read the statistics after the scheduled BSN
   . The next integration lasts until the next scheduled BSN
   . The programmable interval allows arbitrary intergration intervals, which avoid the need for the
@@ -197,7 +217,8 @@ Behaviour of the data points:
   . Sync, dual page monitor, periodic event latch sum values and restart integration at every sosi.sync
     - ST_SST
     
-  . SYnc, dual page control, periodic event page swap at sync when last value was written (so only then swap)
+  . Sync, dual page control, periodic event page swap at sync when last value was written (so only
+    then swap)
     - DP_FRINGE_STOP_OFFSET
                           
 *******************************************************************************
@@ -208,7 +229,8 @@ Behaviour of the data points:
 [2] TCP = Transmission Control Protocol (RFC 793)
 [3] UDP = User Datagram Protocol (RFC 768)
 
-TCP is a connection oriented protocol and is used when the data transfer needs to be intact and complete (e.g. files).
+TCP is a connection oriented protocol and is used when the data transfer needs to be intact and
+complete (e.g. files).
 
  - retransmit corrupt or lost datagrams
  - remove duplicate datagrams
@@ -216,7 +238,9 @@ TCP is a connection oriented protocol and is used when the data transfer needs t
  - rate adaption dependent on the throughput capacity of the network and the receiver
  - fragmentation of application data into datagrams [1]
  
-UDP is a transaction oriented and connectionless protocol and is used when the data transfer needs low latency and lost data may remain lost (e.g. video). The data interface to the application is discrete packets.
+UDP is a transaction oriented and connectionless protocol and is used when the data transfer needs
+low latency and lost data may remain lost (e.g. video). The data interface to the application is
+discrete packets.
 
 
 IP takes care of:
@@ -231,7 +255,11 @@ Ethernet
 - medium access control
 
 
-A socket pair identifies both ends of a connection, i.e. the virtual circuit [3]. For UDP the end-to-end connection identified by the source MAC, IP and UDP port tuple and destination MAC, IP and UDP port is sufficient, because UDP operates per datagram [3]. For TCP in addition a connection needs to be setup, because TCP needs to maintain the state of multiple datagrams that are communicated [2].
+A socket pair identifies both ends of a connection, i.e. the virtual circuit [3]. For UDP the
+end-to-end connection identified by the source MAC, IP and UDP port tuple and destination MAC,
+IP and UDP port is sufficient, because UDP operates per datagram [3]. For TCP in addition a
+connection needs to be setup, because TCP needs to maintain the state of multiple datagrams
+that are communicated [2].
 
 To make a reliable transport protocol involves:
 
@@ -248,7 +276,8 @@ MM transaction
 
 Verify flash
 - using readback is necessary with UCP due to that it uses a MM-DP fifo.
-- the transaction from FPGA to flash on UniBoard should preferrably have been readback already for each write request.
+- the transaction from FPGA to flash on UniBoard should preferrably have been readback already
+  for each write request.
 
 *******************************************************************************
 * Conclusion:
@@ -257,5 +286,5 @@ Verify flash
 - Identify casue of error preferrably via a single monitoring point
 - With proper monitoring no test time is needed
 - Support writing status fields in a test mode for SW - FW interface testing 
-- Use 1 s sync interval of PPS to time period M&C events for all. Optionally support a local BSN scheduler
-  for the XST.
+- Use 1 s sync interval of PPS to time period M&C events for all. Optionally support a local
+  BSN scheduler for the XST.
diff --git a/applications/lofar2/doc/prestudy/vhdl_explained.txt b/applications/lofar2/doc/prestudy/vhdl_explained.txt
index d8175f7f62c5d9ccca751e0fd32cc5e760649c3d..9140f745e434b49e9a814b4830dc5f8eb27e751f 100644
--- a/applications/lofar2/doc/prestudy/vhdl_explained.txt
+++ b/applications/lofar2/doc/prestudy/vhdl_explained.txt
@@ -10,7 +10,25 @@ IF x = 3 THEN
   y <= x;
 END IF;
 
-Maakt dat y een latch wordt. Je moet een ELSE y <= 0 END IF; toevoegen, of beginnen met een default assignment y <= 0; en dan de IF - END IF;
+Maakt dat y een latch wordt. Je moet een ELSE y <= 0 END IF; toevoegen, of beginnen met een default assignment y <= 0; en dan de IF - END IF; Dus:
+
+a <= 0
+IF b THEN
+  a<= 1
+END IF
+
+is hetzelfde als:
+
+IF b THEN
+  a<= 1
+ELSE
+  a <= 0
+END IF
+
+Mijn voorkeur is meestal om de eerste manier te gebruiken, omdat je dan daar al de default assignments doet.
+
+In process met IF of ELSIF rising_edge() moet juist geen ELSE, omdat je daar juist wel wilt dat er een flipflop gegenereerd zal worden. De synthesis compiler snapt dat.
+Een latch en een flipflop zin beide single bit geheugens, maar we moeten alleen flipflops maken.
 
   
 3) Complete sensitivity list
diff --git a/applications/lofar2/images/images.txt b/applications/lofar2/images/images.txt
index 29135b8ae552db29d9b56d622121a6c8b0bbe813..2ee374ed6d6bc4b67bc5cc73e2479310637d6635 100644
--- a/applications/lofar2/images/images.txt
+++ b/applications/lofar2/images/images.txt
@@ -8,4 +8,4 @@ lofar2_unb2b_sdp_station_fsub-rbc8dc7f66            | 2021-06-23    | R vd Walle
 lofar2_unb2b_sdp_station_bf-rc125dfd6d              | 2021-04-21    | R vd Walle           | See $UPE_GEAR/peripherals/tc_lofar2_unb2b_beamformer.py
 lofar2_unb2b_sdp_station_bf-r087d98be6              | 2021-06-14    | R vd Walle           | See $UPE_GEAR/peripherals/tc_lofar2_unb2b_beamformer.py
 lofar2_unb2b_sdp_station_xsub_one-r087d98be6        | 2021-06-14    | R vd Walle           | 
-
+unb2b_minimal-rce6b96eed                            | 2021-08-26    | P. Donker            | unb2b_minimal with new mmap, rbf maid with option --unb2_factory
diff --git a/applications/lofar2/images/unb2b_minimal-rce6b96eed.tar.gz b/applications/lofar2/images/unb2b_minimal-rce6b96eed.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..1ffeaade50d0a5729d27c1e134430bcb84a93b9c
Binary files /dev/null and b/applications/lofar2/images/unb2b_minimal-rce6b96eed.tar.gz differ
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2b_board_peripherals_pkg.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2b_board_peripherals_pkg.vhd
index 47d0e1390b2e2ce81898ee294cf60bf51078c686..ad0a102909558615f140a4146699c84693ef9bff 100644
--- a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2b_board_peripherals_pkg.vhd
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2b_board_peripherals_pkg.vhd
@@ -61,7 +61,7 @@ PACKAGE unb2b_board_peripherals_pkg IS
     reg_common_adr_w           : NATURAL;  -- = 1   -- fixed, from c_mem_reg in mms_common_reg
     
     -- pi_ppsh
-    reg_ppsh_adr_w             : NATURAL;  -- = 1   -- fixed, from c_mm_reg in ppsh_reg
+    reg_ppsh_adr_w             : NATURAL;  -- = 2   -- fixed, from c_mm_reg in ppsh_reg
     
     -- pi_unb_sens
     reg_unb_sens_adr_w         : NATURAL;  -- = 6   -- fixed, from c_mm_reg in unb_sens_reg
diff --git a/boards/uniboard2c/libraries/unb2c_board/src/vhdl/unb2c_board_peripherals_pkg.vhd b/boards/uniboard2c/libraries/unb2c_board/src/vhdl/unb2c_board_peripherals_pkg.vhd
index e64925db8956a2f0296f91f6b30f4787eb9938e8..f24eba33ead6e1d13f4a6fc6541fb52296e80094 100644
--- a/boards/uniboard2c/libraries/unb2c_board/src/vhdl/unb2c_board_peripherals_pkg.vhd
+++ b/boards/uniboard2c/libraries/unb2c_board/src/vhdl/unb2c_board_peripherals_pkg.vhd
@@ -61,7 +61,7 @@ PACKAGE unb2c_board_peripherals_pkg IS
     reg_common_adr_w           : NATURAL;  -- = 1   -- fixed, from c_mem_reg in mms_common_reg
     
     -- pi_ppsh
-    reg_ppsh_adr_w             : NATURAL;  -- = 1   -- fixed, from c_mm_reg in ppsh_reg
+    reg_ppsh_adr_w             : NATURAL;  -- = 2   -- fixed, from c_mm_reg in ppsh_reg
     
     -- pi_unb_sens
     reg_unb_sens_adr_w         : NATURAL;  -- = 6   -- fixed, from c_mm_reg in unb_sens_reg
diff --git a/doc/erko_hdl_design_article.txt b/doc/erko_hdl_design_article.txt
index 433895dd599352b901db76912f8a902c9f1b56e8..258ee28df84f060f20b0aafd45a005d73a3a2f6a 100644
--- a/doc/erko_hdl_design_article.txt
+++ b/doc/erko_hdl_design_article.txt
@@ -43,3 +43,33 @@ $RADIOHDL_WORK/applications/lofar2/doc/prestudy/
 Ref:
  $RADIOHDL/tools/oneclick/doc/desp_firmware_dag_erko.txt
  $RADIOHDL/tools/oneclick/doc/desp_firmware_overview.txt
+
+
+HDL coding: Useful documents about with fundamental knowledge for digital logic in FPGAs and ASICs:
+  - Memory mapped RAM and registers and clock domain crossing. Thanks to these standard components we
+    can run the mm_clk at another rate than the dp_clk:
+    https://svn.astron.nl/UniBoard_FP7/RadioHDL/trunk/libraries/base/common/doc/ASTRON_RP_415_common_mem.pdf
+    https://svn.astron.nl/UniBoard_FP7/UniBoard/trunk/Firmware/modules/Lofar/async_logic/doc/async_logic.pdf
+    About meta stability and asynchronous logic. This doc cointains solutions for:
+    . synchronizing a reset to a clock domain,
+    . transfering a level signal between clock domains
+    . transfering a pulse signal between clock domains
+      It als contains a study that I did to understand how the control of a dual clock FIFO works. Typically
+      we use an IP component as FIFO, but I think the async_fifo RTL code would also work on HW, it does
+      work in simulation.
+  - RTL combinatorial D --> D, rising_edge D --> Q
+    . complicates functional thinking because mixes combinatorial (valid now) and clocked (valid one
+      cylce later)
+    . latency of D --> Q complicates backpressure (RL = 1)
+    . introduces non-functional pipeline, mixes state reg and pipeline reg
+    Gaisler structures this RTL D --> Q coding style, but does not solve these complications
+    Gaisler uses variables, but does not structure the use of variables
+
+Ik zie twee niveaus:
+1) Als de FPGA synthese & timing aangeeft dat het goed is, dan is de FPGA logic foutloos
+  (dwz what you code is what you get).
+2) Als we goed ontwerpen, implementeren en testen, zorgen dat FIFOs niet overstromen, en zorgen
+   dat de packets die binnenkomen van buiten de FPGA correct zijn (bijv. mbv CRC ok) dan is de
+   block processing foutloos (dwz what you want is what you get). Dan kunnen we er intern steeds
+   van uitgaan dat de blokken data correct zijn en hoeven we dus intern geen checks meer te doen.
+
diff --git a/libraries/base/common/src/vhdl/common_counter.vhd b/libraries/base/common/src/vhdl/common_counter.vhd
index d4826da0ff55f29abdd3b937430ab18051055fcf..e65710d343bd86566baa48c1d3d2c5a20b694586 100644
--- a/libraries/base/common/src/vhdl/common_counter.vhd
+++ b/libraries/base/common/src/vhdl/common_counter.vhd
@@ -93,7 +93,7 @@ BEGIN
       nxt_count <= (OTHERS => '0');
     ELSIF cnt_ld='1' THEN
       nxt_count <= load;
-    ELSIF reg_count=cnt_max THEN
+    ELSIF cnt_en='1' AND reg_count=cnt_max THEN
       IF NOT g_clip THEN
         nxt_count <= (OTHERS => '0');
       END IF;
diff --git a/libraries/base/common/src/vhdl/common_pkg.vhd b/libraries/base/common/src/vhdl/common_pkg.vhd
index ba09970a6f98b5f6896ef7036894ca27fa5b024f..3931d107704f9417e9ce3156c27593ebe36fb8a3 100644
--- a/libraries/base/common/src/vhdl/common_pkg.vhd
+++ b/libraries/base/common/src/vhdl/common_pkg.vhd
@@ -195,7 +195,11 @@ PACKAGE common_pkg IS
   
   FUNCTION slv(n: IN STD_LOGIC)        RETURN STD_LOGIC_VECTOR;  -- standard logic to 1 element standard logic vector
   FUNCTION sl( n: IN STD_LOGIC_VECTOR) RETURN STD_LOGIC;         -- 1 element standard logic vector to standard logic
-  
+
+  FUNCTION to_sl(  n: IN BOOLEAN)   RETURN STD_LOGIC;  -- if TRUE       then return '1'   else '0'
+  FUNCTION to_bool(n: IN STD_LOGIC) RETURN BOOLEAN;    -- if '1' or 'H' then return TRUE  else FALSE
+  FUNCTION to_bool(n: IN INTEGER)   RETURN BOOLEAN;    -- if  0         then return FALSE else TRUE
+
   FUNCTION to_natural_arr(n : t_integer_arr; to_zero : BOOLEAN) RETURN t_natural_arr;  -- if to_zero=TRUE then negative numbers are forced to zero, otherwise they will give a compile range error
   FUNCTION to_natural_arr(n : t_nat_natural_arr)                RETURN t_natural_arr;
   FUNCTION to_integer_arr(n : t_natural_arr)                    RETURN t_integer_arr;
@@ -646,7 +650,28 @@ PACKAGE BODY common_pkg IS
     r := n(n'LOW);
     RETURN r;
   END;
-  
+
+
+  FUNCTION to_sl(n: IN BOOLEAN) RETURN STD_LOGIC IS
+  BEGIN
+    IF n = TRUE THEN
+      RETURN '1';
+    ELSE
+      RETURN '0';
+    END IF;
+  END;
+
+  FUNCTION to_bool(n: IN STD_LOGIC) RETURN BOOLEAN IS
+  BEGIN
+    RETURN n = '1' OR n = 'H';
+  END;
+
+  FUNCTION to_bool(n: IN INTEGER) RETURN BOOLEAN IS
+  BEGIN
+    RETURN NOT (n = 0);
+  END;
+
+
   FUNCTION to_natural_arr(n : t_integer_arr; to_zero : BOOLEAN) RETURN t_natural_arr IS
     VARIABLE vN : t_integer_arr(n'LENGTH-1 DOWNTO 0);
     VARIABLE vR : t_natural_arr(n'LENGTH-1 DOWNTO 0);
diff --git a/libraries/base/common/src/vhdl/common_reg_r_w_dc.vhd b/libraries/base/common/src/vhdl/common_reg_r_w_dc.vhd
index 8878d751ee3a09cd3975cf2039658f0d787ca785..d29acbb51aeb1345b3895b2c8a7e4cbea30c3570 100644
--- a/libraries/base/common/src/vhdl/common_reg_r_w_dc.vhd
+++ b/libraries/base/common/src/vhdl/common_reg_r_w_dc.vhd
@@ -44,6 +44,12 @@
 --   In fact g_readback could better be called g_st_readback. An alternative
 --   g_mm_readback could define direct read back in the MM clock domain and
 --   would allow leaving the in_reg not connected.
+-- . reg_wr_arr
+--   Provides write access pulse in dp_clk domain. However the pulse may arrive
+--   before the out_reg data, due to that the pulse and data do not cross the
+--   clock domain in the same way. A solution would be to use a single
+--   common_reg_cross_domain instance to transfer both the wr access info and
+--   the data.
 
 LIBRARY IEEE;
 USE IEEE.STD_LOGIC_1164.ALL;
diff --git a/libraries/base/common/src/vhdl/common_str_pkg.vhd b/libraries/base/common/src/vhdl/common_str_pkg.vhd
index 492bb411ab2341adce4ea2331c759fd56706ed47..cda0f3672e1b164d7156a455166ae428c340b609 100644
--- a/libraries/base/common/src/vhdl/common_str_pkg.vhd
+++ b/libraries/base/common/src/vhdl/common_str_pkg.vhd
@@ -46,6 +46,7 @@ PACKAGE common_str_pkg IS
   FUNCTION time_to_str(in_time : TIME) RETURN STRING;
   FUNCTION str_to_time(in_str : STRING) RETURN TIME;
   FUNCTION slv_to_str(slv : STD_LOGIC_VECTOR) RETURN STRING;
+  FUNCTION sl_to_str(sl : STD_LOGIC) RETURN STRING;
   FUNCTION str_to_hex(str : STRING) RETURN STRING;
   FUNCTION slv_to_hex(slv : STD_LOGIC_VECTOR) RETURN STRING;
   FUNCTION hex_to_slv(str : STRING) RETURN STD_LOGIC_VECTOR;
@@ -140,6 +141,11 @@ PACKAGE BODY common_str_pkg IS
      RETURN v_str;
   END;
 
+  FUNCTION sl_to_str(sl : STD_LOGIC) RETURN STRING IS
+  BEGIN
+     RETURN slv_to_str(slv(sl));
+  END;
+
   FUNCTION str_to_hex(str : STRING) RETURN STRING IS
     CONSTANT c_nof_nibbles : NATURAL := ceil_div(str'LENGTH, c_nibble_w);
     VARIABLE v_nibble_arr  : t_str_4_arr(0 TO c_nof_nibbles-1) := (OTHERS=>(OTHERS=>'0'));
diff --git a/libraries/base/dp/dp.peripheral.yaml b/libraries/base/dp/dp.peripheral.yaml
index 22ec8afb33b8e8755a86d7093a3b075c41408d9c..ba8ee5a641a7a9e761ad82207b562a499697639c 100644
--- a/libraries/base/dp/dp.peripheral.yaml
+++ b/libraries/base/dp/dp.peripheral.yaml
@@ -137,7 +137,7 @@ peripherals:
               address_offset: 0x4
               access_mode: RW
           - - field_name: bsn
-              field_description: "Initial BSN"
+              field_description: "Write: initial BSN. Read: BSN at last sync. First access lo, then hi."
               address_offset: 0x8
               user_width: 64
               radix: uint64
@@ -172,12 +172,12 @@ peripherals:
               bit_offset: 1
               mm_width: 1
               access_mode: RW
-          - - field_name: nof_block_per_sync
+          - - field_name: nof_clk_per_sync
               field_description: "Number of clock cycles per sync interval."
               address_offset: 0x4
               access_mode: RW
           - - field_name: bsn_init
-              field_description: "Initial BSN"
+              field_description: "Write: initial BSN. Read: BSN at last sync. First access lo, then hi."
               address_offset: 0x8
               user_width: 64
               radix: uint64
@@ -199,13 +199,66 @@ peripherals:
         mm_port_description: ""
         fields:
           - - field_name: scheduled_bsn
-              field_description: "Write scheduled BSN. First access lo, then hi."
+              field_description: "Write: scheduled BSN. Read: last BSN. First access lo, then hi."
               address_offset: 0x0
               user_width: 64
               radix: uint64
               access_mode: RW
 
               
+  - peripheral_name: dp_bsn_sync_scheduler    # pi_dp_bsn_sync_scheduler.py
+    peripheral_description: "Disable the output, or enable the output with a programmable sync interval."
+    mm_ports:
+      # MM port for mmp_dp_bsn_sync_scheduler.vhd
+      - mm_port_name: REG_DP_BSN_SYNC_SCHEDULER
+        mm_port_type: REG
+        mm_port_span: 16 * MM_BUS_SIZE
+        mm_port_description: ""
+        fields:
+          - - field_name: ctrl_enable
+              field_description: "Enable the output when 1, disable the output when 0. To first disable output to re-enable output."
+              address_offset: 0 * MM_BUS_SIZE  # = 0x0
+              mm_width: 1
+              access_mode: RW
+          - - field_name: ctrl_interval_size
+              field_description: "Number of samples in output sync interval"
+              address_offset: 1 * MM_BUS_SIZE  # = 0x4
+              access_mode: RW
+          - - field_name: ctrl_start_bsn
+              field_description:
+                "Schedule start BSN for the output. The start BSN needs to be in the future,
+                if the start BSN is in the past or if the input stream is not active, then
+                ctrl_enable = '1' will have no effect."
+              address_offset: 2 * MM_BUS_SIZE  # = 0x8
+              user_width: 64
+              radix: uint64
+              access_mode: RW
+          - - field_name: mon_current_input_bsn
+              field_description: "Current input BSN. This can be read to determine a start BSN in the future."
+              address_offset: 4 * MM_BUS_SIZE  # = 0x10
+              user_width: 64
+              radix: uint64
+              access_mode: RO
+          - - field_name: mon_output_enable
+              field_description:
+                "Is 1 when output is enabled, 0 when output is disabled. The output stream gets
+                 enabled when ctrl_enable is set '1' and when the BSN of the input stream has
+                 reached the ctrl_start_bsn."
+              address_offset: 6 * MM_BUS_SIZE  # = 0x18
+              mm_width: 1
+              access_mode: RO
+          - - field_name: mon_output_sync_bsn
+              field_description: "Output BSN at sync. This yields the number of blocks per output sync interval."
+              address_offset: 7 * MM_BUS_SIZE  # = 0x1C
+              user_width: 64
+              radix: uint64
+              access_mode: RO
+          - - field_name: block_size
+              field_description: "Number of samples per BSN block, same for input stream and output stream."
+              address_offset: 9 * MM_BUS_SIZE  # = 0x24
+              access_mode: RO
+
+
   - peripheral_name: dp_bsn_monitor    # pi_dp_bsn_monitor.py
     peripheral_description: "Monitor the Block Sequence Number (BSN) status of streaming data."
     parameters:
diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg
index c28801a8d2b92f1666074aa671d2f2c6aab0a5ab..9cc984efdde5e083ce57a73815e6cb4d062c570b 100644
--- a/libraries/base/dp/hdllib.cfg
+++ b/libraries/base/dp/hdllib.cfg
@@ -91,6 +91,8 @@ synth_files =
     src/vhdl/dp_bsn_scheduler.vhd
     src/vhdl/dp_bsn_scheduler_reg.vhd
     src/vhdl/mms_dp_bsn_scheduler.vhd
+    src/vhdl/dp_bsn_sync_scheduler.vhd
+    src/vhdl/mmp_dp_bsn_sync_scheduler.vhd
     src/vhdl/dp_bsn_delay.vhd
     src/vhdl/dp_bsn_align.vhd
     src/vhdl/dp_bsn_align_reg.vhd
@@ -214,6 +216,8 @@ test_bench_files =
     tb/vhdl/tb_dp_bsn_source_v2.vhd
     tb/vhdl/tb_mms_dp_bsn_source.vhd
     tb/vhdl/tb_mms_dp_bsn_source_v2.vhd
+    tb/vhdl/tb_dp_bsn_sync_scheduler.vhd
+    tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd
     tb/vhdl/tb_dp_demux.vhd
     tb/vhdl/tb2_dp_demux.vhd
     tb/vhdl/tb3_dp_demux.vhd
@@ -291,6 +295,7 @@ test_bench_files =
     tb/vhdl/tb_tb_dp_block_validate_channel.vhd
     tb/vhdl/tb_tb_dp_bsn_align.vhd
     tb/vhdl/tb_tb_dp_bsn_source_v2.vhd
+    tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd
     tb/vhdl/tb_tb_dp_concat.vhd
     tb/vhdl/tb_tb_dp_demux.vhd
     tb/vhdl/tb_tb2_dp_demux.vhd
@@ -347,7 +352,7 @@ regression_test_vhdl =
     tb/vhdl/tb_dp_bsn_source.vhd
     tb/vhdl/tb_mms_dp_bsn_source.vhd
     tb/vhdl/tb_mms_dp_bsn_source_v2.vhd
-    
+    tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd
     tb/vhdl/tb_tb_dp_block_select.vhd
     tb/vhdl/tb_tb_dp_block_validate_length.vhd
     tb/vhdl/tb_tb_dp_block_validate_err.vhd
@@ -360,6 +365,7 @@ regression_test_vhdl =
     tb/vhdl/tb_tb_dp_block_validate_channel.vhd
     tb/vhdl/tb_tb_dp_bsn_align.vhd
     tb/vhdl/tb_tb_dp_bsn_source_v2.vhd
+    tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd
     tb/vhdl/tb_tb_dp_concat.vhd
     tb/vhdl/tb_tb_dp_demux.vhd
     tb/vhdl/tb_tb2_dp_demux.vhd
diff --git a/libraries/base/dp/src/vhdl/dp_block_validate_channel.vhd b/libraries/base/dp/src/vhdl/dp_block_validate_channel.vhd
index e833f544fc370ec9ca50e407c4445b432e7ae735..8c9151c41a53679c011005d8a83edb6209afafc4 100644
--- a/libraries/base/dp/src/vhdl/dp_block_validate_channel.vhd
+++ b/libraries/base/dp/src/vhdl/dp_block_validate_channel.vhd
@@ -23,12 +23,12 @@
 -- Purpose:
 -- The dp_block_validate_channel.vhd can remove a block of data from a
 -- multiplexed in_sosi stream based on the in_sosi.channel field. 
--- If in_sosi.channel = g_remove_channel, then the in_sosi is passed on to 
+-- If in_sosi.channel = remove_channel, then the in_sosi is passed on to 
 -- remove_sosi and not passed on to keep_sosi, else vice versa.
 -- Other modes can be selected by setting g_mode. g_mode options are:
--- . "=" which removes all blocks with channel = g_remove_channel
--- . "<" which removes all blocks with channel < g_remove_channel
--- . ">" which removes all blocks with channel > g_remove_channel
+-- . "=" which removes all blocks with channel = remove_channel
+-- . "<" which removes all blocks with channel < remove_channel
+-- . ">" which removes all blocks with channel > remove_channel
 -- Remarks:
 
 LIBRARY IEEE, common_lib;
@@ -40,8 +40,7 @@ USE common_lib.common_mem_pkg.ALL;
 
 ENTITY dp_block_validate_channel IS
   GENERIC (
-    g_remove_channel : NATURAL := 0;
-    g_mode           : STRING  := "=" -- can be "=", "<", ">"
+    g_mode : STRING  := "=" -- can be "=", "<", ">"
   );
   PORT (
     dp_rst          : IN  STD_LOGIC;
@@ -50,7 +49,9 @@ ENTITY dp_block_validate_channel IS
     in_sosi         : IN  t_dp_sosi;
     -- ST source
     out_keep_sosi   : OUT t_dp_sosi;
-    out_remove_sosi : OUT t_dp_sosi
+    out_remove_sosi : OUT t_dp_sosi;
+
+    remove_channel  : IN  STD_LOGIC_VECTOR(c_dp_stream_channel_w-1 DOWNTO 0)
 
   );
 END dp_block_validate_channel;
@@ -65,17 +66,17 @@ ARCHITECTURE rtl OF dp_block_validate_channel IS
 BEGIN
 
   ASSERT g_mode = "=" OR g_mode = "<" OR g_mode = ">" REPORT "g_mode must be one of three options: '=', '<' or '>'" SEVERITY ERROR;
-  gen_equal   : IF g_mode = "=" GENERATE -- remove all blocks with ch = g_remove_channel
+  gen_equal   : IF g_mode = "=" GENERATE -- remove all blocks with ch = remove_channel
    remove_blk  <= remove_blk_reg WHEN in_sosi.sop = '0' ELSE 
-                             '1' WHEN TO_UINT(in_sosi.channel) = g_remove_channel ELSE '0';
+                             '1' WHEN UNSIGNED(in_sosi.channel) = UNSIGNED(remove_channel) ELSE '0';
   END GENERATE;
-  gen_smaller : IF g_mode = "<" GENERATE -- remove all blocks with ch < g_remove_channel
+  gen_smaller : IF g_mode = "<" GENERATE -- remove all blocks with ch < remove_channel
    remove_blk  <= remove_blk_reg WHEN in_sosi.sop = '0' ELSE 
-                             '1' WHEN TO_UINT(in_sosi.channel) < g_remove_channel ELSE '0';
+                             '1' WHEN UNSIGNED(in_sosi.channel) < UNSIGNED(remove_channel) ELSE '0';
   END GENERATE;
-  gen_larger  : IF g_mode = ">" GENERATE -- remove all blocks with ch > g_remove_channel
+  gen_larger  : IF g_mode = ">" GENERATE -- remove all blocks with ch > remove_channel
    remove_blk  <= remove_blk_reg WHEN in_sosi.sop = '0' ELSE 
-                             '1' WHEN TO_UINT(in_sosi.channel) > g_remove_channel ELSE '0';
+                             '1' WHEN UNSIGNED(in_sosi.channel) > UNSIGNED(remove_channel) ELSE '0';
   END GENERATE;
 
   p_dp_clk : PROCESS(dp_rst, dp_clk)
diff --git a/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd b/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..9c888558625dbd66a51de1eb75c8cb7ca028d70b
--- /dev/null
+++ b/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd
@@ -0,0 +1,388 @@
+-- --------------------------------------------------------------------------
+-- 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: Eric Kooistra, 30 July 2021
+-- Purpose : 
+--   Create programmable sync interval for input stream.
+-- Description:
+-- * ctrl_start_bsn:
+--   The output sync interval starts at an in_sosi.bsn that is programmable via
+--   ctrl_start_bsn. The c_ctrl_start_bsn must be in the future to enable
+--   output, otherwise the output is not enabled. The alternative to enable the
+--   output immediately in case the BSN is in the passed is easy for a user,
+--   because it then starts at any BSN, but that is not synchronous between
+--   FPGAs.
+-- * ctrl_interval_size:
+--   The output sync interval is programmable via ctrl_interval_size. The
+--   ctrl_interval_size is the number data samples per output sync interval,
+--   so an integer multiple sample periods. The g_block_size is the number of
+--   data samples per block.
+--   The output sync intervals are controlled such that on average the number
+--   of blocks per sync interval is nof_blk = ctrl_interval_size /
+--   g_block_size, also when they are not integer dividable.
+-- * ctrl_enable:
+--   The output is enabled at the ctrl_start_bsn when ctrl_enable = '1' and the
+--   output is disable after an in_sosi.eop when ctrl_enable = '0'. If the
+--   output is diabled, then the sosai control fields are forced to '0', the
+--   other sosi fields of the in_sosi are passed on to the out_sosi.
+-- * mon_current_input_bsn:
+--   The user can read mon_current_input_bsn to determine a suitable
+--   ctrl_start_bsn in the future.
+-- * mon_input_bsn_at_sync:
+--   The user can read mon_current_input_bsn to determine a suitable
+--   ctrl_start_bsn in the future to create a output sync interval that is
+--   aligned with the in_sosi.sync.
+-- * mon_output_enable:
+--   The user can read mon_output_enable to check whether the output is indeed
+--   enabled or not (mon_output_enable = out_enable).
+-- * mon_output_sync_bsn:
+--   The sync interval calculation is robust to lost in_sosi blocks. As soon
+--   as it receives a new in_sosi block it will try to determine the next
+--   output_sync_bsn, even if blocks were lost for multiple output sync
+--   intervals. If mon_output_sync_bsn - mon_current_input_bsn < 0 then the
+--   output sync interval calculation should catch up after some in_sosi
+--   blocks. If mon_output_sync_bsn - mon_current_input_bsn > nof_blk then
+--   something went wrong and then it may be necessary to recover using
+--   ctrl_enable. If mon_output_sync_bsn - mon_current_input_bsn < nof_blk and
+--   > 0 then that yields the number of blocks until the next output sync.
+-- * out_start:
+--   Pulse at out_sosi.sync with out_sosi.bsn = ctrl_start_bsn. The first
+--   out_sosi.sync interval will have nof_blk_max blocks.
+-- * out_enable:
+--   Goes high at first out_sosi.sync. In case of a restart when ctrl_enable
+--   was already '1', then the out_enable will go low and high to ensure that
+--   the restart out_sosi.sync interval will have nof_blk_max blocks. When
+--   ctrl_enable goes low or in case of a restart then out_enable will go
+--   low after an out_sosi.eop, to preserve complete out_sosi blocks. The
+--   out_enable is monitored via mon_output_enable, so that the user can
+--   check via MM whether an ctrl_enable access was applied. Typically the
+--   out_enable OUT can be left OPEN in an VHDL application, and only used for
+--   verification purposes in the test bench (tb).
+-- For example:
+--   . sample period Ts = 5 ns
+--   . g_block_size = 1024 samples
+--   . ctrl_start_bsn = 0
+--   . ctrl_interval_size = 200M
+--   ==>
+--   One block is g_block_size * Ts = 5.12 us
+--   nof_blk = ctrl_interval_size / g_block_size = 195312.5
+--   nof_blk_max = ceil(nof_blk) = 195313 = 1.00000256 s
+--   nof_blk_min = floor(nof_blk) = 195312 = 0.99999744 s
+--   The output sync interval is exactly 1 s on average, the even output sync
+--   periods (starting from inex 0 is even) will use nof_blk_max and the odd
+--   output sync periods will use nof_blk_min.
+--   If all FPGAs are started at the same ctrl_start_bsn, then the output sync
+--   interval is synchonous in the entire array of FPGAs.
+-- Remark:
+-- * The implementation avoids using division and modulo on signals (e.g.
+--   ctrl_interval_size / g_block_size) by using counters and fractions.
+-- * The implementation uses the input BSN to calculate when to output the
+--   scheduled output syncs. It has to be robust against lost input blocks,
+--   therfore it cannot count input valids to determine the scheduled output
+--   syncs.
+-- * This dp_bsn_sync_scheduler.vhd resembles dp_bsn_source_v2. The
+--   similarities are that both:
+--   . create the fractional output sync intervals,
+--   . start at an input trigger.
+--   The differences are that:
+--   . dp_bsn_sync_scheduler requires in_sosi.sync and copies the other in_sosi
+--     ctrl, info and data, whereas generates bs_sosi.ctrl.
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE common_lib.common_pkg.ALL;
+USE work.dp_stream_pkg.ALL;
+
+ENTITY dp_bsn_sync_scheduler IS
+  GENERIC (
+    g_bsn_w           : NATURAL := c_dp_stream_bsn_w;
+    g_block_size      : NATURAL := 256;  -- = number of data valid per BSN block, must be >= 2
+    g_pipeline        : NATURAL := 1     -- use '1' on HW, use '0' for easier debugging in Wave window
+  );
+  PORT (
+    rst                   : IN  STD_LOGIC;
+    clk                   : IN  STD_LOGIC;
+
+    -- M&C
+    ctrl_enable           : IN  STD_LOGIC;
+    ctrl_enable_evt       : IN  STD_LOGIC;
+    ctrl_interval_size    : IN  NATURAL;
+    ctrl_start_bsn        : IN  STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0');
+    mon_current_input_bsn : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+    mon_input_bsn_at_sync : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+    mon_output_enable     : OUT STD_LOGIC;
+    mon_output_sync_bsn   : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+
+    -- Streaming
+    in_sosi               : IN t_dp_sosi;
+    out_sosi              : OUT t_dp_sosi;
+    out_start             : OUT STD_LOGIC;  -- pulse at out_sosi.sync at ctrl_start_bsn
+    out_enable            : OUT STD_LOGIC   -- for tb verification purposes
+  );
+END dp_bsn_sync_scheduler;
+
+
+ARCHITECTURE rtl OF dp_bsn_sync_scheduler IS
+
+  TYPE t_reg IS RECORD
+    enable_init       : STD_LOGIC;
+    enable            : STD_LOGIC;
+    blk_cnt           : NATURAL;
+    interval_size     : NATURAL;
+    start_bsn         : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+    input_bsn         : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+    nof_blk_min       : NATURAL;
+    nof_blk_max       : NATURAL;
+    nof_blk           : NATURAL;
+    extra             : NATURAL RANGE 0 TO g_block_size;
+    accumulate        : NATURAL RANGE 0 TO g_block_size*2;
+    hold_eop          : STD_LOGIC;
+    update_bsn        : STD_LOGIC;
+    output_enable     : STD_LOGIC;
+    output_sync_bsn   : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+  END RECORD;
+
+  CONSTANT c_reg_rst  : t_reg := ('0', '0', 0, 0, (OTHERS=>'0'), (OTHERS=>'0'), 0, 0, 0, 0, 0, '1', '0', '0', (OTHERS=>'0'));
+
+  -- Local registers
+  SIGNAL r            : t_reg;
+  SIGNAL nxt_r        : t_reg;
+
+  SIGNAL output_start : STD_LOGIC;
+  SIGNAL output_sync  : STD_LOGIC;
+  SIGNAL output_sosi  : t_dp_sosi;
+
+BEGIN
+
+  ASSERT g_block_size >= 2 REPORT "g_block_size must be >= 2." SEVERITY FAILURE;
+
+  -- Capture monitoring info
+  mon_current_input_bsn <= in_sosi.bsn(g_bsn_w-1 DOWNTO 0) WHEN rising_edge(clk) AND in_sosi.sop = '1';
+  mon_input_bsn_at_sync <= in_sosi.bsn(g_bsn_w-1 DOWNTO 0) WHEN rising_edge(clk) AND in_sosi.sync = '1';
+  mon_output_enable     <= r.output_enable;
+  mon_output_sync_bsn   <= r.output_sync_bsn;
+
+  p_clk : PROCESS(rst, clk)
+  BEGIN
+    IF rst='1' THEN
+      r <= c_reg_rst;
+    ELSIF rising_edge(clk) THEN
+      r <= nxt_r;
+    END IF;
+  END PROCESS;
+
+  p_comb : PROCESS(r, ctrl_enable, ctrl_enable_evt, ctrl_interval_size, ctrl_start_bsn, in_sosi)
+    VARIABLE v      : t_reg;
+    VARIABLE v_size : NATURAL;
+  BEGIN
+    v := r;
+    output_start <= '0';
+    output_sync <= '0';
+
+    -- Detect ctrl_enable rising event
+    IF ctrl_enable = '1' AND ctrl_enable_evt = '1' THEN
+      v.enable_init := '1';
+    END IF;
+
+    -- Initialization: calculate number of blocks per output sync interval
+    -- . use r.enable_init instead of v.enable_init to easy timing closure and
+    --   because functionally it makes no difference.
+    IF r.enable_init = '1' THEN
+      -- Assume ctrl_start_bsn is scheduled more than nof_blk block clk cycles
+      -- after the ctrl_enable_evt, so there is sufficient time until
+      -- v.output_enable = '1', to perform the calculation of nof_blk_min and
+      -- nof_blk_max sequentially. This avoids using division in logic to
+      -- calculate ctrl_interval_size / g_block_size.
+      v_size := r.blk_cnt * g_block_size;
+      IF v_size = ctrl_interval_size THEN
+        -- Support integer number of blocks per output sync interval
+        v.interval_size := ctrl_interval_size;  -- hold ctrl_interval_size
+        v.start_bsn := ctrl_start_bsn;          -- hold ctrl_start_bsn
+        -- Fixed sync interval control, effectively disable fractional sync interval control:
+        v.nof_blk_min := r.blk_cnt;
+        v.nof_blk_max := r.blk_cnt;
+        v.nof_blk := r.blk_cnt;                 -- nof_blk = nof_blk_max = nof_blk_min
+        v.extra := 0;
+        v.accumulate := 0;
+        v.enable_init := '0';                   -- enable initialization is done
+      ELSIF v_size > ctrl_interval_size THEN
+        -- Support fractional number of blocks per output sync interval
+        v.interval_size := ctrl_interval_size;  -- hold ctrl_interval_size
+        v.start_bsn := ctrl_start_bsn;          -- hold ctrl_start_bsn
+        -- Fractional sync interval control:
+        v.nof_blk_min := r.blk_cnt - 1;
+        v.nof_blk_max := r.blk_cnt;
+        v.nof_blk := r.blk_cnt;                 -- start with nof_blk_max sync interval
+        v.extra := v_size - ctrl_interval_size; -- number of extra samples in nof_blk_max compared to ctrl_interval_size
+        v.accumulate := v.extra;                -- start with nof_blk_max sync interval
+        v.enable_init := '0';                   -- enable initialization is done
+      ELSE
+        v.blk_cnt := r.blk_cnt + 1;
+      END IF;
+    ELSE
+      v.blk_cnt := 0;
+    END IF;
+
+    -- Enable / disable control
+    IF ctrl_enable = '0' THEN
+      -- Disable output when ctrl_enable requests disable.
+      v.enable := '0';
+    ELSIF ctrl_enable_evt = '1' THEN
+      -- ctrl_enable is on, so this is a re-enable. First disable output.
+      v.enable := '0';
+    ELSIF r.enable_init = '0' THEN
+      -- ctrl_enable is still on, so now enable the output. In case of an
+      -- enable, then the output was already disabled. In case of a re-enable,
+      -- then wait until the output got disabled.
+      -- Enabling the output from disabled state ensures that the output will
+      -- start or restart with nof_blk_max in the first sync interval.
+      -- Otherwise with re-enabling from enabled state, it is undefined
+      -- whether the first sync interval after the restart will have
+      -- nof_blk_min or nof_blk_max blocks.
+      IF r.output_enable = '0' THEN
+        v.enable := '1';
+      END IF;
+    END IF;
+
+    -- Hold input eop to detect when input has finished a block and to detect
+    -- gaps between in_sosi.eop and in_sosi.sop
+    IF in_sosi.sop = '1' THEN
+      v.hold_eop := '0';
+    END IF;
+    IF in_sosi.eop = '1' THEN
+      v.hold_eop := '1';
+    END IF;
+
+    IF v.enable = '1' THEN
+      -- Output enable at in_sosi.sop start_bsn
+      IF in_sosi.sop = '1' THEN
+        IF UNSIGNED(in_sosi.bsn) = UNSIGNED(r.start_bsn) THEN
+          v.output_enable := '1';
+          output_start <= '1';  -- Pulse at start of output enable at start BSN of output sync intervals
+          v.output_sync_bsn := r.start_bsn;  -- Initialize output sync at start BSN of output sync intervals
+        END IF;
+      END IF;
+    ELSE
+      -- Output disable after in_sosi.eop
+      IF r.hold_eop = '1' THEN
+        v.output_enable := '0';
+      END IF;
+    END IF;
+
+    -- Generate output sync interval based on input BSN and ctrl_interval_size
+    IF v.output_enable = '1' THEN
+      IF in_sosi.sop = '1' THEN
+        IF UNSIGNED(in_sosi.bsn) = UNSIGNED(v.output_sync_bsn) THEN
+          -- Matching input block
+          output_sync <= '1';  -- The output sync interval
+          v.update_bsn := '1';
+        ELSIF UNSIGNED(in_sosi.bsn) > UNSIGNED(v.output_sync_bsn) THEN
+          -- Missed one or more input blocks, so cannot output sync, look for
+          -- next opportunity
+          v.update_bsn := '1';
+        END IF;
+      END IF;
+    END IF;
+
+    -- Determine BSN for next output sync
+    IF r.update_bsn = '1' THEN
+      -- Similar code as in proc_dp_verify_sync(), the difference is that:
+      -- . Here r.extra is number of extra samples in nof_blk_max compared to
+      --   ctrl_interval_size,
+      -- . in proc_dp_verify_sync() r.extra is number of extra samples in
+      --   ctrl_interval_size compared to nof_blk_min.
+      -- Both schemes are valid, by using different schemes here and in tb the
+      -- verification coverage improves.
+      v.output_sync_bsn := ADD_UVEC(r.output_sync_bsn, TO_UVEC(r.nof_blk, c_natural_w));  -- next BSN
+
+      v.nof_blk := r.nof_blk_max;
+      v.accumulate := r.accumulate + r.extra;  -- account for nof_blk_max
+      IF v.accumulate >= g_block_size THEN
+        v.nof_blk := r.nof_blk_min;
+        v.accumulate := v.accumulate - g_block_size;  -- adjust for nof_blk_min
+      END IF;
+
+      -- Assume output_sync_bsn is in future
+      v.update_bsn := '0';
+
+      -- else: last r.input_bsn will be used to keep update_bsn active for
+      -- more clk cycles to catch up for lost input blocks.
+    END IF;
+
+    -- Hold input bsn
+    IF in_sosi.sop = '1' THEN
+      v.input_bsn := in_sosi.bsn(g_bsn_w-1 DOWNTO 0);
+    END IF;
+
+    -- Catch up with output_sync_bsn in case of lost input blocks. If many
+    -- input blocks were lost (e.g. > nof_blk_max), then catching up the
+    -- output_sync_bsn to the current input_bsn can cause that one or more
+    -- output_sync will not be made active, but that is acceptable in case
+    -- recovery from of lost input blocks.
+    IF v.output_enable = '1' THEN
+      IF UNSIGNED(r.input_bsn) > UNSIGNED(v.output_sync_bsn) THEN
+        -- Missed one or more input blocks, fast forward to look for next
+        -- output_sync_bsn in every clk cycle.
+        v.update_bsn := '1';
+      END IF;
+    END IF;
+
+    nxt_r <= v;
+  END PROCESS;
+
+  -- Output in_sosi with programmed sync interval or disable the output
+  p_output_sosi : PROCESS(in_sosi, nxt_r, output_sync)
+  BEGIN
+    output_sosi <= in_sosi;
+    IF nxt_r.output_enable = '1' THEN
+      output_sosi.sync <= output_sync;
+    ELSE
+      output_sosi.sync  <= '0';
+      output_sosi.sop   <= '0';
+      output_sosi.eop   <= '0';
+      output_sosi.valid <= '0';
+    END IF;
+  END PROCESS;
+
+  -- Pipeline output to avoid timing closure problems due to use of nxt_r.output_enable
+  u_out_sosi : ENTITY work.dp_pipeline
+  GENERIC MAP (
+    g_pipeline  => g_pipeline
+  )
+  PORT MAP (
+    rst          => rst,
+    clk          => clk,
+    -- ST sink
+    snk_in       => output_sosi,
+    -- ST source
+    src_out      => out_sosi
+  );
+
+  gen_pipe_out_start : IF g_pipeline = 1 GENERATE
+    out_start <= output_start WHEN rising_edge(clk);
+    out_enable <= r.output_enable;
+  END GENERATE;
+  no_pipe_out_start : IF g_pipeline = 0 GENERATE
+    out_start <= output_start;
+    out_enable <= nxt_r.output_enable;
+  END GENERATE;
+
+END rtl;
+
+
diff --git a/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd b/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd
index 677d106cf4f081b06f34da46a8d4a8adc99317ef..dece1acc5d05756e51fa4ce82e21175e5b9903c6 100644
--- a/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd
+++ b/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd
@@ -265,6 +265,7 @@ PACKAGE dp_stream_pkg Is
   FUNCTION INCR_DP_SDATA(   vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR;  --   signed vec(w-1:0) + dec
   FUNCTION INCR_DP_DSP_DATA(vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR;  --   signed vec(w-1:0) + dec
   FUNCTION INCR_DP_BSN(     vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR;  -- unsigned vec(w-1:0) + dec
+  FUNCTION INCR_DP_CHANNEL( vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR;  -- unsigned vec(w-1:0) + dec
   
   FUNCTION REPLICATE_DP_DATA(  seq  : STD_LOGIC_VECTOR                 ) RETURN STD_LOGIC_VECTOR;  -- replicate seq as often as fits in c_dp_stream_data_w
   FUNCTION UNREPLICATE_DP_DATA(data : STD_LOGIC_VECTOR; seq_w : NATURAL) RETURN STD_LOGIC_VECTOR;  -- unreplicate data to width seq_w, return low seq_w bits and set mismatch MSbits bits to '1'
@@ -578,6 +579,12 @@ PACKAGE BODY dp_stream_pkg IS
   BEGIN
     RETURN RESIZE_DP_BSN(STD_LOGIC_VECTOR(UNSIGNED(vec(w-1 DOWNTO 0)) + dec));
   END INCR_DP_BSN;
+  
+  FUNCTION INCR_DP_CHANNEL(vec : STD_LOGIC_VECTOR; dec : INTEGER; w : NATURAL) RETURN STD_LOGIC_VECTOR IS
+  BEGIN
+    RETURN RESIZE_DP_CHANNEL(STD_LOGIC_VECTOR(UNSIGNED(vec(w-1 DOWNTO 0)) + dec));
+  END INCR_DP_CHANNEL;
+
 
   FUNCTION REPLICATE_DP_DATA(seq : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
     CONSTANT c_seq_w            : NATURAL := seq'LENGTH;
diff --git a/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler.vhd b/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..842fa3175e688d1c4048b4417abd2a526e9e6579
--- /dev/null
+++ b/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler.vhd
@@ -0,0 +1,216 @@
+-- --------------------------------------------------------------------------
+-- 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 : E. Kooistra, 6 aug 2021
+-- Purpose : MM peripheral interface for dp_bsn_sync_scheduler.vhd
+-- Description: MM port register logic
+--
+--  wi    Bits  Access     Type   Name
+--   0     [0]      RW  boolean   ctrl_enable, '1' is on, '0' is FALSE is off
+--   1  [31:0]      RW   uint32   ctrl_interval_size
+--   2  [31:0]      RW   uint64   ctrl_start_bsn[31:0]
+--   3  [31:0]      RW            ctrl_start_bsn[63:32]
+--   4  [31:0]      RO   uint64   mon_current_input_bsn[31:0]
+--   5  [31:0]      RO            mon_current_input_bsn[63:32]
+--   6  [31:0]      RO   uint64   mon_input_bsn_at_sync[31:0]
+--   7  [31:0]      RO            mon_input_bsn_at_sync[63:32]
+--   8     [0]      RO  boolean   mon_output_enable, '1' is on, '0' is FALSE is off
+--   9  [31:0]      RO   uint64   mon_output_sync_bsn[31:0]
+--  10  [31:0]      RO            mon_output_sync_bsn[63:32]
+--  11  [31:0]      RO   uint32   block_size[31:0]
+--
+-- * Do not use reg_wr_arr[0] in dp_clk domain to detect ctrl_enable_evt,
+--   because reg_wr_arr pulses occur before the reg_wr data arrives in the
+--   dp_clk domain. Therefore instead use change in wr_ctrl_enable value
+--   to detect ctrl_enable_evt. Hence a re-enable via MM now requires a
+--   disable via MM first.
+--
+-- Remarks:
+-- * The actual bsn width is constrained by g_bsn_w.
+-- * The MM interface accesses 64 bit words in two 32 bit MM word accesses.
+--   This can result in a BSN value that is wrong if it happens to have
+--   an increment carry from the low word to the high word. The BSN carry
+--   occurs after every 2**32 blocks, so e.g. with a block period of 5.12 us
+--   this is once every 6.1 hours. It is very unlikely that this will cause
+--   a problem and if it does then a next attempt will succeed. Therefore
+--   it is not necessary to ensure that the 64 values are accesses more
+--   robustly (e.g. by only accepting them when the high word is accessed),
+--   and therefore it is fine to use common_reg_r_w_dc for 64 bit BSN words.
+--
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE work.dp_stream_pkg.ALL;
+
+
+ENTITY mmp_dp_bsn_sync_scheduler IS
+  GENERIC (
+    g_bsn_w         : NATURAL := c_dp_stream_bsn_w;
+    g_block_size    : NATURAL := 256   -- = number of data valid per BSN block, must be >= 2
+  );
+  PORT (
+    -- Clocks and reset
+    mm_rst          : IN  STD_LOGIC;
+    mm_clk          : IN  STD_LOGIC;
+    dp_rst          : IN  STD_LOGIC;
+    dp_clk          : IN  STD_LOGIC;
+
+    -- MM control
+    reg_mosi        : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_miso        : OUT t_mem_miso;
+
+    -- Streaming
+    in_sosi         : IN t_dp_sosi;
+    out_sosi        : OUT t_dp_sosi;
+    out_start       : OUT STD_LOGIC;
+    out_enable      : OUT STD_LOGIC
+  );
+END mmp_dp_bsn_sync_scheduler;
+
+ARCHITECTURE str OF mmp_dp_bsn_sync_scheduler IS
+
+  -- TYPE t_c_mem IS RECORD
+  --   latency   : NATURAL;    -- read latency
+  --   adr_w     : NATURAL;
+  --   dat_w     : NATURAL;
+  --   nof_dat   : NATURAL;    -- optional, nof dat words <= 2**adr_w
+  --   init_sl   : STD_LOGIC;  -- optional, init all dat words to std_logic '0', '1' or 'X'
+  CONSTANT c_mm_reg         : t_c_mem := (1, 4, c_word_w, 12, '0');
+
+  SIGNAL reg_wr_arr         : STD_LOGIC_VECTOR(c_mm_reg.nof_dat               -1 DOWNTO 0);
+  SIGNAL reg_wr             : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0);
+  SIGNAL reg_rd             : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0');
+
+  SIGNAL wr_ctrl_enable        : STD_LOGIC;
+  SIGNAL wr_ctrl_enable_evt    : STD_LOGIC;
+  SIGNAL ctrl_enable           : STD_LOGIC := '0';
+  SIGNAL ctrl_enable_evt       : STD_LOGIC := '0';
+  SIGNAL ctrl_interval_size    : NATURAL;
+  SIGNAL ctrl_start_bsn        : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0');
+  SIGNAL mon_current_input_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+  SIGNAL mon_input_bsn_at_sync : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+  SIGNAL mon_output_enable     : STD_LOGIC;
+  SIGNAL mon_output_sync_bsn   : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0);
+
+  -- Resize BSN values to 64 bit
+  SIGNAL wr_start_bsn_64           : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0);
+  SIGNAL rd_current_input_bsn_64   : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0);
+  SIGNAL rd_input_bsn_at_sync_64   : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0);
+  SIGNAL rd_output_sync_bsn_64     : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0);
+
+BEGIN
+
+  ctrl_start_bsn <= wr_start_bsn_64(g_bsn_w-1 DOWNTO 0);
+
+  rd_current_input_bsn_64 <= RESIZE_UVEC(mon_current_input_bsn, 2*c_word_w);
+  rd_input_bsn_at_sync_64 <= RESIZE_UVEC(mon_input_bsn_at_sync, 2*c_word_w);
+  rd_output_sync_bsn_64   <= RESIZE_UVEC(mon_output_sync_bsn,   2*c_word_w);
+
+  -- Register mapping
+  -- . Write
+  wr_ctrl_enable                                  <=         reg_wr(                              0);
+  ctrl_interval_size                              <= TO_UINT(reg_wr( 2*c_word_w-1 DOWNTO 1*c_word_w));
+  wr_start_bsn_64(  c_word_w-1 DOWNTO          0) <=         reg_wr( 3*c_word_w-1 DOWNTO 2*c_word_w);  -- low word
+  wr_start_bsn_64(2*c_word_w-1 DOWNTO 1*c_word_w) <=         reg_wr( 4*c_word_w-1 DOWNTO 3*c_word_w);  -- high word
+
+  -- Derive ctrl_enable_evt from change in wr_ctrl_enable, instead of using
+  -- reg_wr_arr(0), see description
+  u_common_evt : ENTITY common_lib.common_evt
+  GENERIC MAP (
+    g_evt_type   => "BOTH",
+    g_out_reg    => TRUE
+  )
+  PORT MAP (
+    rst      => dp_rst,
+    clk      => dp_clk,
+    in_sig   => wr_ctrl_enable,
+    out_evt  => wr_ctrl_enable_evt
+  );
+
+  ctrl_enable     <= wr_ctrl_enable     WHEN rising_edge(dp_clk) AND wr_ctrl_enable_evt = '1';
+  ctrl_enable_evt <= wr_ctrl_enable_evt WHEN rising_edge(dp_clk);
+
+  -- . Read
+  reg_rd(                               0) <= ctrl_enable;  -- read back internal ctrl_enable
+  reg_rd( 2*c_word_w-1 DOWNTO  1*c_word_w) <= TO_UVEC(ctrl_interval_size, c_word_w);
+  reg_rd( 3*c_word_w-1 DOWNTO  2*c_word_w) <= wr_start_bsn_64(          c_word_w-1 DOWNTO        0);  -- low word
+  reg_rd( 4*c_word_w-1 DOWNTO  3*c_word_w) <= wr_start_bsn_64(        2*c_word_w-1 DOWNTO c_word_w);  -- high word
+  reg_rd( 5*c_word_w-1 DOWNTO  4*c_word_w) <= rd_current_input_bsn_64(  c_word_w-1 DOWNTO        0);  -- low word
+  reg_rd( 6*c_word_w-1 DOWNTO  5*c_word_w) <= rd_current_input_bsn_64(2*c_word_w-1 DOWNTO c_word_w);  -- high word
+  reg_rd( 7*c_word_w-1 DOWNTO  6*c_word_w) <= rd_input_bsn_at_sync_64(  c_word_w-1 DOWNTO        0);  -- low word
+  reg_rd( 8*c_word_w-1 DOWNTO  7*c_word_w) <= rd_input_bsn_at_sync_64(2*c_word_w-1 DOWNTO c_word_w);  -- high word
+  reg_rd(                      8*c_word_w) <= mon_output_enable;
+  reg_rd(10*c_word_w-1 DOWNTO  9*c_word_w) <= rd_output_sync_bsn_64(    c_word_w-1 DOWNTO        0);  -- low word
+  reg_rd(11*c_word_w-1 DOWNTO 10*c_word_w) <= rd_output_sync_bsn_64(  2*c_word_w-1 DOWNTO c_word_w);  -- high word
+  reg_rd(12*c_word_w-1 DOWNTO 11*c_word_w) <= TO_UVEC(g_block_size, c_word_w);
+
+  u_common_reg_r_w_dc : ENTITY common_lib.common_reg_r_w_dc
+  GENERIC MAP (
+    g_cross_clock_domain   => TRUE,
+    g_readback             => FALSE,
+    g_reg                  => c_mm_reg
+  )
+  PORT MAP (
+    -- Clocks and reset
+    mm_rst         => mm_rst,
+    mm_clk         => mm_clk,
+    st_rst         => dp_rst,
+    st_clk         => dp_clk,
+
+    -- Memory Mapped Slave in mm_clk domain
+    sla_in         => reg_mosi,
+    sla_out        => reg_miso,
+
+    -- MM registers in st_clk domain
+    reg_wr_arr     => reg_wr_arr,
+    reg_rd_arr     => OPEN,
+    out_reg        => reg_wr,   -- readback via ST clock domain
+    in_reg         => reg_rd
+  );
+
+  u_dp_bsn_sync_scheduler : ENTITY work.dp_bsn_sync_scheduler
+  GENERIC MAP (
+    g_bsn_w         => g_bsn_w,
+    g_block_size    => g_block_size,
+    g_pipeline      => 1
+  )
+  PORT MAP (
+    rst                   => dp_rst,
+    clk                   => dp_clk,
+
+    -- M&C
+    ctrl_enable           => ctrl_enable,
+    ctrl_enable_evt       => ctrl_enable_evt,
+    ctrl_interval_size    => ctrl_interval_size,
+    ctrl_start_bsn        => ctrl_start_bsn,
+    mon_current_input_bsn => mon_current_input_bsn,
+    mon_input_bsn_at_sync => mon_input_bsn_at_sync,
+    mon_output_enable     => mon_output_enable,
+    mon_output_sync_bsn   => mon_output_sync_bsn,
+
+    -- Streaming
+    in_sosi               => in_sosi,
+    out_sosi              => out_sosi,
+    out_start             => out_start,
+    out_enable            => out_enable
+  );
+
+END str;
+
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_channel.vhd b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_channel.vhd
index a1ec94568689273a16f8f2f889223d7888634c62..ce5232b6867c71d18c9acb2115ba132912de1e0c 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_channel.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_channel.vhd
@@ -113,18 +113,19 @@ BEGIN
   ------------------------------------------------------------------------------     
   u_dut : ENTITY work.dp_block_validate_channel
   GENERIC MAP (
-    g_remove_channel => g_remove_channel, 
-    g_mode           => g_mode 
+    g_mode          => g_mode 
   )
   PORT MAP (
-    dp_rst           => rst,
-    dp_clk           => dp_clk,
+    dp_rst          => rst,
+    dp_clk          => dp_clk,
 
     -- ST sink
-    in_sosi          => stimuli_sosi,
+    in_sosi         => stimuli_sosi,
     -- ST source
-    out_keep_sosi    => keep_sosi,
-    out_remove_sosi  => remove_sosi
+    out_keep_sosi   => keep_sosi,
+    out_remove_sosi => remove_sosi,
+
+    remove_channel  => TO_UVEC(g_remove_channel, 32)
   );
 
   
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_bsn_source_v2.vhd b/libraries/base/dp/tb/vhdl/tb_dp_bsn_source_v2.vhd
index 2e701d81502e0eb51d9ced01318b5187a8fde452..7f15f845fc365470ac223203310aa98097df13eb 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_bsn_source_v2.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_bsn_source_v2.vhd
@@ -46,7 +46,8 @@ USE dp_lib.tb_dp_pkg.ALL;
 
 ENTITY tb_dp_bsn_source_v2 IS
   GENERIC (
-    g_pps_interval : NATURAL := 240;
+    g_nof_pps      : NATURAL := 20;
+    g_pps_interval : NATURAL := 230;
     g_block_size   : NATURAL := 32 
   );
 END tb_dp_bsn_source_v2;
@@ -97,6 +98,9 @@ ARCHITECTURE tb OF tb_dp_bsn_source_v2 IS
   SIGNAL expected_sync_dly   : STD_LOGIC := '0';
   SIGNAL expected_bsn        : NATURAL   := 0;
   SIGNAL expected_offset_bsn : NATURAL   := 0;
+  SIGNAL dbg_nof_blk         : NATURAL   := 0;
+  SIGNAL dbg_accumulate      : NATURAL   := 0;
+  SIGNAL dbg_expected_bsn    : NATURAL   := 0;
 
 BEGIN
 
@@ -161,7 +165,7 @@ BEGIN
     dp_on_pps <= '0';
     dp_on     <= '1';
     verify_sync <= '0';  -- only verify visualy in wave window
-    proc_common_wait_some_cycles(clk, 10*g_pps_interval);
+    proc_common_wait_some_cycles(clk, g_nof_pps*g_pps_interval);
     verify_sync <= '0';
     -- Stop by making dp_on low
     tb_state <= s_disable;
@@ -191,7 +195,7 @@ BEGIN
       dp_on_pps <= '1';
       dp_on     <= '1';
       verify_sync <= '1';  -- verify automatically in test bench
-      proc_common_wait_some_cycles(clk, 10*g_pps_interval);
+      proc_common_wait_some_cycles(clk, g_nof_pps*g_pps_interval);
       verify_sync <= '0';
       -- Stop by making dp_on low
       tb_state <= s_disable;
@@ -219,6 +223,23 @@ BEGIN
   proc_dp_verify_sop_and_eop(clk, bs_sosi.valid, bs_sosi.sop, bs_sosi.eop, hold_bs_sop);  -- Verify that sop and eop come in pairs
   proc_dp_verify_sync(clk, verify_sync, bs_sosi.sync, bs_sosi.sop, expected_sync_dly);  -- Verify sync at sop and at expected_sync
 
+  -- Verify sync at sop and at expected_sync again:
+  -- . now using the proc_dp_verify_sync() variant for dp_bsn_source_v2 that
+  --   can verify fractional sync periods.
+  -- . the proc_dp_verify_sync() v2 variant was made later, so in fact
+  --   this tb_dp_bsn_source_v2 verifies this new v2 procedure.
+  proc_dp_verify_sync(TO_UINT(bsn_init),
+                      g_pps_interval,
+                      g_block_size,
+                      clk,
+                      verify_sync,
+                      bs_sosi.sync,
+                      bs_sosi.sop,
+                      bs_sosi.bsn,
+                      dbg_nof_blk,
+                      dbg_accumulate,
+                      dbg_expected_bsn);
+
   -----------------------------------------------------------------------------
   -- DUT: dp_bsn_source_v2
   -----------------------------------------------------------------------------
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_bsn_sync_scheduler.vhd b/libraries/base/dp/tb/vhdl/tb_dp_bsn_sync_scheduler.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a94570c92e294b528d12f0d07819f6dad441fb7e
--- /dev/null
+++ b/libraries/base/dp/tb/vhdl/tb_dp_bsn_sync_scheduler.vhd
@@ -0,0 +1,570 @@
+-------------------------------------------------------------------------------
+-- --------------------------------------------------------------------------
+-- 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: Eric Kooistra
+-- Purpose: Test bench for dp_bsn_sync_scheduler.vhd
+-- Description:
+--   The tb automatically TODO verifies the following cases:
+--   * when enabled the out_sosi = in_sosi, except for the output sync
+--     interval
+--   * disabling the output and re-enabling the output using
+--     c_nof_test_intervals
+--   * c_ctrl_start_bsn must be in the future, else output remains disabled
+--   * gaps between input blocks using g_input_gap_size > 0
+--   * output sync intervals that have fractional number of blocks using
+--     ctrl_interval_size = g_nof_samples_per_output_sync
+--   * output sync interval recovery in case of lost input blocks
+-- Usage:
+-- > as 4
+-- > run -all
+--   View in Wave window u_dut: r, nxt_r, and tb: in_sosi, out_sosi,
+--   out_sync, out_start
+--
+-- Development steps:
+--  . Step    1 ~1 day work (idea started earlier, so requirements were clear),
+--    steps 2,5 ~2 days work (fixing details and verifying all features),
+--    steps 3,4 ~1 day work,
+--    total ~4 days work spent in ~ 1 week.
+-- 1a Draft design description of dp_bsn_sync_scheduler
+--  b Initial implementation that compiles
+-- 2a Initial tb using u_stimuli to generate in_sosi and using p_stimuli
+--    to test basic functionality, i.e. to get out_sosi when ctrl_enable is
+--    on and no output when off.
+--  b Verify that g_input_gap_size > 0 also works
+--  c Add verification of out_sosi = in sosi when enabled
+--    (proc_dp_verify_sosi_equal)
+--  d Add verification of out_sosi (p_verify_out_enable)
+--  e Add verification of out_start and first out_sync (p_verify_out_start)
+--  f Add verification of out_sosi.sync using proc_dp_verify_sync() for
+--    fractional sync intervals
+--  g Add verification of mon_output_sync_bsn (p_verify_mon_output_sync_bsn)
+-- 3a Add tb generics and tb_tb_dp_bsn_sync_scheduler.vhd
+-- 4a Add mmp_dp_bsn_sync_scheduler.vhd with MM register and
+--    tb_mmp_dp_bsn_sync_scheduler.vhd that verifies only the MM part,
+--    because the sync part is already verified by
+--    tb_tb_dp_bsn_sync_scheduler.vhd.
+-- 5a For all ASSERTs, verify that the ERROR or FAILURE can occur by e.g.
+--    temporarily changing the ASSERT condition
+--  b Initialy used LOOP in p_stimuli to repeat test. Later used list of
+--    c_nof_test_intervals and tb_state to try different stimuli.
+
+LIBRARY IEEE, common_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_str_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE dp_lib.tb_dp_pkg.ALL;
+
+ENTITY tb_dp_bsn_sync_scheduler IS
+  GENERIC (
+    -- Input sync period and sosi ctrl
+    g_nof_input_sync               : NATURAL := 10;
+    g_nof_block_per_input_sync     : NATURAL := 17;
+    g_block_size                   : NATURAL := 10;
+    g_input_gap_size               : NATURAL := 3;
+
+    -- Output sync period
+    g_nof_samples_per_output_sync  : NATURAL := 45  -- 45 / g_block_size = 4.5
+  );
+END tb_dp_bsn_sync_scheduler;
+
+ARCHITECTURE tb OF tb_dp_bsn_sync_scheduler IS
+
+  CONSTANT c_clk_period                   : TIME    := 10 ns;
+  CONSTANT c_bsn_w                        : NATURAL := 31;
+  CONSTANT c_dut_latency                  : NATURAL := 1;
+
+  -- Test intervals
+  CONSTANT c_nof_test_intervals           : NATURAL := 4;  -- nof should be large enough for p_stimuli
+  CONSTANT c_nof_block_per_test_interval  : NATURAL := g_nof_block_per_input_sync * g_nof_input_sync;
+  CONSTANT c_nof_lost_input_blocks        : NATURAL := g_nof_block_per_input_sync * 4 + 3;
+  CONSTANT c_nof_clk_per_block            : NATURAL := g_block_size + g_input_gap_size;
+  CONSTANT c_nof_clk_per_test_interval    : NATURAL := c_nof_clk_per_block * c_nof_block_per_test_interval;
+  CONSTANT c_begin_of_test_interval       : NATURAL := 0 + c_nof_clk_per_block * 4;                             -- just after start
+  CONSTANT c_early_in_test_interval       : NATURAL := c_nof_clk_per_test_interval / 3;                         -- just after begin and before mid
+  CONSTANT c_mid_of_test_interval         : NATURAL := c_nof_clk_per_test_interval / 2;                         -- at mid
+  CONSTANT c_end_of_test_interval         : NATURAL := c_nof_clk_per_test_interval - c_nof_clk_per_block * 3;   -- just before end
+
+  CONSTANT c_sim_nof_blocks               : NATURAL := c_nof_block_per_test_interval * c_nof_test_intervals;
+
+  CONSTANT c_output_nof_blocks_min        : NATURAL := g_nof_samples_per_output_sync / g_block_size;
+  CONSTANT c_enable_init_nof_bsn          : NATURAL := ceil_value(c_output_nof_blocks_min / g_block_size + 10, g_nof_block_per_input_sync);
+
+  SIGNAL clk                   : STD_LOGIC := '1';
+  SIGNAL rst                   : STD_LOGIC := '1';
+  SIGNAL cnt                   : INTEGER := 0;
+  SIGNAL test_interval         : INTEGER := 0;
+  SIGNAL tb_end                : STD_LOGIC := '0';
+
+  TYPE t_stimuli_state_enum IS (  -- use short names to ease unzoomed view in Wave window
+    e_dis,      -- disable
+    e_en,       -- enable
+    e_re,       -- re-enable
+    e_lost,     -- lost input blocks
+    e_old       -- start bsn in passed
+  );
+  SIGNAL stimuli_state         : t_stimuli_state_enum := e_dis;  -- to show what tb does in Wave window
+
+  -- Stimuli
+  SIGNAL ctrl_enable           : STD_LOGIC := '0';
+  SIGNAL ctrl_enable_evt       : STD_LOGIC := '0';
+  SIGNAL ctrl_interval_size    : NATURAL := g_nof_samples_per_output_sync;
+  SIGNAL ctrl_start_bsn        : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := (OTHERS=>'0');
+  SIGNAL mon_current_input_bsn : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
+  SIGNAL mon_input_bsn_at_sync : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
+  SIGNAL mon_output_enable     : STD_LOGIC;
+  SIGNAL mon_output_sync_bsn   : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
+  SIGNAL out_sop_dly           : STD_LOGIC;
+
+  SIGNAL stimuli_sosi          : t_dp_sosi := c_dp_sosi_init;
+  SIGNAL stimuli_sync          : STD_LOGIC;  -- declared next to stimuli_sosi and out_sync for easier comparison in Wave window
+
+  -- Input stimuli
+  SIGNAL in_lost               : STD_LOGIC := '0';
+  SIGNAL in_sosi               : t_dp_sosi := c_dp_sosi_init;  -- = stimuli_sosi, with option for lost blocks
+  SIGNAL in_sync               : STD_LOGIC;
+
+  -- Output
+  SIGNAL out_sync              : STD_LOGIC;  -- declared next to in_sync, out_start and out_sosi for easier comparison in Wave window
+  SIGNAL out_start             : STD_LOGIC;
+  SIGNAL out_enable            : STD_LOGIC;
+  SIGNAL out_sosi              : t_dp_sosi := c_dp_sosi_init;
+
+  -- Verify
+  SIGNAL in_sosi_integer       : t_dp_sosi_integer;
+  SIGNAL out_sosi_integer      : t_dp_sosi_integer;
+
+  SIGNAL verify_sosi_equal     : STD_LOGIC := '0';
+  SIGNAL verify_sync           : STD_LOGIC := '1';
+  SIGNAL recover_from_in_lost  : STD_LOGIC := '0';
+
+  SIGNAL verifying_sync_equal  : STD_LOGIC := '0';
+
+  SIGNAL prev_out_enable       : STD_LOGIC := '0';
+  SIGNAL pending_out_disable   : STD_LOGIC := '0';
+  SIGNAL expected_out_enable   : STD_LOGIC := '0';
+  SIGNAL expecting_out_start   : STD_LOGIC := '0';
+  SIGNAL hold_out_eop          : STD_LOGIC := '0';
+  SIGNAL hold_out_sop          : STD_LOGIC := '0';
+  SIGNAL out_sop_cnt           : NATURAL := 0;
+
+  SIGNAL dbg_out_sosi_sync     : STD_LOGIC;
+  SIGNAL dbg_out_sosi_sop      : STD_LOGIC;
+  SIGNAL dbg_out_sosi_bsn      : NATURAL;
+  SIGNAL dbg_nof_blk           : NATURAL := 0;
+  SIGNAL dbg_accumulate        : NATURAL := 0;
+  SIGNAL dbg_expected_bsn      : NATURAL := 0;
+
+  -- Local procedures
+  PROCEDURE proc_output_enable(SIGNAL clk                   : IN STD_LOGIC;
+                               SIGNAL cnt                   : IN INTEGER;
+                               SIGNAL sync                  : IN STD_LOGIC;
+                               SIGNAL mon_input_bsn_at_sync : IN STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
+                               SIGNAL stimuli_state         : OUT t_stimuli_state_enum;
+                               SIGNAL ctrl_start_bsn        : OUT STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
+                               SIGNAL ctrl_enable           : OUT STD_LOGIC;
+                               SIGNAL ctrl_enable_evt       : OUT STD_LOGIC) IS
+  BEGIN
+    proc_common_wait_until_hi_lo(clk, sync);  -- (re)enable at begin of sync interval
+    stimuli_state <= e_en;
+    ctrl_start_bsn <= ADD_UVEC(mon_input_bsn_at_sync, TO_UVEC(c_enable_init_nof_bsn, c_natural_w));  -- determine BSN in the future
+    ctrl_enable <= '1';
+    ctrl_enable_evt <= '1';
+    proc_common_wait_some_cycles(clk, 1);
+    ctrl_enable_evt <= '0';
+  END proc_output_enable;
+
+  PROCEDURE proc_output_re_enable(SIGNAL clk                   : IN STD_LOGIC;
+                                  SIGNAL cnt                   : IN INTEGER;
+                                  SIGNAL mon_input_bsn_at_sync : IN STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
+                                  SIGNAL stimuli_state         : OUT t_stimuli_state_enum;
+                                  SIGNAL ctrl_start_bsn        : OUT STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
+                                  SIGNAL ctrl_enable           : OUT STD_LOGIC;
+                                  SIGNAL ctrl_enable_evt       : OUT STD_LOGIC) IS
+  BEGIN
+    proc_output_enable(clk, cnt, in_sync, mon_input_bsn_at_sync, stimuli_state, ctrl_start_bsn, ctrl_enable, ctrl_enable_evt);
+    stimuli_state <= e_re;
+  END proc_output_re_enable;
+
+  PROCEDURE proc_output_disable(SIGNAL stimuli_state   : OUT t_stimuli_state_enum;
+                                SIGNAL ctrl_enable     : OUT STD_LOGIC;
+                                SIGNAL ctrl_enable_evt : OUT STD_LOGIC) IS
+  BEGIN
+    stimuli_state <= e_dis;
+    ctrl_enable <= '0';
+    ctrl_enable_evt <= '1';
+    proc_common_wait_some_cycles(clk, 1);
+    ctrl_enable_evt <= '0';
+  END proc_output_disable;
+
+BEGIN
+
+  ------------------------------------------------------------------------------
+  -- Clock & reset
+  ------------------------------------------------------------------------------
+  clk <= (NOT clk) OR tb_end AFTER c_clk_period/2;
+  rst <= '1', '0' AFTER c_clk_period*7;
+  cnt <= cnt + 1 WHEN rising_edge(clk);
+
+  ------------------------------------------------------------------------------
+  -- Stimuli:
+  ------------------------------------------------------------------------------
+
+  p_stimuli : PROCESS
+  BEGIN
+    stimuli_state <= e_dis;
+    proc_common_wait_until_low(clk, rst);
+
+    ------------------------------------------------------------------------------
+    -- Enable and disable output
+    ------------------------------------------------------------------------------
+    test_interval <= 0; proc_common_wait_some_cycles(clk, 1);
+
+    proc_common_wait_until_value(test_interval * c_nof_clk_per_test_interval + c_begin_of_test_interval, clk, cnt);
+    -- Start of test_interval: Enable output
+    proc_output_enable(clk, cnt, in_sync, mon_input_bsn_at_sync, stimuli_state, ctrl_start_bsn, ctrl_enable, ctrl_enable_evt);
+
+    -- End of test_interval: Disable output
+    proc_common_wait_until_value(test_interval * c_nof_clk_per_test_interval + c_end_of_test_interval, clk, cnt);
+    proc_output_disable(stimuli_state, ctrl_enable, ctrl_enable_evt);
+
+    ------------------------------------------------------------------------------
+    -- Re enable output when already enabled
+    ------------------------------------------------------------------------------
+    test_interval <= test_interval + 1; proc_common_wait_some_cycles(clk, 1);
+
+    -- Start of test_interval: Enable output
+    proc_common_wait_until_value(test_interval * c_nof_clk_per_test_interval + c_begin_of_test_interval, clk, cnt);
+    proc_output_enable(clk, cnt, in_sync, mon_input_bsn_at_sync, stimuli_state, ctrl_start_bsn, ctrl_enable, ctrl_enable_evt);
+
+    -- Mid of test_interval: Re-enable output
+    proc_common_wait_until_value(test_interval * c_nof_clk_per_test_interval + c_mid_of_test_interval, clk, cnt);
+    proc_output_re_enable(clk, cnt, mon_input_bsn_at_sync, stimuli_state, ctrl_start_bsn, ctrl_enable, ctrl_enable_evt);
+
+    -- End of test_interval: Disable output
+    proc_common_wait_until_value(test_interval * c_nof_clk_per_test_interval + c_end_of_test_interval, clk, cnt);
+    proc_output_disable(stimuli_state, ctrl_enable, ctrl_enable_evt);
+
+    ------------------------------------------------------------------------------
+    -- Lost input blocks
+    ------------------------------------------------------------------------------
+    test_interval <= test_interval + 1; proc_common_wait_some_cycles(clk, 1);
+
+    -- Start of test_interval: Enable output
+    proc_common_wait_until_value(test_interval * c_nof_clk_per_test_interval + c_begin_of_test_interval, clk, cnt);
+    proc_output_enable(clk, cnt, in_sync, mon_input_bsn_at_sync, stimuli_state, ctrl_start_bsn, ctrl_enable, ctrl_enable_evt);
+
+    -- Early in test_interval: Disable input to simulate lost blocks
+    proc_common_wait_until_value(test_interval * c_nof_clk_per_test_interval + c_early_in_test_interval, clk, cnt);
+    stimuli_state <= e_lost;
+    proc_common_wait_until_high(clk, stimuli_sosi.eop);
+    in_lost <= '1';  -- high after eop, so high at next sop
+    recover_from_in_lost <= '1';
+    FOR I IN 0 TO c_nof_lost_input_blocks-1 LOOP
+      proc_common_wait_some_cycles(clk, 1);
+      proc_common_wait_until_high(clk, stimuli_sosi.eop);
+    END LOOP;
+    in_lost <= '0';  -- low after eop, so low at next sop
+    stimuli_state <= e_en;
+    -- Wait for some cycles that DUT needs to catch up after lost input (see nxt_r.update_bsn in DUT)
+    FOR I IN 0 TO c_nof_lost_input_blocks / c_output_nof_blocks_min + 5 LOOP  -- + for some extra margin
+      proc_common_wait_some_cycles(clk, 1);
+    END LOOP;
+    recover_from_in_lost <= '0';
+
+    -- End of test_interval: Disable output
+    proc_common_wait_until_value(test_interval * c_nof_clk_per_test_interval + c_end_of_test_interval, clk, cnt);
+    proc_output_disable(stimuli_state, ctrl_enable, ctrl_enable_evt);
+
+    WAIT;
+  END PROCESS;
+
+  -- Generate data blocks with input sync
+  u_stimuli : ENTITY work.dp_stream_stimuli
+  GENERIC MAP (
+    g_sync_period  => g_nof_block_per_input_sync,
+    g_err_init     => 0,
+    g_err_incr     => 0,  -- do not increment, to not distract from viewing of BSN in Wave window
+    g_channel_init => 0,
+    g_channel_incr => 0,  -- do not increment, to not distract from viewing of BSN in Wave window
+    g_nof_repeat   => c_sim_nof_blocks,
+    g_pkt_len      => g_block_size,
+    g_pkt_gap      => g_input_gap_size
+  )
+  PORT MAP (
+    rst               => rst,
+    clk               => clk,
+
+    -- Generate stimuli
+    src_out           => stimuli_sosi,
+
+    -- End of stimuli
+    tb_end            => tb_end
+  );
+
+  -- Input with option to loose data blocks
+  p_in_sosi : PROCESS(stimuli_sosi, in_lost)
+  BEGIN
+    in_sosi <= stimuli_sosi;
+    IF in_lost = '1' THEN
+      in_sosi.sync  <= '0';
+      in_sosi.sop   <= '0';
+      in_sosi.eop   <= '0';
+      in_sosi.valid <= '0';
+    END IF;
+  END PROCESS;
+
+  -----------------------------------------------------------------------------
+  -- Verification
+  -----------------------------------------------------------------------------
+
+  -- separate signal for easier viewing in Wave window
+  stimuli_sync <= stimuli_sosi.sync;
+  in_sync <= in_sosi.sync;
+  out_sync <= out_sosi.sync;
+
+  -----------------------------------------------------------------------------
+  -- . Verify out_enable
+  -----------------------------------------------------------------------------
+  p_hold_out_eop : PROCESS(clk)
+  BEGIN
+    IF rising_edge(clk) THEN
+      IF out_sosi.eop = '1' THEN
+        hold_out_eop <= '1';
+      ELSIF out_sosi.sop = '1' THEN
+        hold_out_eop <= '0';
+      END IF;
+    END IF;
+  END PROCESS;
+
+  -- Determine expected out_enable
+  p_expected_out_enable : PROCESS(ctrl_enable, ctrl_enable_evt, in_sosi, ctrl_start_bsn, out_enable, pending_out_disable, hold_out_eop)
+  BEGIN
+    -- Expect output disable after ctrl_enable_evt
+    IF ctrl_enable_evt = '1' THEN
+       IF out_enable = '0' THEN
+         -- Output is already disabled
+         expected_out_enable <= '0';
+       ELSE
+         -- Output is enabled, so this is a re-enable event.
+         IF hold_out_eop = '1' THEN
+           expected_out_enable <= '0';  -- end of block, so output can disable immediately
+         ELSE
+           pending_out_disable <= '1';  -- plan output disable before re-enable
+         END IF;
+       END IF;
+    END IF;
+
+    IF pending_out_disable <= '1' THEN
+      IF hold_out_eop = '1' THEN
+        expected_out_enable <= '0';  -- end of block, so output can disable
+        pending_out_disable <= '0';
+      END IF;
+    END IF;
+
+    -- Expect output enable at start BSN
+    IF ctrl_enable = '1' THEN
+      IF UNSIGNED(in_sosi.bsn) >= UNSIGNED(ctrl_start_bsn) THEN
+        expected_out_enable <= '1';
+      END IF;
+    END IF;
+  END PROCESS;
+
+  p_verify_out_enable : PROCESS(clk)
+  BEGIN
+    -- Use registered values to compare, to avoid combinatorial differences
+    -- that can occur during a simulation delta cycle. These combinatorial
+    -- differences are not relevant, because they get resolved after a few
+    -- delta cycles.
+    IF rising_edge(clk) THEN
+      IF out_enable /= expected_out_enable THEN
+        IF out_enable = '1' THEN
+          REPORT "Unexpected enabled out_enable" SEVERITY ERROR;
+        ELSE
+          REPORT "Unexpected disabled out_enable" SEVERITY ERROR;
+        END IF;
+      END IF;
+    END IF;
+  END PROCESS;
+
+  -----------------------------------------------------------------------------
+  -- . Verify that there was valid output
+  -----------------------------------------------------------------------------
+
+  out_sop_cnt <= out_sop_cnt + 1 WHEN rising_edge(clk) AND out_sosi.sop = '1';
+
+  p_verify_output : PROCESS
+  BEGIN
+    WAIT UNTIL tb_end = '1';
+    ASSERT out_sop_cnt > 0 REPORT "There was no output." SEVERITY ERROR;
+    WAIT;
+  END PROCESS;
+
+  -----------------------------------------------------------------------------
+  -- . Verify out_start
+  -----------------------------------------------------------------------------
+
+  p_expecting_out_start : PROCESS(clk)
+  BEGIN
+    IF rising_edge(clk) THEN
+      IF ctrl_enable = '1' AND ctrl_enable_evt = '1' THEN
+        expecting_out_start <= '1';
+      ELSIF out_start = '1' THEN
+        expecting_out_start <= '0';
+      END IF;
+    END IF;
+  END PROCESS;
+
+  prev_out_enable <= out_enable WHEN rising_edge(clk);
+
+  p_verify_out_start : PROCESS(clk)
+  BEGIN
+    IF rising_edge(clk) THEN
+      -- Check that out_sync is active at out_start
+      IF out_start = '1' THEN
+        IF out_sync = '0' THEN
+          REPORT "Missing out_sync at out_start" SEVERITY ERROR;
+        END IF;
+      END IF;
+
+      -- Check unexpected out_start
+      IF out_start = '1' AND expecting_out_start = '0' THEN
+        REPORT "Unexpected out_start" SEVERITY ERROR;
+      END IF;
+
+      -- Check that out_start is active when out_enable goes high
+      IF out_start = '0' AND out_enable = '1' AND prev_out_enable = '0' THEN
+        REPORT "Missed out_start" SEVERITY ERROR;
+      END IF;
+    END IF;
+  END PROCESS;
+
+  -----------------------------------------------------------------------------
+  -- . Verify out_sosi = in_sosi, for all fields except out_sosi.sync
+  -----------------------------------------------------------------------------
+  -- Use registered values for func_dp_stream_slv_to_integer(), to avoid
+  -- Warning: NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0 at
+  -- Time: 0 fs in Transcript window. Using only c_dp_sosi_init at signal
+  -- declaration is not sufficient.
+
+  verify_sosi_equal <= out_enable WHEN rising_edge(clk);
+  in_sosi_integer   <= func_dp_stream_slv_to_integer(in_sosi, c_natural_w) WHEN rising_edge(clk);
+  out_sosi_integer  <= func_dp_stream_slv_to_integer(out_sosi, c_natural_w) WHEN rising_edge(clk);
+
+  proc_dp_verify_sosi_equal(  "bsn", clk, verify_sosi_equal, out_sosi_integer, in_sosi_integer);
+  proc_dp_verify_sosi_equal(  "sop", clk, verify_sosi_equal, out_sosi_integer, in_sosi_integer);
+  proc_dp_verify_sosi_equal(  "eop", clk, verify_sosi_equal, out_sosi_integer, in_sosi_integer);
+  proc_dp_verify_sosi_equal("valid", clk, verify_sosi_equal, out_sosi_integer, in_sosi_integer);
+  proc_dp_verify_sosi_equal( "data", clk, verify_sosi_equal, out_sosi_integer, in_sosi_integer);
+
+  -- Verify that out_sosi blocks have sop and eop
+  proc_dp_verify_sop_and_eop(clk, out_sosi.valid, out_sosi.sop, out_sosi.eop, hold_out_sop);
+
+  -----------------------------------------------------------------------------
+  -- . Verify out_sosi.sync = in_sosi.sync, when sync interval is not changed
+  -----------------------------------------------------------------------------
+  gen_verify_sync_equal : IF g_nof_samples_per_output_sync = g_nof_block_per_input_sync * g_block_size GENERATE
+    verifying_sync_equal <= '1';  -- to show in Wave window that this check is active
+    proc_dp_verify_sosi_equal( "sync", clk, verify_sosi_equal, out_sosi_integer, in_sosi_integer);
+  END GENERATE;
+
+  -----------------------------------------------------------------------------
+  -- . Verify out_sosi.sync interval
+  -----------------------------------------------------------------------------
+  verify_sync <= NOT recover_from_in_lost;
+
+  proc_dp_verify_sync(TO_UINT(ctrl_start_bsn),
+                              ctrl_interval_size,
+                              g_block_size,
+                              clk,
+                              verify_sync,
+                              out_sosi.sync,
+                              out_sosi.sop,
+                              out_sosi.bsn,
+                              dbg_nof_blk,
+                              dbg_accumulate,
+                              dbg_expected_bsn);
+
+  dbg_out_sosi_sync <= out_sosi.sync;
+  dbg_out_sosi_sop  <= out_sosi.sop;
+  dbg_out_sosi_bsn  <= TO_UINT(out_sosi.bsn);
+
+  -----------------------------------------------------------------------------
+  -- . Verify mon_output_sync_bsn
+  -----------------------------------------------------------------------------
+
+  out_sop_dly <= out_sosi.sop WHEN rising_edge(clk);
+
+  p_verify_mon_output_sync_bsn : PROCESS(clk)
+    VARIABLE v_bsn_min : NATURAL;
+    VARIABLE v_bsn_max : NATURAL;
+  BEGIN
+    IF rising_edge(clk) THEN
+      IF recover_from_in_lost = '0' THEN
+        IF out_sop_dly = '1' THEN
+          v_bsn_min := TO_UINT(mon_current_input_bsn) - 1;
+          v_bsn_max := TO_UINT(mon_current_input_bsn) + c_output_nof_blocks_min + 1;
+
+          ASSERT TO_UINT(mon_output_sync_bsn) >= v_bsn_min
+            REPORT "Wrong: mon_output_sync_bsn is behind (" & int_to_str(TO_UINT(mon_output_sync_bsn)) & " < " & int_to_str(v_bsn_min) & ")"  SEVERITY ERROR;
+          ASSERT TO_UINT(mon_output_sync_bsn) <= v_bsn_max
+            REPORT "Wrong: mon_output_sync_bsn is too far ahead (" & int_to_str(TO_UINT(mon_output_sync_bsn)) & " > " & int_to_str(v_bsn_max) & ")" SEVERITY ERROR;
+
+          --Debug report used to investigate v_bsn_min and v_bsn_max assert conditions
+          --REPORT int_to_str(TO_UINT(mon_output_sync_bsn)) & " : " & int_to_str(TO_UINT(mon_current_input_bsn)) SEVERITY NOTE;
+        END IF;
+      END IF;
+    END IF;
+  END PROCESS;
+
+
+  -----------------------------------------------------------------------------
+  -- DUT: dp_bsn_sync_scheduler
+  -----------------------------------------------------------------------------
+
+  dut : ENTITY work.dp_bsn_sync_scheduler
+  GENERIC MAP (
+    g_bsn_w           => c_bsn_w,
+    g_block_size      => g_block_size,
+    g_pipeline        => 0
+  )
+  PORT MAP (
+    rst                   => rst,
+    clk                   => clk,
+
+    -- M&C
+    ctrl_enable           => ctrl_enable,
+    ctrl_enable_evt       => ctrl_enable_evt,
+    ctrl_interval_size    => ctrl_interval_size,
+    ctrl_start_bsn        => ctrl_start_bsn,
+    mon_current_input_bsn => mon_current_input_bsn,
+    mon_input_bsn_at_sync => mon_input_bsn_at_sync,
+    mon_output_enable     => mon_output_enable,
+    mon_output_sync_bsn   => mon_output_sync_bsn,
+
+    -- Streaming
+    in_sosi               => in_sosi,
+    out_sosi              => out_sosi,
+    out_start             => out_start,
+    out_enable            => out_enable
+  );
+
+END tb;
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd b/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd
index 381a32262b5abb01aeb880676d4fe1a6f74bdbbb..6e60576827b6b82a8cf5868f626744dfcf28322a 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_pkg.vhd
@@ -444,6 +444,12 @@ PACKAGE tb_dp_pkg IS
                                       SIGNAL   verify_en   : IN STD_LOGIC;
                                       SIGNAL   res_data    : IN STD_LOGIC_VECTOR);
 
+  PROCEDURE proc_dp_verify_sosi_equal(CONSTANT c_str       : IN STRING;
+                                      SIGNAL   clk         : IN STD_LOGIC;
+                                      SIGNAL   verify_en   : IN STD_LOGIC;
+                                      SIGNAL   dut_sosi    : IN t_dp_sosi_integer;   -- use func_dp_stream_slv_to_integer for conversion
+                                      SIGNAL   exp_sosi    : IN t_dp_sosi_integer);  -- use func_dp_stream_slv_to_integer for conversion
+
   PROCEDURE proc_dp_verify_valid(CONSTANT c_ready_latency : IN    NATURAL;
                                  SIGNAL   clk             : IN    STD_LOGIC;
                                  SIGNAL   verify_en       : IN    STD_LOGIC;
@@ -458,30 +464,43 @@ PACKAGE tb_dp_pkg IS
                                  SIGNAL   out_val         : IN    STD_LOGIC);
 
   -- Verify the DUT output sync
-  PROCEDURE proc_dp_verify_sync(CONSTANT c_sync_period : IN    NATURAL;
-                                CONSTANT c_sync_offset : IN    NATURAL;
-                                SIGNAL   clk           : IN    STD_LOGIC;
+  PROCEDURE proc_dp_verify_sync(SIGNAL   clk           : IN    STD_LOGIC;
                                 SIGNAL   verify_en     : IN    STD_LOGIC;
                                 SIGNAL   sync          : IN    STD_LOGIC;
                                 SIGNAL   sop           : IN    STD_LOGIC;
-                                SIGNAL   bsn           : IN    STD_LOGIC_VECTOR);
+                                         expected_sync : IN    STD_LOGIC);
 
--- Verify the DUT output sync
   PROCEDURE proc_dp_verify_sync(SIGNAL   clk           : IN    STD_LOGIC;
                                 SIGNAL   verify_en     : IN    STD_LOGIC;
                                 SIGNAL   sync          : IN    STD_LOGIC;
                                 SIGNAL   sop           : IN    STD_LOGIC;
-                                SIGNAL   expected_sync : IN    STD_LOGIC);
+                                         bsn           : IN    NATURAL;  -- for reporting
+                                         expected_bsn  : IN    NATURAL;  -- for reporting
+                                         expected_sync : IN    STD_LOGIC);
+    -- Note: A SIGNAL IN can only connect a SIGNAL. Therefore define IN as
+    --       default (= CONSTANT) instead of SIGNAL to be able to connect
+    --       VARIABLE or SIGNAL.
 
-  -- Verify the DUT output sync
-  PROCEDURE proc_dp_verify_sync_v2(CONSTANT c_sync_period : IN    NATURAL;
-                                   CONSTANT c_sync_offset : IN    NATURAL;
-                                   SIGNAL   clk           : IN    STD_LOGIC;
-                                   SIGNAL   verify_en     : IN    STD_LOGIC;
-                                   SIGNAL   sync          : IN    STD_LOGIC;
-                                   SIGNAL   sop           : IN    STD_LOGIC;
-                                   SIGNAL   bsn           : IN    STD_LOGIC_VECTOR;
-                                   SIGNAL   tb_bsn_cnt    : INOUT INTEGER);
+  PROCEDURE proc_dp_verify_sync(CONSTANT c_sync_period : IN    NATURAL;
+                                CONSTANT c_sync_offset : IN    NATURAL;
+                                SIGNAL   clk           : IN    STD_LOGIC;
+                                SIGNAL   verify_en     : IN    STD_LOGIC;
+                                SIGNAL   sync          : IN    STD_LOGIC;
+                                SIGNAL   sop           : IN    STD_LOGIC;
+                                SIGNAL   bsn           : IN    STD_LOGIC_VECTOR);
+
+  PROCEDURE proc_dp_verify_sync(CONSTANT c_start_bsn      : IN    NATURAL;
+                                CONSTANT c_sync_period    : IN    NATURAL;
+                                CONSTANT c_block_size     : IN    NATURAL;
+                                SIGNAL   clk              : IN    STD_LOGIC;
+                                SIGNAL   verify_en        : IN    STD_LOGIC;
+                                SIGNAL   sync             : IN    STD_LOGIC;
+                                SIGNAL   sop              : IN    STD_LOGIC;
+                                SIGNAL   bsn              : IN    STD_LOGIC_VECTOR;
+                                -- for debug purposes
+                                SIGNAL   dbg_nof_blk      : OUT   NATURAL;
+                                SIGNAL   dbg_accumulate   : OUT   NATURAL;
+                                SIGNAL   dbg_expected_bsn : OUT   NATURAL);
 
   -- Verify the DUT output sop and eop
   PROCEDURE proc_dp_verify_sop_and_eop(CONSTANT c_ready_latency : IN    NATURAL;
@@ -2155,6 +2174,78 @@ PACKAGE BODY tb_dp_pkg IS
     END IF;
   END proc_dp_verify_other_sosi;
 
+  ------------------------------------------------------------------------------
+  -- PROCEDURE: Verify per field whether DUT output SOSI is equal to expected SOSI
+  ------------------------------------------------------------------------------
+  PROCEDURE proc_dp_verify_sosi_equal(CONSTANT c_str       : IN STRING;
+                                      SIGNAL   clk         : IN STD_LOGIC;
+                                      SIGNAL   verify_en   : IN STD_LOGIC;
+                                      SIGNAL   dut_sosi    : IN t_dp_sosi_integer;     -- use func_dp_stream_slv_to_integer for conversion
+                                      SIGNAL   exp_sosi    : IN t_dp_sosi_integer) IS  -- use func_dp_stream_slv_to_integer for conversion
+  BEGIN
+    -- Use sosi integers, instead of sosi slv, for easier comparision. This
+    -- implies that only integer low part of sosi slv fields is checked, so
+    -- NATURAL'width = 31 bit for control and info and c_dat_w <= 32 bits for
+    -- data, re, im (c_dat_w is a parameter of func_dp_stream_slv_to_integer).
+    IF rising_edge(clk) THEN
+      IF verify_en='1' THEN
+        -- sosi ctrl fields
+        IF    c_str="sync" THEN
+          IF dut_sosi.sync /= exp_sosi.sync THEN
+            REPORT "DP : Wrong dut_sosi.sync (" & sl_to_str(dut_sosi.sync) & " /= " & sl_to_str(exp_sosi.sync) & ")" SEVERITY ERROR;
+          END IF;
+        ELSIF c_str="sop" THEN
+          IF dut_sosi.sop /= exp_sosi.sop THEN
+            REPORT "DP : Wrong dut_sosi.sop (" & sl_to_str(dut_sosi.sop) & " /= " & sl_to_str(exp_sosi.sop) & ")" SEVERITY ERROR;
+          END IF;
+        ELSIF c_str="eop" THEN
+          IF dut_sosi.eop /= exp_sosi.eop THEN
+            REPORT "DP : Wrong dut_sosi.eop (" & sl_to_str(dut_sosi.eop) & " /= " & sl_to_str(exp_sosi.eop) & ")" SEVERITY ERROR;
+          END IF;
+        ELSIF c_str="valid" THEN
+          IF dut_sosi.valid /= exp_sosi.valid THEN
+            REPORT "DP : Wrong dut_sosi.valid (" & sl_to_str(dut_sosi.valid) & " /= " & sl_to_str(exp_sosi.valid) & ")" SEVERITY ERROR;
+          END IF;
+
+        -- sosi info fields
+        ELSIF c_str="bsn" THEN
+          IF dut_sosi.bsn /= exp_sosi.bsn THEN
+            REPORT "DP : Wrong dut_sosi.bsn (" & int_to_str(dut_sosi.bsn) & " /= " & int_to_str(exp_sosi.bsn) & ")" SEVERITY ERROR;
+          END IF;
+        ELSIF c_str="empty" THEN
+          IF dut_sosi.empty /= exp_sosi.empty THEN
+            REPORT "DP : Wrong dut_sosi.empty (" & int_to_str(dut_sosi.empty) & " /= " & int_to_str(exp_sosi.empty) & ")" SEVERITY ERROR;
+          END IF;
+        ELSIF c_str="channel" THEN
+          IF dut_sosi.channel /= exp_sosi.channel THEN
+            REPORT "DP : Wrong dut_sosi.channel (" & int_to_str(dut_sosi.channel) & " /= " & int_to_str(exp_sosi.channel) & ")" SEVERITY ERROR;
+          END IF;
+        ELSIF c_str="err" THEN
+          IF dut_sosi.err /= exp_sosi.err THEN
+            REPORT "DP : Wrong dut_sosi.err (" & int_to_str(dut_sosi.err) & " /= " & int_to_str(exp_sosi.err) & ")" SEVERITY ERROR;
+          END IF;
+
+        -- sosi data fields
+        ELSIF c_str="data" THEN
+          IF dut_sosi.data /= exp_sosi.data THEN
+            REPORT "DP : Wrong dut_sosi.data (" & int_to_str(dut_sosi.data) & " /= " & int_to_str(exp_sosi.data) & ")" SEVERITY ERROR;
+          END IF;
+        ELSIF c_str="re" THEN
+          IF dut_sosi.re /= exp_sosi.re THEN
+            REPORT "DP : Wrong dut_sosi.re (" & int_to_str(dut_sosi.re) & " /= " & int_to_str(exp_sosi.re) & ")" SEVERITY ERROR;
+          END IF;
+        ELSIF c_str="im" THEN
+          IF dut_sosi.im /= exp_sosi.im THEN
+            REPORT "DP : Wrong dut_sosi.im (" & int_to_str(dut_sosi.im) & " /= " & int_to_str(exp_sosi.im) & ")" & ")" SEVERITY ERROR;
+          END IF;
+
+        -- unknown sosi field
+        ELSE
+          REPORT "proc_dp_verify_sosi_equal : Unknown sosi." & c_str & "field" SEVERITY FAILURE;
+        END IF;
+      END IF;
+    END IF;
+  END proc_dp_verify_sosi_equal;
 
   ------------------------------------------------------------------------------
   -- PROCEDURE: Verify the DUT output valid
@@ -2208,30 +2299,25 @@ PACKAGE BODY tb_dp_pkg IS
   ------------------------------------------------------------------------------
   -- PROCEDURE: Verify the DUT output sync
   -- . sync is defined such that it can only be active at sop
-  -- . assume that the sync occures priodically at bsn MOD c_sync_period = c_sync_offset
+  -- . report expected_sync from input
   ------------------------------------------------------------------------------
-  PROCEDURE proc_dp_verify_sync(CONSTANT c_sync_period   : IN    NATURAL;    -- BSN sync period
-                                CONSTANT c_sync_offset   : IN    NATURAL;    -- BSN sync offset
-                                SIGNAL   clk             : IN    STD_LOGIC;
+  PROCEDURE proc_dp_verify_sync(SIGNAL   clk             : IN    STD_LOGIC;
                                 SIGNAL   verify_en       : IN    STD_LOGIC;
                                 SIGNAL   sync            : IN    STD_LOGIC;
                                 SIGNAL   sop             : IN    STD_LOGIC;
-                                SIGNAL   bsn             : IN    STD_LOGIC_VECTOR) IS
-    CONSTANT c_bsn_w         : NATURAL := sel_a_b(bsn'LENGTH>31, 31, bsn'LENGTH);  -- use maximally 31 bit of BSN slv to allow calculations with integers
-    VARIABLE v_expected_sync : BOOLEAN;
+                                         expected_sync   : IN    STD_LOGIC) IS
   BEGIN
     IF rising_edge(clk) THEN
       IF verify_en='1' THEN
-        v_expected_sync := (TO_UINT(bsn(c_bsn_w-1 DOWNTO 0))-c_sync_offset) MOD c_sync_period = 0;
         -- Check for unexpected sync
         IF sync='1' THEN
-          ASSERT v_expected_sync = TRUE
+          ASSERT expected_sync='1'
             REPORT "Error: Unexpected sync at BSN" SEVERITY ERROR;
           ASSERT sop = '1'
             REPORT "Error: Unexpected sync at inactive sop" SEVERITY ERROR;
         END IF;
         -- Check for missing sync
-        IF sop='1' AND v_expected_sync=TRUE THEN
+        IF sop='1' AND expected_sync='1' THEN
           ASSERT sync = '1'
             REPORT "Error: Missing sync" SEVERITY ERROR;
         END IF;
@@ -2239,23 +2325,20 @@ PACKAGE BODY tb_dp_pkg IS
     END IF;
   END proc_dp_verify_sync;
 
-
-  ------------------------------------------------------------------------------
-  -- PROCEDURE: Verify the DUT output sync
-  -- . sync is defined such that it can only be active at sop
-  ------------------------------------------------------------------------------
   PROCEDURE proc_dp_verify_sync(SIGNAL   clk             : IN    STD_LOGIC;
                                 SIGNAL   verify_en       : IN    STD_LOGIC;
                                 SIGNAL   sync            : IN    STD_LOGIC;
                                 SIGNAL   sop             : IN    STD_LOGIC;
-                                SIGNAL   expected_sync   : IN    STD_LOGIC) IS
+                                         bsn             : IN    NATURAL;  -- for reporting
+                                         expected_bsn    : IN    NATURAL;  -- for reporting
+                                         expected_sync   : IN    STD_LOGIC) IS
   BEGIN
     IF rising_edge(clk) THEN
       IF verify_en='1' THEN
         -- Check for unexpected sync
         IF sync='1' THEN
           ASSERT expected_sync='1'
-            REPORT "Error: Unexpected sync at BSN" SEVERITY ERROR;
+            REPORT "Error: Unexpected sync at BSN (" & int_to_str(bsn) & " /= " & int_to_str(expected_bsn) & ")" SEVERITY ERROR;
           ASSERT sop = '1'
             REPORT "Error: Unexpected sync at inactive sop" SEVERITY ERROR;
         END IF;
@@ -2268,79 +2351,87 @@ PACKAGE BODY tb_dp_pkg IS
     END IF;
   END proc_dp_verify_sync;
 
-
   ------------------------------------------------------------------------------
   -- PROCEDURE: Verify the DUT output sync
   -- . sync is defined such that it can only be active at sop
   -- . assume that the sync occures priodically at bsn MOD c_sync_period = c_sync_offset
   ------------------------------------------------------------------------------
-  PROCEDURE proc_dp_verify_sync_v2(CONSTANT c_sync_period   : IN    NATURAL;    -- BSN sync period
-                                   CONSTANT c_sync_offset   : IN    NATURAL;    -- BSN sync offset
-                                   SIGNAL   clk             : IN    STD_LOGIC;
-                                   SIGNAL   verify_en       : IN    STD_LOGIC;
-                                   SIGNAL   sync            : IN    STD_LOGIC;
-                                   SIGNAL   sop             : IN    STD_LOGIC;
-                                   SIGNAL   bsn             : IN    STD_LOGIC_VECTOR;
-                                   SIGNAL   tb_bsn_cnt      : INOUT INTEGER) IS
-    CONSTANT c_bsn_w         : NATURAL := sel_a_b(bsn'LENGTH>31, 31, bsn'LENGTH);  -- use maximally 31 bit of BSN slv to allow calculations with integers
-
+  PROCEDURE proc_dp_verify_sync(CONSTANT c_sync_period   : IN    NATURAL;    -- BSN sync period
+                                CONSTANT c_sync_offset   : IN    NATURAL;    -- BSN sync offset
+                                SIGNAL   clk             : IN    STD_LOGIC;
+                                SIGNAL   verify_en       : IN    STD_LOGIC;
+                                SIGNAL   sync            : IN    STD_LOGIC;
+                                SIGNAL   sop             : IN    STD_LOGIC;
+                                SIGNAL   bsn             : IN    STD_LOGIC_VECTOR) IS
+    CONSTANT c_bsn_w         : NATURAL := sel_a_b(bsn'LENGTH>31, 31, bsn'LENGTH);  -- use maximally c_natural_w = 31 bit of BSN slv to allow calculations with integers
+    VARIABLE v_bsn           : NATURAL := TO_UINT(bsn(c_bsn_w-1 DOWNTO 0));
     VARIABLE v_expected_sync : BOOLEAN;
-    VARIABLE v_tb_bsn_cnt    : INTEGER;
   BEGIN
-    IF rising_edge(clk) THEN
-      IF verify_en='1' THEN
-        -- Determine whether sync is expected at this bsn
-
-        v_expected_sync := FALSE;
-        v_tb_bsn_cnt := tb_bsn_cnt;  -- assign signal to variable
-
-        -- on sync check if tb_bsn_cnt is a valid value
-        -- valid is c_sync_period or c_sync_period-1
-        IF sync='1' THEN
-          IF v_tb_bsn_cnt=c_sync_period OR v_tb_bsn_cnt=c_sync_period-1 THEN
-            v_expected_sync := TRUE;
-            --REPORT "bsn count valid " & int_to_str(v_tb_bsn_cnt);
-          ELSE
-            v_expected_sync := FALSE;
-          END IF;
-
-          v_tb_bsn_cnt := 0;  -- reset tb_bsn_cnt
-        END IF;
-
-        -- on sop increment tb_bsn_cnt by 1
-        IF sop='1' THEN
-            v_tb_bsn_cnt := v_tb_bsn_cnt + 1;
-        END IF;
-
-        -- if bsn = 0 (when in dp_off state) set tb_bsn_cnt also to 0
-        IF TO_UINT(bsn(c_bsn_w-1 DOWNTO 0)) = c_sync_offset THEN
-          v_tb_bsn_cnt := 0;
-        END IF;
-
-        tb_bsn_cnt <= v_tb_bsn_cnt;  -- assign variable to signal
+    -- Determine v_expected_sync
+    v_expected_sync := (v_bsn - c_sync_offset) MOD c_sync_period = 0;
+    -- Report sync and v_expected_sync
+    proc_dp_verify_sync(clk, verify_en, sync, sop, to_sl(v_expected_sync));
+  END proc_dp_verify_sync;
 
-        -- Check for unexpected sync
-        IF sync='1' THEN
-          ASSERT v_expected_sync = TRUE
-            REPORT "Error: Unexpected BSN count " & int_to_str(v_tb_bsn_cnt) SEVERITY ERROR;
-          ASSERT sop = '1'
-            REPORT "Error: Unexpected sync at inactive sop" SEVERITY ERROR;
-        END IF;
-        -- Check for missing sync
-        IF sop='1' AND v_expected_sync=TRUE THEN
-          ASSERT sync = '1'
-            REPORT "Error: Missing sync" SEVERITY ERROR;
-        END IF;
-        -- Check for missing sync
-        IF sop='1' THEN
-          ASSERT v_tb_bsn_cnt <= c_sync_period
-            REPORT "Error: bsn count " & int_to_str(v_tb_bsn_cnt) & " > " & int_to_str(c_sync_period) SEVERITY ERROR;
+  ------------------------------------------------------------------------------
+  -- PROCEDURE: Verify the DUT output sync
+  -- . sync is defined such that it can only be active at sop
+  -- . assume that the fractional sync period varies between N and N-1 blocks
+  -- . the fractional sync period starts with N blocks and fits e.g.
+  --   dp_bsn_source_v2, dp_bsn_sync_scheduler.
+  ------------------------------------------------------------------------------
+  PROCEDURE proc_dp_verify_sync(CONSTANT c_start_bsn      : IN    NATURAL;    -- BSN of first sync, start of fractional periods
+                                CONSTANT c_sync_period    : IN    NATURAL;    -- number of sample per sync period
+                                CONSTANT c_block_size     : IN    NATURAL;    -- number of sample per block
+                                SIGNAL   clk              : IN    STD_LOGIC;
+                                SIGNAL   verify_en        : IN    STD_LOGIC;
+                                SIGNAL   sync             : IN    STD_LOGIC;
+                                SIGNAL   sop              : IN    STD_LOGIC;
+                                SIGNAL   bsn              : IN    STD_LOGIC_VECTOR;
+                                -- for debug purposes
+                                SIGNAL   dbg_nof_blk      : OUT   NATURAL;
+                                SIGNAL   dbg_accumulate   : OUT   NATURAL;
+                                SIGNAL   dbg_expected_bsn : OUT   NATURAL) IS
+    CONSTANT c_bsn_w         : NATURAL := sel_a_b(bsn'LENGTH>31, 31, bsn'LENGTH);  -- use maximally c_natural_w = 31 bit of BSN slv to allow calculations with integers
+    CONSTANT c_nof_blk_min   : NATURAL := c_sync_period / c_block_size;    -- minimum number of blocks in sync period
+    CONSTANT c_extra         : NATURAL := c_sync_period MOD c_block_size;  -- number of extra samples in sync period
+    VARIABLE v_bsn           : NATURAL := TO_UINT(bsn(c_bsn_w-1 DOWNTO 0));
+    VARIABLE v_expected_sync : BOOLEAN := FALSE;  -- default FALSE, e.g. when bsn < c_start_bsn is in the past
+    VARIABLE v_expected_bsn  : NATURAL := c_start_bsn;    -- BSN that is expected to have a sync, intialize with start BSN
+    VARIABLE v_nof_blk       : NATURAL := c_nof_blk_min + 1;  -- number of blocks in period, first sync period will be 1 block longer to achieve the fraction part
+    VARIABLE v_accumulate    : INTEGER := c_block_size - c_extra;  -- number of extra samples in period, first sync period will have v_accumulate more
+  BEGIN
+    -- Determine v_expected_sync
+    IF c_extra = 0 THEN
+      -- The sync period contains an integer number of blocks (c_extra = 0)
+      -- Determine directly whether the input bsn is expected to have a sync
+      v_expected_sync := ((v_bsn - c_start_bsn) MOD c_nof_blk_min = 0);
+    ELSE
+      -- The sync period contains a fractional number of blocks
+      -- Determine next expected BSN with sync until the input bsn is reached using a loop
+      WHILE v_expected_bsn < v_bsn LOOP
+        v_expected_bsn := v_expected_bsn + v_nof_blk;  -- next expected BSN to have a sync
+
+        v_nof_blk := c_nof_blk_min;
+        v_accumulate   := v_accumulate - c_extra;
+        IF v_accumulate < 0 THEN
+          v_nof_blk := v_nof_blk + 1;
+          v_accumulate   := v_accumulate + c_block_size;
         END IF;
+      END LOOP;
+      v_expected_sync := (v_bsn = v_expected_bsn);
+    END IF;
 
-      END IF;
+    IF verify_en = '1' THEN
+      -- Debug signals, for view in Wave window
+      dbg_nof_blk      <= v_nof_blk;
+      dbg_accumulate   <= v_accumulate;
+      dbg_expected_bsn <= v_expected_bsn;
     END IF;
-  END proc_dp_verify_sync_v2;
 
+    -- Report sync and v_expected_sync
+    proc_dp_verify_sync(clk, verify_en, sync, sop, v_bsn, v_expected_bsn, to_sl(v_expected_sync));
+  END proc_dp_verify_sync;
 
   ------------------------------------------------------------------------------
   -- PROCEDURE: Verify the DUT output sop and eop
diff --git a/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd b/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..ce4e5f605e7efbba13cb3ec7a972a5d9b9548805
--- /dev/null
+++ b/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd
@@ -0,0 +1,405 @@
+-- --------------------------------------------------------------------------
+-- 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: E. Kooistra, 6 aug 2021
+-- Purpose: Verify MM part of mmp_dp_bsn_sync_scheduler
+-- Description:
+--    The functional part is already verified by tb_tb_dp_bsn_sync_scheduler.vhd.
+-- Usage:
+-- > as 5
+-- > run -all
+--   . View *_64 BSN values as radix hex in Wave window to recognize BSN hi word.
+  
+LIBRARY IEEE, common_lib, technology_lib;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.tb_common_mem_pkg.ALL; 
+USE common_lib.common_str_pkg.ALL;
+USE work.dp_stream_pkg.ALL;
+USE work.tb_dp_pkg.ALL;
+
+ENTITY tb_mmp_dp_bsn_sync_scheduler IS
+END tb_mmp_dp_bsn_sync_scheduler;
+
+
+ARCHITECTURE tb OF tb_mmp_dp_bsn_sync_scheduler IS
+
+  CONSTANT c_mm_clk_period                : TIME := 40 ns;
+  CONSTANT c_dp_clk_period                : TIME := 10 ns;
+  CONSTANT c_cross_clock_domain_latency   : NATURAL := 20;
+
+  CONSTANT c_report_note                  : BOOLEAN := FALSE;  -- Use TRUE for tb debugging, else FALSE to keep Transcript window more empty
+
+  CONSTANT c_nof_input_sync               : NATURAL := 10;
+  CONSTANT c_nof_block_per_input_sync     : NATURAL := 17;
+  CONSTANT c_nof_block_per_output_sync    : NATURAL := 5;
+  CONSTANT c_block_size                   : NATURAL := 10;
+  CONSTANT c_input_gap_size               : NATURAL := 3;
+  CONSTANT c_sim_nof_blocks               : NATURAL := c_nof_block_per_input_sync * c_nof_input_sync;
+
+  -- DUT settings
+  CONSTANT c_bsn_w                        : NATURAL := 40;
+  CONSTANT c_bsn_hi_value                 : NATURAL := 23;
+  CONSTANT c_ctrl_interval_size           : NATURAL := c_nof_block_per_output_sync * c_block_size;
+  CONSTANT c_ctrl_start_bsn_lo            : NATURAL := 19;
+  CONSTANT c_ctrl_start_bsn_hi            : NATURAL := 17;
+
+  SIGNAL tb_end                   : STD_LOGIC := '0';
+  SIGNAL stimuli_end              : STD_LOGIC := '0';
+  SIGNAL mm_clk                   : STD_LOGIC := '1';
+  SIGNAL mm_rst                   : STD_LOGIC := '1';
+  SIGNAL dp_clk                   : STD_LOGIC := '1';
+  SIGNAL dp_rst                   : STD_LOGIC := '1';
+
+  SIGNAL reg_mosi                 : t_mem_mosi := c_mem_mosi_rst;
+  SIGNAL reg_miso                 : t_mem_miso;
+
+  SIGNAL ctrl_start_bsn_64        : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0);
+
+  SIGNAL mon_output_enable        : STD_LOGIC;
+  SIGNAL mon_current_input_bsn_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0);
+  SIGNAL mon_input_bsn_at_sync_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0);
+  SIGNAL mon_output_sync_bsn_64   : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0);
+  SIGNAL mon_block_size           : NATURAL;
+
+  SIGNAL stimuli_sosi             : t_dp_sosi;
+  SIGNAL in_sosi                  : t_dp_sosi;
+  SIGNAL out_sosi                 : t_dp_sosi;
+  SIGNAL out_start                : STD_LOGIC;
+  SIGNAL out_enable               : STD_LOGIC;
+
+  SIGNAL verify_bsn_hi            : STD_LOGIC := '0';
+
+BEGIN
+
+  dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2;
+  mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2;
+  dp_rst <= '1', '0' AFTER c_dp_clk_period*7;    
+  mm_rst <= '1', '0' AFTER c_mm_clk_period*7;
+  
+  ------------------------------------------------------------------------------
+  -- MM stimuli and verification
+  ------------------------------------------------------------------------------
+
+  p_stimuli_and_verify_mm : PROCESS
+    VARIABLE v_bsn : NATURAL;
+  BEGIN              
+    proc_common_wait_until_low(dp_clk, mm_rst);
+    proc_common_wait_until_low(dp_clk, dp_rst);
+    proc_common_wait_some_cycles(mm_clk, 5);
+
+    ---------------------------------------------------------------------------
+    -- Initial check
+    ---------------------------------------------------------------------------
+    -- . Read mon_block_size
+    proc_mem_mm_bus_rd(11, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_block_size <= TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0));
+
+    -- . Verify mon_block_size
+    proc_common_wait_some_cycles(mm_clk, 1);
+    ASSERT mon_block_size = c_block_size REPORT "Wrong block_size." SEVERITY ERROR;
+
+    -- . Read mon_output_enable
+    proc_mem_mm_bus_rd(8, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_output_enable <= reg_miso.rddata(0);
+
+    -- . Verify output is off
+    proc_common_wait_some_cycles(mm_clk, 1);
+    ASSERT mon_output_enable = '0' REPORT "DUT output is enabled." SEVERITY ERROR;
+
+    ---------------------------------------------------------------------------
+    -- Verify c_ctrl_start_bsn_hi
+    ---------------------------------------------------------------------------
+
+    -- . Write ctrl_start_bsn
+    proc_mem_mm_bus_wr(2, c_ctrl_start_bsn_lo,  mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_wr(3, c_ctrl_start_bsn_hi,  mm_clk, reg_miso, reg_mosi);
+    proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency);
+    proc_common_wait_some_cycles(dp_clk, c_cross_clock_domain_latency);
+
+    -- . Read back ctrl_start_bsn
+    proc_mem_mm_bus_rd(2, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    ctrl_start_bsn_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(3, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    ctrl_start_bsn_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+
+    proc_common_wait_some_cycles(mm_clk, 1);
+    ASSERT c_ctrl_start_bsn_lo = TO_UINT(ctrl_start_bsn_64(  c_word_w-1 DOWNTO        0)) REPORT "Wrong ctrl_start_bsn low word." SEVERITY ERROR;
+    ASSERT c_ctrl_start_bsn_hi = TO_UINT(ctrl_start_bsn_64(2*c_word_w-1 DOWNTO c_word_w)) REPORT "Wrong ctrl_start_bsn high word." SEVERITY ERROR;
+
+    ---------------------------------------------------------------------------
+    -- Setup, enable and verify DUT output
+    ---------------------------------------------------------------------------
+    -- . Read mon_current_input_bsn_64
+    proc_mem_mm_bus_rd(4, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_current_input_bsn_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(5, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_current_input_bsn_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_common_wait_some_cycles(mm_clk, 1);
+
+    -- . Select start BSN in the future
+    v_bsn := TO_UINT(mon_current_input_bsn_64) + 20;
+
+    -- . Setup output sync interval
+    proc_mem_mm_bus_wr(1, c_ctrl_interval_size, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_wr(2, v_bsn,                mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_wr(3, 0,                    mm_clk, reg_miso, reg_mosi);
+    proc_common_wait_some_cycles(dp_clk, c_block_size*10);
+
+    -- . Enable output
+    proc_mem_mm_bus_wr(0, 1, mm_clk, reg_miso, reg_mosi);
+    proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency);
+    proc_common_wait_some_cycles(dp_clk, c_cross_clock_domain_latency);
+
+    proc_common_wait_some_cycles(dp_clk, c_block_size*10);
+
+    -- . Read back ctrl_start_bsn
+    proc_mem_mm_bus_rd(2, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    ctrl_start_bsn_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(3, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    ctrl_start_bsn_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+
+    -- . Read mon_current_input_bsn_64
+    proc_mem_mm_bus_rd(4, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_current_input_bsn_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(5, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_current_input_bsn_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+
+    -- . Read mon_input_bsn_at_sync_64
+    proc_mem_mm_bus_rd(6, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_input_bsn_at_sync_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(7, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_input_bsn_at_sync_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+
+    -- . Read mon_output_sync_bsn_64
+    proc_mem_mm_bus_rd(9, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_output_sync_bsn_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(10, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_output_sync_bsn_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+
+    -- . Read mon_output_enable
+    proc_mem_mm_bus_rd(8, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_output_enable <= reg_miso.rddata(0);
+
+    -- Verify output is on and running
+    proc_common_wait_some_cycles(mm_clk, 1);
+    ASSERT mon_output_enable = '1' REPORT "mon_output_enable is not enabled." SEVERITY ERROR;
+    ASSERT        out_enable = '1' REPORT "output_enable is not enabled." SEVERITY ERROR;
+
+    ---------------------------------------------------------------------------
+    -- Check that monitor BSN are incrementing
+    ---------------------------------------------------------------------------
+    proc_common_wait_some_cycles(mm_clk, c_ctrl_interval_size * 3);
+
+    -- . Check mon_current_input_bsn_64
+    v_bsn := TO_UINT(mon_current_input_bsn_64);
+    proc_mem_mm_bus_rd(4, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_current_input_bsn_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(5, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_current_input_bsn_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_common_wait_some_cycles(mm_clk, 1);
+    IF c_report_note THEN
+      REPORT "mon_current_input_bsn : " & int_to_str(v_bsn) & ", " & int_to_str(TO_UINT(mon_current_input_bsn_64)) SEVERITY NOTE;
+    END IF;
+    ASSERT v_bsn < TO_UINT(mon_current_input_bsn_64) REPORT "DUT mon_current_input_bsn is not incrementing." SEVERITY ERROR;
+
+    -- . Check mon_input_bsn_at_sync_64
+    v_bsn := TO_UINT(mon_input_bsn_at_sync_64);
+    proc_mem_mm_bus_rd(6, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_input_bsn_at_sync_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(7, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_input_bsn_at_sync_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_common_wait_some_cycles(mm_clk, 1);
+    IF c_report_note THEN
+      REPORT "mon_input_bsn_at_sync : " & int_to_str(v_bsn) & ", " & int_to_str(TO_UINT(mon_input_bsn_at_sync_64)) SEVERITY NOTE;
+    END IF;
+    ASSERT v_bsn < TO_UINT(mon_input_bsn_at_sync_64) REPORT "DUT mon_input_bsn_at_sync is not incrementing." SEVERITY ERROR;
+    ASSERT (TO_UINT(mon_input_bsn_at_sync_64) - v_bsn) MOD c_nof_block_per_input_sync = 0 REPORT "TB input_sync interval is not correct." SEVERITY ERROR;
+
+    -- . Check mon_output_sync_bsn_64
+    v_bsn := TO_UINT(mon_output_sync_bsn_64);
+    proc_mem_mm_bus_rd(9, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_output_sync_bsn_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(10, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_output_sync_bsn_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_common_wait_some_cycles(mm_clk, 1);
+    IF c_report_note THEN
+      REPORT "mon_output_sync_bsn : " & int_to_str(v_bsn) & ", " & int_to_str(TO_UINT(mon_output_sync_bsn_64)) SEVERITY NOTE;
+    END IF;
+    ASSERT v_bsn < TO_UINT(mon_output_sync_bsn_64) REPORT "DUT mon_output_sync_bsn is not incrementing." SEVERITY ERROR;
+    ASSERT (TO_UINT(mon_output_sync_bsn_64) - v_bsn) MOD c_nof_block_per_output_sync = 0 REPORT "DUT output_sync interval is not correct." SEVERITY ERROR;
+
+    ---------------------------------------------------------------------------
+    -- Verify BSN hi word
+    ---------------------------------------------------------------------------
+    -- . wait until input block boundary
+    proc_common_wait_until_high(dp_clk, stimuli_sosi.sop);
+    verify_bsn_hi <= '1';
+    proc_common_wait_some_cycles(dp_clk, c_block_size*c_nof_block_per_input_sync * 2);
+
+    -- . Read mon_current_input_bsn_64
+    proc_mem_mm_bus_rd(4, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_current_input_bsn_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(5, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_current_input_bsn_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+
+    -- . Read mon_input_bsn_at_sync_64
+    proc_mem_mm_bus_rd(6, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_input_bsn_at_sync_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(7, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_input_bsn_at_sync_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+
+    -- . Read mon_output_sync_bsn_64
+    proc_mem_mm_bus_rd(9, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_output_sync_bsn_64(c_word_w-1 DOWNTO 0) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_mem_mm_bus_rd(10, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_output_sync_bsn_64(2*c_word_w-1 DOWNTO c_word_w) <= reg_miso.rddata(c_word_w-1 DOWNTO 0);
+    proc_common_wait_some_cycles(mm_clk, 1);
+
+    -- The out_sosi.bsn will not reach the c_bsn_hi_value, because the
+    -- dp_bsn_sync_scheduler will be busy trying to catch up, see
+    -- nxt_r.update_bsn = '1' in dp_bsn_sync_scheduler.vhd. Therefore
+    -- expected mon_output_sync_bsn_64 hi value is still 0.
+    ASSERT c_bsn_hi_value = TO_UINT(mon_current_input_bsn_64(2*c_word_w-1 DOWNTO c_word_w)) REPORT "Wrong mon_current_input_bsn high word." SEVERITY ERROR;
+    ASSERT c_bsn_hi_value = TO_UINT(mon_input_bsn_at_sync_64(2*c_word_w-1 DOWNTO c_word_w)) REPORT "Wrong mon_input_bsn_at_sync high word." SEVERITY ERROR;
+    ASSERT 0              = TO_UINT(mon_output_sync_bsn_64(  2*c_word_w-1 DOWNTO c_word_w)) REPORT "Wrong mon_output_sync_bsn high word." SEVERITY ERROR;
+
+    ---------------------------------------------------------------------------
+    -- Disable and verify DUT output
+    ---------------------------------------------------------------------------
+
+    -- . Disable output
+    proc_mem_mm_bus_wr(0, 0, mm_clk, reg_miso, reg_mosi);
+    proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency);
+    proc_common_wait_some_cycles(dp_clk, c_cross_clock_domain_latency);
+
+    proc_common_wait_some_cycles(dp_clk, c_block_size*10);
+
+    -- . Read mon_output_enable
+    proc_mem_mm_bus_rd(8, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_output_enable <= reg_miso.rddata(0);
+
+    -- Verify output is on and running
+    proc_common_wait_some_cycles(mm_clk, 1);
+    ASSERT mon_output_enable = '0' REPORT "DUT mon_output_enable is not diabled." SEVERITY ERROR;
+    ASSERT        out_enable = '0' REPORT "DUT output_enable is not enabled." SEVERITY ERROR;
+
+    ---------------------------------------------------------------------------
+    -- End of test
+    ---------------------------------------------------------------------------
+    proc_common_wait_until_high(dp_clk, stimuli_end);
+    tb_end <= '1';
+    WAIT;
+  END PROCESS;
+
+  ------------------------------------------------------------------------------
+  -- Streaming stimuli
+  ------------------------------------------------------------------------------
+
+  p_in_sosi : PROCESS(stimuli_sosi, verify_bsn_hi)
+  BEGIN
+    in_sosi <= stimuli_sosi;
+
+    IF verify_bsn_hi = '1' THEN
+      -- Set hi word of input BSN
+      in_sosi.bsn(2*c_word_w-1 DOWNTO c_word_w) <= TO_UVEC(c_bsn_hi_value, c_word_w);
+    END IF;
+  END PROCESS;
+
+  -- Generate data blocks with input sync
+  u_stimuli : ENTITY work.dp_stream_stimuli
+  GENERIC MAP (
+    g_sync_period  => c_nof_block_per_input_sync,
+    g_err_init     => 0,
+    g_err_incr     => 0,  -- do not increment, to not distract from viewing of BSN in Wave window
+    g_channel_init => 0,
+    g_channel_incr => 0,  -- do not increment, to not distract from viewing of BSN in Wave window
+    g_nof_repeat   => c_sim_nof_blocks,
+    g_pkt_len      => c_block_size,
+    g_pkt_gap      => c_input_gap_size
+  )
+  PORT MAP (
+    rst               => dp_rst,
+    clk               => dp_clk,
+
+    -- Generate stimuli
+    src_out           => stimuli_sosi,
+
+    -- End of stimuli
+    tb_end            => stimuli_end
+  );
+
+  ------------------------------------------------------------------------------
+  -- DUT 
+  ------------------------------------------------------------------------------
+  
+  u_mmp_dp_bsn_sync_scheduler : ENTITY work.mmp_dp_bsn_sync_scheduler
+  GENERIC MAP (
+    g_bsn_w         => c_bsn_w,
+    g_block_size    => c_block_size
+  )
+  PORT MAP (
+    -- Clocks and reset
+    mm_rst          => mm_rst,
+    mm_clk          => mm_clk,
+    dp_rst          => dp_rst,
+    dp_clk          => dp_clk,
+
+    -- MM control
+    reg_mosi        => reg_mosi,
+    reg_miso        => reg_miso,
+
+    -- Streaming
+    in_sosi         => in_sosi,
+    out_sosi        => out_sosi,
+    out_start       => out_start,
+    out_enable      => out_enable
+  );
+  
+END tb;
diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_source_v2.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_source_v2.vhd
index 4c1700d33404cb7a9399ba52a7ed41642e12456a..b893581245a4262daf58758174bb4fd8ba9558fd 100644
--- a/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_source_v2.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_source_v2.vhd
@@ -34,22 +34,29 @@ END tb_tb_dp_bsn_source_v2;
 
 ARCHITECTURE tb OF tb_tb_dp_bsn_source_v2 IS
   SIGNAL tb_end : STD_LOGIC := '0';  -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end'
+
+  CONSTANT c_nof_pps : NATURAL := 50;  -- choose > g_block_size, because the fractional sync pattern will repeat
+                                       -- within g_block_size number of g_pps_interval's
+
 BEGIN
   -- from tb_dp_bsn_source_v2.vhd
   --
+  -- g_nof_pps      : NATURAL := 20;
   -- g_pps_interval : NATURAL := 240
   -- g_block_size   : NATURAL := 32  
 
-  --                                        (g_pps_interval, g_block_size)
   -- test different clk_per_sync
-  u0_230 : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (230, 32);
-  u0_240 : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (240, 32);
-  u0_248 : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (248, 32);
+  u_230_32_div_7_mod_6  : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (c_nof_pps, 230, 32);  -- 230 / 32 = 7, 230 MOD 32 = 6
+  u_240_32_div_7_mod_16 : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (c_nof_pps, 240, 32);  -- 240 / 32 = 7, 240 MOD 32 = 16
+  u_248_32_div_7_mod_24 : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (c_nof_pps, 248, 32);  -- 248 / 32 = 7, 248 MOD 32 = 24
 
   -- test different block_size's
-  u1_1 : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (240, 30);
-  u1_3 : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (240, 32);
-  u1_4 : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (240, 27);
-  
+  u_240_27_div_8_mod_24 : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (c_nof_pps, 240, 27);  -- 240 / 27 = 8, 240 MOD 27 = 24
+  u_240_30_div_8_mod_0  : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (c_nof_pps, 240, 30);  -- 240 / 30 = 8, 240 MOD 30 = 0
+
+  -- test some prime values
+  u_101_17_div_5_mod_16  : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (c_nof_pps, 101, 17);  -- 101 / 17 = 5, 101 MOD 17 = 16
+  u_101_23_div_4_mod_9   : ENTITY work.tb_dp_bsn_source_v2 GENERIC MAP (c_nof_pps, 101, 23);  -- 101 / 23 = 4, 101 MOD 23 = 9
+
 END tb;
-  
\ No newline at end of file
+  
diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..aea05a239d8776863bee18a2457fe397579c8727
--- /dev/null
+++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_bsn_sync_scheduler.vhd
@@ -0,0 +1,80 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2010
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-------------------------------------------------------------------------------
+-- Author: Eric Kooistra
+-- Purpose: Multi test bench for tb_dp_bsn_sync_scheduler.vhd
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+USE work.tb_dp_pkg.ALL;
+
+
+-- > as 4
+-- > run -all --> OK
+
+ENTITY tb_tb_dp_bsn_sync_scheduler IS
+END tb_tb_dp_bsn_sync_scheduler;
+
+
+ARCHITECTURE tb OF tb_tb_dp_bsn_sync_scheduler IS
+  SIGNAL tb_end : STD_LOGIC := '0';  -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end'
+
+  -- Use g_block_size < c_nof_input_sync, because the fractional sync pattern
+  -- will repeat within g_block_size number of output sync intervals. The
+  -- repeat period of the sync pattern is visible by nxt_r.accumulate in
+  -- dp_bsn_scheduler.vhd.
+  CONSTANT c_nof_input_sync : NATURAL := 25;
+
+BEGIN
+  -- from tb_dp_bsn_scheduler.vhd
+  --
+  -- -- Input sync period and sosi ctrl
+  -- g_nof_input_sync               : NATURAL := 10;
+  -- g_nof_block_per_input_sync     : NATURAL := 17;
+  -- g_block_size                   : NATURAL := 10;
+  -- g_input_gap_size               : NATURAL := 3;
+  --
+  -- -- Output sync period
+  -- g_nof_samples_per_output_sync  : NATURAL := 45;  -- = g_block_size * 9 / 2
+
+  u_output_is_input             : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 170);  -- 170/10 = 17    block/out_sync, = in_sosi
+  u_output_is_input_no_gaps     : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17,  5, 0,  85);  --  85/5  = 17    block/out_sync, = in_sosi
+
+  u_sync_interval_0_5x          : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3,  85);  --  85/10 =  8.5  block/out_sync, factor  85/170 = 0.5,
+  u_sync_interval_1_5x          : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 255);  -- 255/10 = 25.5  block/out_sync, factor 255/170 = 1.5,
+  u_sync_interval_prime_251     : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3, 251);  -- 251/10 = 25.1  block/out_sync, 251 is a prime
+
+  u_short_block_4_3_15          : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync,  4,  3, 3,  15);  --  15/3  =  5    block/out_sync,
+  u_short_block_5_3_16          : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync,  5,  3, 3,  16);  --  16/3  =  5.33 block/out_sync,
+  u_short_block_6_3_17          : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync,  6,  3, 3,  17);  --  17/3  =  5.66 block/out_sync,
+
+  u_short_block_no_gaps_4_3_15  : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync,  4,  3, 0,  15);  --  15/3  =  5    block/out_sync,
+  u_short_block_no_gaps_5_3_16  : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync,  5,  3, 0,  16);  --  16/3  =  5.33 block/out_sync,
+  u_short_block_no_gaps_6_3_17  : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync,  6,  3, 0,  17);  --  17/3  =  5.66 block/out_sync,
+
+  u_short_block_size_2          : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync,  7,  2, 3,  16);  --  16/2  =  8    block/out_sync,
+  u_short_block_size_2_no_gaps  : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync,  7,  2, 0,  16);  --  16/2  =  8    block/out_sync,
+
+  u_fraction_half               : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3,  45);  --  45/10 =  4.5  block/out_sync
+  u_fraction_0                  : ENTITY work.tb_dp_bsn_sync_scheduler GENERIC MAP (c_nof_input_sync, 17, 10, 3,  50);  --  50/10 =  5    block/out_sync
+
+END tb;
+  
diff --git a/libraries/base/ring/hdllib.cfg b/libraries/base/ring/hdllib.cfg
index d4452e8b64c7013b3bed1dca2884f3fa2bb58ae6..96d39f35a78c464ee187bd900cb60c8890fee9c6 100644
--- a/libraries/base/ring/hdllib.cfg
+++ b/libraries/base/ring/hdllib.cfg
@@ -8,6 +8,7 @@ synth_files =
     src/vhdl/ring_pkg.vhd
     src/vhdl/ring_lane_info_reg.vhd
     src/vhdl/ring_lane_info.vhd
+    src/vhdl/ring_tx.vhd
 test_bench_files =
     tb/vhdl/tb_ring_lane_info.vhd
 
diff --git a/libraries/base/ring/src/vhdl/ring_pkg.vhd b/libraries/base/ring/src/vhdl/ring_pkg.vhd
index 4786e34fb59f1d07cbb733e64246272ec20a5e3a..11a4e1e5c20b1aaf5c469d77a27f5ffdda3d67ea 100644
--- a/libraries/base/ring/src/vhdl/ring_pkg.vhd
+++ b/libraries/base/ring/src/vhdl/ring_pkg.vhd
@@ -31,6 +31,7 @@ USE IEEE.std_logic_1164.ALL;
 USE common_lib.common_pkg.ALL;
 USE common_lib.common_mem_pkg.ALL;
 USE common_lib.common_field_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
 
 PACKAGE ring_pkg is
 -- lane info, see https://support.astron.nl/confluence/x/jyu7Ag
@@ -78,10 +79,66 @@ PACKAGE ring_pkg is
         (field_name_pad("tx_select"),          "RW",  1, field_default(0)),
         (field_name_pad("rx_select"),          "RW",  1, field_default(0)) );
 
+  CONSTANT c_ring_eth_dst_mac : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0) := x"FFFFFFFFFFFF";
+  CONSTANT c_ring_eth_src_mac : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0) := x"002286080000";
+  CONSTANT c_ring_pkt_type_bf : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0) := x"10FB";
+  CONSTANT c_ring_pkt_type_xc : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0) := x"10FC";
+  CONSTANT c_ring_pkt_type_so : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0) := x"10FD";
+  CONSTANT c_ring_pkt_type_tb : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0) := x"10FE";
+
+  CONSTANT c_ring_eth_nof_hdr_fields : NATURAL := 3;
+  CONSTANT c_ring_eth_hdr_field_sel  : STD_LOGIC_VECTOR(c_ring_eth_nof_hdr_fields-1 DOWNTO 0) := "000";
+  CONSTANT c_ring_eth_hdr_field_arr : t_common_field_arr(c_ring_eth_nof_hdr_fields-1 DOWNTO 0) := (
+      ( field_name_pad("eth_dst_mac"  ), "RW", 48, field_default(c_ring_eth_dst_mac) ), 
+      ( field_name_pad("eth_src_mac"  ), "RW", 48, field_default(c_ring_eth_src_mac) ),
+      ( field_name_pad("eth_type"     ), "RW", 16, field_default(0) )
+  );
+
+  CONSTANT c_ring_dp_nof_hdr_fields : NATURAL := 6;
+  CONSTANT c_ring_dp_hdr_field_sel  : STD_LOGIC_VECTOR(c_ring_dp_nof_hdr_fields-1 DOWNTO 0) := "000"&"000";
+  CONSTANT c_ring_dp_hdr_field_arr : t_common_field_arr(c_ring_dp_nof_hdr_fields-1 DOWNTO 0) := (
+      ( field_name_pad("eth_dst_mac"  ), "RW", 48, field_default(c_ring_eth_dst_mac) ),  
+      ( field_name_pad("eth_src_mac"  ), "RW", 48, field_default(c_ring_eth_src_mac) ),
+      ( field_name_pad("eth_type"     ), "RW", 16, field_default(0) ),
+      ( field_name_pad("dp_channel"   ), "RW", 16, field_default(0) ),
+      ( field_name_pad("dp_sync"      ), "RW",  1, field_default(0) ),
+      ( field_name_pad("dp_bsn"       ), "RW", 63, field_default(0) )
+  );
+
+  FUNCTION func_nof_hops_to_source_rn(hops, this_rn, N_rn, lane_dir : NATURAL) RETURN NATURAL;
+  FUNCTION func_nof_hops_to_source_rn(hops, this_rn, N_rn : STD_LOGIC_VECTOR; lane_dir : NATURAL) RETURN STD_LOGIC_VECTOR; -- return vector length is same as hops vector length
+
  END PACKAGE ring_pkg;
 
 PACKAGE BODY ring_pkg IS
 
+  FUNCTION func_nof_hops_to_source_rn(hops, this_rn, N_rn, lane_dir : NATURAL) RETURN NATURAL IS
+    VARIABLE v_source_rn     : INTEGER;
+    VARIABLE v_source_rn_nat : NATURAL;
+  BEGIN
+
+    IF lane_dir > 0 THEN
+      v_source_rn := this_rn - hops;
+    ELSE
+      v_source_rn := this_rn + hops;
+    END IF;
+
+    IF v_source_rn < 0 THEN -- Cannot use MOD as N_rn is not a constant.
+      v_source_rn := v_source_rn + N_rn;
+    END IF;
+
+    IF v_source_rn > N_rn THEN
+      v_source_rn := v_source_rn - N_rn;
+    END IF;
+
+    v_source_rn_nat := v_source_rn;
+    RETURN v_source_rn_nat;
+  END;
+
+  FUNCTION func_nof_hops_to_source_rn(hops, this_rn, N_rn : STD_LOGIC_VECTOR; lane_dir : NATURAL) RETURN STD_LOGIC_VECTOR IS
+  BEGIN
+    RETURN TO_UVEC(func_nof_hops_to_source_rn(TO_UINT(hops), TO_UINT(N_rn), TO_UINT(N_rn), lane_dir),hops'LENGTH);
+  END;
   
 END ring_pkg;
 
diff --git a/libraries/base/ring/src/vhdl/ring_tx.vhd b/libraries/base/ring/src/vhdl/ring_tx.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..4e8d6c7d3ff2173ccc915aa0ce8182c2744c4459
--- /dev/null
+++ b/libraries/base/ring/src/vhdl/ring_tx.vhd
@@ -0,0 +1,229 @@
+-------------------------------------------------------------------------------
+--
+-- 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
+
+-- Purpose: Handle TX side of ring design.
+-- Description: See https://support.astron.nl/confluence/x/jyu7Ag
+-- Remark:
+-- .
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, mm_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE work.ring_pkg.ALL;
+
+ENTITY ring_tx IS
+  GENERIC (
+    g_lane_direction   : NATURAL := 1;
+    g_data_w           : NATURAL := 64;
+    g_symbol_w         : NATURAL := 8;
+    g_ring_pkt_type    : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0) := c_ring_pkt_type_bf;
+    g_validate_channel : BOOLEAN := TRUE;
+    g_mode             : STRING  := ">";
+    g_nof_tx_monitors  : NATURAL := 1
+  );
+  PORT (
+    -- Clocks and reset
+    mm_rst                  : IN  STD_LOGIC;   -- reset synchronous with mm_clk
+    mm_clk                  : IN  STD_LOGIC;   -- memory-mapped bus clock
+
+    dp_clk                  : IN  STD_LOGIC;
+    dp_rst                  : IN  STD_LOGIC;
+
+    to_lane_sosi            : IN  t_dp_sosi;
+    lane_tx_cable_sosi      : OUT t_dp_sosi;
+    lane_tx_board_sosi      : OUT t_dp_sosi;
+
+    reg_bsn_monitor_v2_mosi : IN  t_mem_mosi;
+    reg_bsn_monitor_v2_miso : OUT t_mem_miso;
+   
+    tx_select               : IN  STD_LOGIC;
+    remove_channel          : IN  STD_LOGIC_VECTOR(c_dp_stream_channel_w-1 DOWNTO 0);
+    this_rn                 : IN  STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+    N_rn                    : IN  STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0)
+  );
+END ring_tx;
+
+ARCHITECTURE str OF ring_tx IS
+
+  CONSTANT c_use_empty      : BOOLEAN := sel_a_b(g_symbol_w = g_data_w, FALSE, TRUE);
+  CONSTANT c_empty_w        : NATURAL := ceil_log2(g_data_w / g_symbol_w);
+  CONSTANT c_use_dp_layer   : BOOLEAN := TRUE;
+  CONSTANT c_nof_hdr_fields : NATURAL := sel_a_b(c_use_dp_layer, c_ring_dp_nof_hdr_fields, c_ring_eth_nof_hdr_fields);
+  CONSTANT c_hdr_field_sel  : STD_LOGIC_VECTOR(c_nof_hdr_fields-1 DOWNTO 0)   := sel_a_b(c_use_dp_layer, c_ring_dp_hdr_field_sel, c_ring_eth_hdr_field_sel);
+  CONSTANT c_hdr_field_arr  : t_common_field_arr(c_nof_hdr_fields-1 DOWNTO 0) := sel_a_b(c_use_dp_layer, c_ring_dp_hdr_field_arr, c_ring_eth_hdr_field_arr);
+  CONSTANT c_fifo_size      : NATURAL := 5; -- Large enough to fit ETH/DP header.
+
+  SIGNAL validated_sosi   : t_dp_sosi;
+  SIGNAL tx_sosi          : t_dp_sosi;
+  SIGNAL tx_fifo_sosi     : t_dp_sosi;
+  SIGNAL tx_fifo_siso     : t_dp_siso;
+  SIGNAL lane_tx_sosi     : t_dp_sosi;
+  SIGNAL monitor_sosi     : t_dp_sosi;
+  SIGNAL monitor_sosi_arr : t_dp_sosi_arr(g_nof_tx_monitors-1 DOWNTO 0);
+
+  SIGNAL hdr_fields_in     : STD_LOGIC_VECTOR(1023 DOWNTO 0);
+  SIGNAL hdr_fields_in_reg : STD_LOGIC_VECTOR(1023 DOWNTO 0);
+
+BEGIN
+  -- Validate transport_nof_hops
+  gen_validate : IF g_validate_channel GENERATE
+    u_dp_block_validate_channel: ENTITY dp_lib.dp_block_validate_channel
+    GENERIC MAP (
+      g_mode           => g_mode
+    )
+    PORT MAP (
+      dp_rst => dp_rst,
+      dp_clk => dp_clk,
+
+      in_sosi       => to_lane_sosi,
+      out_keep_sosi => validated_sosi,
+      
+      remove_channel => remove_channel    
+    );
+  END GENERATE;
+  -- Don't validate transport_nof_hops
+  gen_no_validate : IF NOT g_validate_channel GENERATE
+    validated_sosi <= to_lane_sosi;
+  END GENERATE;
+
+  -- increase channel by 1, e.g. add 1 hop.
+  p_hop: PROCESS(validated_sosi)
+  BEGIN
+    tx_sosi <= validated_sosi;
+    IF TO_UINT(validated_sosi.channel) >= TO_UINT(N_rn)-1 THEN
+      tx_sosi.channel <= (OTHERS => '0');
+    ELSE
+      tx_sosi.channel <= INCR_DP_CHANNEL(validated_sosi.channel, 1, c_dp_stream_channel_w);
+    END IF;
+  END PROCESS;
+
+  -- Encode packet header
+  hdr_fields_in(field_hi(c_hdr_field_arr, "eth_dst_mac"  ) DOWNTO field_lo(c_hdr_field_arr, "eth_dst_mac" )) <= c_ring_eth_dst_mac;
+  hdr_fields_in(field_hi(c_hdr_field_arr, "eth_src_mac"  ) DOWNTO field_lo(c_hdr_field_arr, "eth_src_mac" )) <= c_ring_eth_src_mac;
+  hdr_fields_in(field_hi(c_hdr_field_arr, "eth_type"     ) DOWNTO field_lo(c_hdr_field_arr, "eth_type"    )) <= g_ring_pkt_type;
+  gen_hdr_dp : IF c_use_dp_layer GENERATE
+    hdr_fields_in(field_hi(c_hdr_field_arr, "dp_channel" ) DOWNTO field_lo(c_hdr_field_arr, "dp_channel"  )) <= tx_sosi.channel(c_halfword_w-1 DOWNTO 0);
+    hdr_fields_in(field_hi(c_hdr_field_arr, "dp_sync"    ) DOWNTO field_lo(c_hdr_field_arr, "dp_sync"     )) <= slv(tx_sosi.sync);
+    hdr_fields_in(field_hi(c_hdr_field_arr, "dp_bsn"     ) DOWNTO field_lo(c_hdr_field_arr, "dp_bsn"      )) <= tx_sosi.bsn(62 DOWNTO 0);
+  END GENERATE;
+
+  -- Lead DP info around the FIFO via hdr_fields_in_reg, to avoid having to pass on the DP info via the FIFO, to save on block RAM.
+  hdr_fields_in_reg <= hdr_fields_in WHEN rising_edge(dp_clk) AND tx_sosi.sop = '1' ELSE hdr_fields_in_reg;
+
+  -- Fifo for inserting header
+  u_dp_fifo_sc: ENTITY dp_lib.dp_fifo_sc
+  GENERIC MAP (
+    g_data_w    => g_data_w,
+    g_empty_w   => c_empty_w,
+    g_use_empty => c_use_empty,
+    g_fifo_size => c_fifo_size
+  )
+  PORT MAP (
+    rst => dp_rst,
+    clk => dp_clk,
+
+    snk_in => tx_sosi,
+
+    src_out => tx_fifo_sosi,
+    src_in  => tx_fifo_siso
+  );
+
+  -- Inserting ETH/DP header
+  u_dp_offload_tx_v3: ENTITY dp_lib.dp_offload_tx_v3
+  GENERIC MAP (
+    g_nof_streams   => 1,
+    g_data_w        => g_data_w,
+    g_symbol_w      => g_symbol_w,
+    g_hdr_field_arr => c_hdr_field_arr,
+    g_hdr_field_sel => c_hdr_field_sel
+  )
+  PORT MAP (
+    mm_rst => mm_rst,
+    mm_clk => mm_clk,
+
+    dp_rst => dp_rst,
+    dp_clk => dp_clk,
+
+    snk_in_arr(0)  => tx_fifo_sosi,
+    snk_out_arr(0) => tx_fifo_siso,
+    src_out_arr(0) => lane_tx_sosi,
+
+    hdr_fields_in_arr(0)  => hdr_fields_in_reg
+  );
+
+  -- Select output based on tx_select
+  p_sel_out : PROCESS(lane_tx_sosi, tx_select)
+  BEGIN
+    IF tx_select = '1' THEN -- transmit via cable
+      lane_tx_cable_sosi <= lane_tx_sosi; 
+      lane_tx_board_sosi <= c_dp_sosi_rst; 
+    ELSE -- transmit via  board
+      lane_tx_cable_sosi <= c_dp_sosi_rst; 
+      lane_tx_board_sosi <= lane_tx_sosi;    
+    END IF;
+  END PROCESS;
+ 
+  -- BSN Monitors
+  gen_bsn_monitors : IF c_use_dp_layer GENERATE
+    -- Convert nof_hops to source RN
+    p_hop_to_src_rn: PROCESS(validated_sosi, this_rn, N_rn)
+    BEGIN
+      monitor_sosi <= validated_sosi;
+      monitor_sosi.channel <= func_nof_hops_to_source_rn(validated_sosi.channel, this_rn, N_rn, g_lane_direction);
+    END PROCESS;
+
+    u_dp_demux : ENTITY dp_lib.dp_demux
+    GENERIC MAP (
+      g_nof_output => g_nof_tx_monitors,
+      g_sel_ctrl_invert => TRUE
+    )
+    PORT MAP (
+      rst         => dp_rst,
+      clk         => dp_clk,
+      snk_in      => monitor_sosi,
+      src_out_arr => monitor_sosi_arr 
+    );
+
+    u_mms_dp_bsn_monitor_v2 : ENTITY dp_lib.mms_dp_bsn_monitor_v2
+    GENERIC MAP (
+      g_nof_streams => g_nof_tx_monitors
+    )
+    PORT MAP (
+      mm_rst      => mm_rst,
+      mm_clk      => mm_clk,
+      reg_mosi    => reg_bsn_monitor_v2_mosi,
+      reg_miso    => reg_bsn_monitor_v2_miso,
+
+      dp_rst      => dp_rst,
+      dp_clk      => dp_clk,
+      in_sosi_arr => monitor_sosi_arr
+    );
+
+  END GENERATE; 
+
+END str;
diff --git a/libraries/dsp/st/doc/st_histogram_status.txt b/libraries/dsp/st/doc/st_histogram_status.txt
index f657cbdac864fb1e3fb1bbdac710093afe9ed959..648b455ea7fd14b2d925085f4e699be630c404e2 100644
--- a/libraries/dsp/st/doc/st_histogram_status.txt
+++ b/libraries/dsp/st/doc/st_histogram_status.txt
@@ -3,15 +3,20 @@ Status of st_histogram on june 2021 after merge to master in GitLab.
 EK = Eric Kooistra
 DS = Daniel van der Schuur
 
-In summary the things to do still for st_histogram are (this can be done in new Jira story):
+In summary the things to do still for st_histogram are (this can be done in
+new Jira story):
 
 - add top level functional description (see 2b, 3)
 - explain why common_paged_ram_r_w was not used (see 2a)
 - remove control via MM (see 3, 4, 5a)
+- explain the block RAM usage (see 2b, 3)
 - verify using DC signal (see 5b)
-- verify that sum(bins) has expected constant value every sync interval (see 5c)
+- verify that sum(bins) has expected constant value every sync interval
+  (see 5c)
 
-Below, for reference, EK copied the left over comments and answers from the GitLab merge ( https://git.astron.nl/desp/hdl/-/merge_requests/101 ) of the st_histogram VHDL in L2SDP-151 into L2SDP-143 and then into the master.
+Below, for reference, EK copied the left over comments and answers from the
+GitLab merge ( https://git.astron.nl/desp/hdl/-/merge_requests/101 ) of the
+st_histogram VHDL in L2SDP-151 into L2SDP-143 and then into the master.
 
 
 1) mms_st_histogram.vhd - no comments
@@ -22,20 +27,32 @@ a) EK comment
 
 Why common_ram_r_w was selected instead of common_ram_cr_cw ?
 
-Waarom gebruik je niet common_paged_ram_r_w.vhd voor de RAM ? Kun je dat in comment aangeven, of vermelden dat common_paged_ram_r_w ook gebruikt had kunnen worden.
+Waarom gebruik je niet common_paged_ram_r_w.vhd voor de RAM ? Kun je dat in
+comment aangeven, of vermelden dat common_paged_ram_r_w ook gebruikt had
+kunnen worden.
 
 
 b) EK comment
 
-Waarom kan read en write tegelijk voorkomen? --> Wat beslist de bus arbiter dan? --> Wat is het gevolg dan voor de bin waardes ?
+Waarom kan read en write tegelijk voorkomen? --> Wat beslist de bus arbiter
+dan? --> Wat is het gevolg dan voor de bin waardes ?
 
-Hoe ziet de st_histogram werking er in de tijd van een sync interval uit? Tellen de bins echt alle samples, of gaan er steed bijv K samples per sync interval verloren, dat is acceptabel mits K constant is en K << N = nof samples per sync.
+Hoe ziet de st_histogram werking er in de tijd van een sync interval uit?
+Tellen de bins echt alle samples, of gaan er steeds bijvoorbeeld K samples
+per sync interval verloren, dat is acceptabel mits K constant is en mits
+K << N = nof samples per sync.
 
-Eigenlijk ontbreekt nog de beschrijving op functioneel niveau, los van de implementatie details, bijvoorbeeld zaken als:
+Eigenlijk ontbreekt nog de beschrijving op functioneel niveau, los van de
+implementatie details, bijvoorbeeld zaken als:
 
-* The number of bins in the histogram g_nof_bins is a power of 2 and g_nof_bins_w <= g_data_w, so each bin counts the occurance of a subrange with 2**(g_data_w - g_nof_bins_w) samples values.
-* The sample values in range g_data_w get mapped to g_nof_bins by counting how often the sample value(s) for that bin occur during a sync interval.
-* The sum of the histogram bin values in each sync interval is : sum(bins) = N - K (klopt dat)?
+* The number of bins in the histogram g_nof_bins is a power of 2 and
+  g_nof_bins_w <= g_data_w, so each bin counts the occurance of a subrange
+  with 2**(g_data_w - g_nof_bins_w) samples values.
+* The sample values in range g_data_w get mapped to g_nof_bins by counting
+  how often the sample value(s) for that bin occur during a sync interval.
+* The sum of the histogram bin values in each sync interval is : sum(bins)
+  = N - K (klopt dat)?
+* Block RAM usage overview, how many block RAM per signal input?
 
 
 
@@ -43,60 +60,90 @@ Eigenlijk ontbreekt nog de beschrijving op functioneel niveau, los van de implem
 
 ==> EK comment
 
-Ik snap niet waarom ram_clear en ram_fill nodig zijn op het MM interface. Voor ADUH_MON mean, power en voor SST is dat ook niet nodig.
+Ik snap niet waarom ram_clear en ram_fill nodig zijn op het MM interface.
+Voor ADUH_MON mean, power en voor SST is dat ook niet nodig.
 
-Eigenlijk moet het zo zijn dat de user op elk moment st_histogram RAM uit mag lezen, zonder extra polling of controlling. Als de user toevallig leest terwijl de pages swap, dan zal een deel van de bins bij het ene sync interval horen en de rest van de bins uit het volgende sync interval komen, maar dat is niet erg, want waarschijnlijk veranderd de histogram toch niet veel van sync interval op sync interval. Daarbij komt dat de kans dat de user precies tijdens een sync het histogram leest klein is, want lezen duurt veel korter dan 1 sync interval.
+Eigenlijk moet het zo zijn dat de user op elk moment st_histogram RAM uit mag
+lezen, zonder extra polling of controlling. Als de user toevallig leest
+terwijl de pages swap, dan zal een deel van de bins bij het ene sync interval
+horen en de rest van de bins uit het volgende sync interval komen, maar dat
+is niet erg, want waarschijnlijk verandert de histogram toch niet veel van
+sync interval op sync interval. Daarbij komt dat de kans dat de user precies
+tijdens een sync het histogram leest klein is, want lezen duurt veel korter
+dan 1 sync interval.
 
-Kunnen we st_histogram_reg.vhd verwijderen van het MM interface en vervangen door een intern VHDL process dat op fixed momenten de write velden bedient ?
+Kunnen we st_histogram_reg.vhd verwijderen van het MM interface en vervangen
+door een intern VHDL process dat op fixed momenten de write velden bedient ?
 
-In een los Python scriptje is st_histogram_reg nog wel te bedienen, maar in een compleet M&C systeem (driver) is het denk ik te ingewikkeld en te belastend.
+In een los Python scriptje is st_histogram_reg nog wel te bedienen, maar in
+een compleet M&C systeem (driver) is het denk ik te ingewikkeld en te
+belastend.
 
 
 ==> DS antwoord:
 
-De ram_clear control is per abuis achtergebleven; deze was al vervangen voor een automatisch VHDL proces. Ik heb dit gefixt in de code.
+De ram_clear control is per abuis achtergebleven; deze was al vervangen voor
+een automatisch VHDL proces. Ik heb dit gefixt in de code.
 
-De ram_fill control bedient in essentie een g_nof_instances (12 voor LOFAR) naar 1 DP->MM selector. Er is dus maar 1 MM RAM en de user kiest middels de ram_fill control van welke van de g_nof_instances (12 voor lofar) de inhoud in de MM RAM moet staan. Dit bespaart g_nof_instances-1 RAM blocks.
+De ram_fill control bedient in essentie een g_nof_instances (12 voor LOFAR)
+naar 1 DP->MM selector. Er is dus maar 1 MM RAM en de user kiest middels de
+ram_fill control van welke van de g_nof_instances (12 voor lofar) de inhoud
+in de MM RAM moet staan. Dit bespaart g_nof_instances-1 RAM blocks.
 
-Goed punt over de M&C belasting hierdoor. We zouden hier (automated VHDL proces ipv MM control) een JIRA ticket van kunnen maken.
+Goed punt over de M&C belasting hierdoor. We zouden hier (automated VHDL
+proces ipv MM control) een JIRA ticket van kunnen maken.
 
 
 4) tb_mms_st_histogram.vhd
 
 ==> EK comment:
 
-Only needs to verify that the MM interface is connected properly, so should be a minimal tb. The details of the st_histogram inner workings have already been verified by tb_st_histogram.
+Only needs to verify that the MM interface is connected properly, so should
+be a minimal tb. The details of the st_histogram inner workings have already
+been verified by tb_st_histogram.
 
 ==> DS antwoord:
-tb_st_histogram tests only a single instance. tb_mms_st_histogram tests mms_st_histogram which has multi-instance support and the ram_fill control discussed above. Depending on what we do with ram_fill topic, we might no longer need the tb_mms. Possible JIRA ticket
+tb_st_histogram tests only a single instance. tb_mms_st_histogram tests
+mms_st_histogram which has multi-instance support and the ram_fill control
+discussed above. Depending on what we do with ram_fill topic, we might no
+longer need the tb_mms. Possible JIRA ticket
 
 
 5) tb_st_histogram.vhd
 
 a) EK comment:
 
-The tb does not use reg_mosi, is that not needed ? But why is reg_mosi port then on the st_histogram ?
+The tb does not use reg_mosi, is that not needed ? But why is reg_mosi port
+then on the st_histogram ?
 
 ==> DS antwoord:
 
-st_histogram.vhd does not have a reg_mosi port. tb_st_histogram tests only a single instance. tb_mms_st_histogram tests mms_st_histogram which has multi-instance support and the ram_fill control discussed above. Depending on what we do with ram_fill topic, we might no longer need the tb_mms. Possible JIRA ticket
+st_histogram.vhd does not have a reg_mosi port. tb_st_histogram tests only a
+single instance. tb_mms_st_histogram tests mms_st_histogram which has
+multi-instance support and the ram_fill control discussed above. Depending
+on what we do with ram_fill topic, we might no longer need the tb_mms.
+Possible JIRA ticket
 
 
 b) EK comment:
 
 What kind of data is used, does proc_dp_gen_block_data increment it?
 
-Have you tested using DC data ? I think having multiple sample values in a row that are important to try too.
+Have you tested using DC data ? I think having multiple sample values in a row
+that are important to try too.
 
 ==> DS antwoord:
 
-Good point, we're only using counter data at this point. st_histogram should work with DC data but this really needs to be added to the TB. Possible JIRA ticket
+Good point, we're only using counter data at this point. st_histogram should
+work with DC data but this really needs to be added to the TB. Possible JIRA
+ticket.
 
 
 c) EK comment:
 
-Can you also check in a process that sum(bins) has always the expected constant value ?
+Can you also check in a process that sum(bins) has always the expected
+constant value ?
 
 ==> DS antwoord:    Collapse replies
 
-This would be a good addition to the TB. Possible (par of) JIRE ticket
+This would be a good addition to the TB. Possible (par of) JIRE ticket.
diff --git a/libraries/dsp/st/st.peripheral.yaml b/libraries/dsp/st/st.peripheral.yaml
index 23b11ddf8086194ade628fc1ec8e98d84e14d0b3..805b806ab85e5b5e6d6798883148f55d1d553814 100644
--- a/libraries/dsp/st/st.peripheral.yaml
+++ b/libraries/dsp/st/st.peripheral.yaml
@@ -34,7 +34,7 @@ peripherals:
         fields:
           - - field_name: power
               field_description: ""
-              number_of_fields: g_nof_stat * g_stat_data_sz
+              number_of_fields: g_nof_stat
               address_offset: 0x0
               mm_width: 32
               user_width: g_stat_data_w
@@ -46,7 +46,7 @@ peripherals:
        "Accumulate the subband auto power values during a sync interval for the subband statistics (SST) in LOFAR2.0 SDP"
     parameters:
       # Parameters of pi_st_sst.py, fixed in node_sdp_filterbank.vhd / sdp_pkg.vhd
-      - { name: g_nof_instances, value: 6 }
+      - { name: g_nof_instances, value: 6 }  # c_sdp_P_pfb = 6
       # Parameters of st_sst.vhd, fixed in node_sdp_filterbank.vhd / sdp_pkg.vhd
       - { name: g_nof_stat, value: 1024 }  # nof accumulators:  N_sub * Q_fft = 512 * 2 = 1024
       - { name: g_stat_data_w, value: 54 }  # statistics accumulator user_width in bits: W_statistic = 64
@@ -67,7 +67,7 @@ peripherals:
         fields:
           - - field_name: power
               field_description: ""
-              number_of_fields: g_nof_stat * g_stat_data_sz
+              number_of_fields: g_nof_stat
               address_offset: 0x0
               mm_width: 32
               user_width: g_stat_data_w
@@ -79,7 +79,7 @@ peripherals:
        "Accumulate the beamlet auto power values during a sync interval for the beamlet statistics (BST) in LOFAR2.0 SDP"
     parameters:
       # Parameters of pi_st_bst.py, fixed in node_sdp_beamformer.vhd / sdp_pkg.vhd
-      - { name: g_nof_instances, value: 6 }
+      - { name: g_nof_instances, value: 1 }
       # Parameters of st_sst.vhd, fixed in node_sdp_filterbank.vhd / sdp_pkg.vhd
       - { name: g_nof_stat, value: 976 }  # nof accumulators:  S_sub_bf * N_pol_bf = 488 * 2 = 976
       - { name: g_stat_data_w, value: 54 }  # statistics accumulator user_width in bits: W_statistic = 64
@@ -95,11 +95,11 @@ peripherals:
            (uint64)BST[g_nof_stat] = (uint64)BST[S_sub_bf][N_pol_bf]
 
            where N_pol_bf = 2 and S_sub_bf = 488 are defined in sdp_pkg.vhd."
-        number_of_mm_ports: 1
+        number_of_mm_ports: g_nof_instances
         fields:
           - - field_name: power
               field_description: ""
-              number_of_fields: g_nof_stat * g_stat_data_sz
+              number_of_fields: g_nof_stat
               address_offset: 0x0
               mm_width: 32
               user_width: g_stat_data_w
@@ -112,27 +112,50 @@ peripherals:
     parameters:
       # Parameters of pi_st_xst.py, fixed in node_sdp_correlator.vhd / sdp_pkg.vhd
       - { name: g_nof_streams, value: 9 } # P_sq
-      # Parameters of st_xst.vhd, fixed in node_sdp_correlator.vhd / sdp_pkg.vhd
+      # Parameters of st_xst.vhd, st_xsq_arr.vhd fixed in node_sdp_correlator.vhd / sdp_pkg.vhd
       - { name: g_nof_crosslets, value: 1 }  # N_crosslets
       - { name: g_nof_signal_inputs, value: 12 }  # S_pn = 12
       - { name: g_in_data_w, value: 16 }  # W_crosslet = 16
       - { name: g_stat_data_w, value: 64 }  # W_statistic = 64
       - { name: g_stat_data_sz, value: 2 }  # W_statistic_sz = 2
     mm_ports:
-      # MM port for st_sst.vhd
+      # MM port for st_xst.vhd
       - mm_port_name: RAM_ST_XSQ
         mm_port_type: RAM
+        # from sdp_pkg.vhd:
+        # . c_sdp_ram_st_xsq_addr_w = ceil_log2(P_sq) + ceil_log2(N_crosslets * X_sq * c_nof_complex * (c_longword_sz/c_word_sz)
+        # . c_sdp_X_sq = S_pn**2 = g_nof_signal_inputs**2
+        mm_port_span: ceil_pow2(g_nof_streams) + ceil_pow2(g_nof_crosslets * g_nof_signal_inputs**2 * c_nof_complex * g_stat_data_sz) * MM_BUS_SIZE
         mm_port_description: |
-          "The crosslets statistics per PN are stored in 1 block of 
-           g_nof_crosslets * g_nof_signal_inputs**2 * c_nof_complex * g_stat_data_sz = 1 * 12 * 12 * 2 * 2 = 576 values as:
+          "The crosslets statistics per PN are stored in g_nof_streams blocks
+           of each nof_stat values per block (= per X_sq correlator cell). The
+           N_crosslets are stored tightly in series per block:
+
+             nof_stat = g_nof_crosslets * g_nof_signal_inputs**2
+                      # g_nof_crosslets = 1:
+                      = 1 * 12 * 12 = 144 complex values = number_of_fields
+                      = c_nof_complex * 144 = 288 real values
+                      = g_stat_data_sz * 288 = 576 MM words --> mm_port_span = 1024
+                      # g_nof_crosslets = 7:
+                      = 7 * 12 * 12 = 1008 complex values = number_of_fields
+                      = c_nof_complex * 1008 = 2016 real values
+                      = g_stat_data_sz * 2016 = 4032 MM words --> mm_port_span = 4096
+
+           in this format:
+
+             (cint64)XST[] = XST[crosslets][in A][in B][N_complex][g_stat_data_sz]
 
-           (cint64)XST[] = (cint64)XST[crosslets][in A][in B][complex][word]"
+           In total there are g_nof_streams = P_sq parallel X_sq blocks in the MM
+           peripheral span:
 
-        number_of_mm_ports: 1
+             mm_peripheral_span = ceil_pow2(g_nof_streams) * ceil_pow2(nof_stat MM words)
+                                = 16 * 1024 = 16K = 0x4000 when N_crosslets = 1
+                                = 16 * 4096 = 64K = 0x10000 when N_crosslets = 7."
+        number_of_mm_ports: g_nof_streams
         fields:
           - - field_name: power
               field_description: ""
-              number_of_fields: 576
+              number_of_fields: g_nof_crosslets * g_nof_signal_inputs**2
               address_offset: 0x0
               mm_width: 32
               user_width: g_stat_data_w
diff --git a/libraries/io/ppsh/tb/vhdl/tb_mms_ppsh.vhd b/libraries/io/ppsh/tb/vhdl/tb_mms_ppsh.vhd
index 39e21de98a90bb33568d11fbeed94e304dc52444..d308e06249db71b1111e2183d43cbd900c416d37 100644
--- a/libraries/io/ppsh/tb/vhdl/tb_mms_ppsh.vhd
+++ b/libraries/io/ppsh/tb/vhdl/tb_mms_ppsh.vhd
@@ -32,13 +32,18 @@ END tb_mms_ppsh;
 
 ARCHITECTURE tb OF tb_mms_ppsh IS
 
-  CONSTANT c_clk_freq     : NATURAL := 1000;                  -- clock frequency in Hz
-  CONSTANT c_clk_period   : TIME    := 1000000 us / c_clk_freq;
-  CONSTANT c_pps_period   : NATURAL := c_clk_freq;            -- 1 s takes c_clk_freq clk cycles
+  CONSTANT c_st_clk_freq     : NATURAL := 1000;                  -- clock frequency in Hz
+  CONSTANT c_st_clk_period   : TIME    := 1000000 us / c_st_clk_freq;
+  CONSTANT c_mm_clk_period   : TIME    := c_st_clk_period * 3;   -- somewhat slower mm_clk
+  CONSTANT c_pps_period      : NATURAL := c_st_clk_freq;            -- 1 s takes c_clk_freq clk cycles
+
+  CONSTANT c_cnt_w           : NATURAL := ceil_log2(c_st_clk_freq);
 
   SIGNAL tb_end           : STD_LOGIC := '0';
-  SIGNAL rst              : STD_LOGIC := '1';
-  SIGNAL clk              : STD_LOGIC := '1';
+  SIGNAL mm_rst           : STD_LOGIC := '1';
+  SIGNAL mm_clk           : STD_LOGIC := '1';
+  SIGNAL st_rst           : STD_LOGIC := '1';
+  SIGNAL st_clk           : STD_LOGIC := '1';
 
   -- DUT
   SIGNAL pps_ext          : STD_LOGIC;
@@ -48,7 +53,7 @@ ARCHITECTURE tb OF tb_mms_ppsh IS
   SIGNAL reg_miso         : t_mem_miso;
 
   -- Verify
-  SIGNAL bsn              : NATURAL;
+  SIGNAL bsn              : NATURAL;  -- block sequence number counts seconds
   SIGNAL pps_toggle       : STD_LOGIC;
   SIGNAL pps_stable       : STD_LOGIC;
   SIGNAL capture_cnt      : NATURAL;
@@ -65,8 +70,10 @@ BEGIN
   -----------------------------------------------------------------------------
   -- Stimuli
   -----------------------------------------------------------------------------
-  rst <= '1', '0' AFTER 7*c_clk_period;
-  clk <= NOT clk OR tb_end AFTER c_clk_period/2;
+  st_rst <= '1', '0' AFTER 7*c_st_clk_period;
+  st_clk <= NOT st_clk OR tb_end AFTER c_st_clk_period/2;
+  mm_rst <= '1', '0' AFTER 7*c_mm_clk_period;
+  mm_clk <= NOT mm_clk OR tb_end AFTER c_mm_clk_period/2;
 
   p_pps_ext : PROCESS
     VARIABLE v_pps_period : NATURAL := c_pps_period;
@@ -81,10 +88,10 @@ BEGIN
       ELSIF bsn = 69 THEN
         v_pps_period := c_pps_period+1;
       END IF;
-      proc_common_wait_some_cycles(clk, v_pps_period-1);
+      proc_common_wait_some_cycles(st_clk, v_pps_period-1);
       pps_ext <= '1';
       bsn <= bsn + 1;
-      proc_common_wait_some_cycles(clk, 1);
+      proc_common_wait_some_cycles(st_clk, 1);
       pps_ext <= '0';
     END LOOP;
 
@@ -94,88 +101,89 @@ BEGIN
   p_mm_stimuli : PROCESS
     VARIABLE v_word : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
   BEGIN
-    proc_common_wait_until_low(clk, rst);                      -- Wait until reset has finished
-    proc_common_wait_some_cycles(clk, 10);                     -- Wait an additional amount of cycles
+    proc_common_wait_until_low(st_clk, st_rst);                -- Wait until reset has finished
+    proc_common_wait_until_low(mm_clk, mm_rst);                -- Wait until reset has finished
+    proc_common_wait_some_cycles(mm_clk, 10);                  -- Wait an additional amount of cycles
 
     v_word := '0' & TO_UVEC(c_pps_period, 31);   -- capture_edge = '0' = at rising edge
                                                  -- expected_cnt = c_pps_period = 1000
-    proc_mem_mm_bus_wr(1, v_word, clk, reg_mosi);
+    proc_mem_mm_bus_wr(1, v_word, mm_clk, reg_mosi);
 
 
     -- Simulate reading PPS status every 10 PPS periods
-    proc_common_wait_some_cycles(clk, 10);
+    proc_common_wait_some_cycles(st_clk, 10);
     FOR I IN 0 TO 9 LOOP
-      proc_common_wait_some_cycles(clk, c_pps_period*10);
+      proc_common_wait_some_cycles(st_clk, c_pps_period*10);
 
-      proc_mem_mm_bus_rd(0, clk, reg_mosi);
-      proc_common_wait_some_cycles(clk, 1);
+      proc_mem_mm_bus_rd(0, mm_clk, reg_mosi);
+      proc_common_wait_some_cycles(mm_clk, 1);
       pps_toggle  <= reg_miso.rddata(31);
       pps_stable  <= reg_miso.rddata(30);
-      capture_cnt <= TO_UINT(reg_miso.rddata(ceil_log2(c_clk_freq)-1 DOWNTO 0));
+      capture_cnt <= TO_UINT(reg_miso.rddata(c_cnt_w-1 DOWNTO 0));
     END LOOP;
 
-    -- Simulate reading PPS offset counter every 0.1 PPS periods
-    proc_common_wait_some_cycles(clk, 10);
-    FOR I IN 0 TO 4 LOOP
-      proc_common_wait_some_cycles(clk, c_pps_period/10);
+    -- Simulate reading PPS offset counter every 0.25 PPS periods
+    proc_common_wait_some_cycles(st_clk, 10);
+    FOR I IN 0 TO 40 LOOP
+      proc_common_wait_some_cycles(st_clk, c_pps_period/4);
       last_offset_cnt <= offset_cnt;
-      proc_mem_mm_bus_rd(2, clk, reg_mosi);
-      proc_common_wait_some_cycles(clk, 1);
-      offset_cnt <= TO_UINT(reg_miso.rddata(ceil_log2(c_clk_freq)-1 DOWNTO 0));
+      proc_mem_mm_bus_rd(2, mm_clk, reg_mosi);
+      proc_common_wait_some_cycles(mm_clk, 1);
+      offset_cnt <= TO_UINT(reg_miso.rddata(c_cnt_w-1 DOWNTO 0));
     END LOOP;
 
-    proc_common_wait_some_cycles(clk, 100);
+    proc_common_wait_some_cycles(st_clk, 100);
     tb_end <= '1';
     WAIT;
   END PROCESS;
 
   p_verify : PROCESS
   BEGIN
-    proc_common_wait_until_low(clk, rst);                      -- Wait until reset has finished
-    proc_common_wait_some_cycles(clk, 10);                     -- Wait an additional amount of cycles
+    proc_common_wait_until_low(st_clk, st_rst);                   -- Wait until reset has finished
+    proc_common_wait_some_cycles(st_clk, 10);                     -- Wait an additional amount of cycles
 
-    proc_common_wait_some_cycles(clk, c_pps_period/2);         -- Verification offset
+    proc_common_wait_some_cycles(st_clk, c_pps_period/2);         -- Verification offset
     -- 1
-    proc_common_wait_some_cycles(clk, c_pps_period*10);
+    proc_common_wait_some_cycles(st_clk, c_pps_period*10);
     ASSERT pps_stable='0'   REPORT "1) Wrong pps_stable" SEVERITY ERROR;
     ASSERT capture_cnt=1000 REPORT "1) Wrong capture_cnt" SEVERITY ERROR;
     -- 2
-    proc_common_wait_some_cycles(clk, c_pps_period*10);
+    proc_common_wait_some_cycles(st_clk, c_pps_period*10);
     ASSERT pps_stable='1'   REPORT "2) Wrong pps_stable" SEVERITY ERROR;
     ASSERT capture_cnt=1000 REPORT "2) Wrong capture_cnt" SEVERITY ERROR;
     -- 3
-    proc_common_wait_some_cycles(clk, c_pps_period*10);
+    proc_common_wait_some_cycles(st_clk, c_pps_period*10);
     ASSERT pps_stable='0'   REPORT "3) Wrong pps_stable" SEVERITY ERROR;
     ASSERT capture_cnt=999  REPORT "3) Wrong capture_cnt" SEVERITY ERROR;
     -- 4
-    proc_common_wait_some_cycles(clk, c_pps_period*10);
+    proc_common_wait_some_cycles(st_clk, c_pps_period*10);
     ASSERT pps_stable='0'   REPORT "4) Wrong pps_stable" SEVERITY ERROR;
     ASSERT capture_cnt=1000 REPORT "4) Wrong capture_cnt" SEVERITY ERROR;
     -- 5
-    proc_common_wait_some_cycles(clk, c_pps_period*10);
+    proc_common_wait_some_cycles(st_clk, c_pps_period*10);
     ASSERT pps_stable='1'   REPORT "5) Wrong pps_stable" SEVERITY ERROR;
     ASSERT capture_cnt=1000 REPORT "5) Wrong capture_cnt" SEVERITY ERROR;
     -- 6
-    proc_common_wait_some_cycles(clk, c_pps_period*10);
+    proc_common_wait_some_cycles(st_clk, c_pps_period*10);
     ASSERT pps_stable='1'   REPORT "6) Wrong pps_stable" SEVERITY ERROR;
     ASSERT capture_cnt=1000 REPORT "6) Wrong capture_cnt" SEVERITY ERROR;
     -- 7
-    proc_common_wait_some_cycles(clk, c_pps_period*10);
+    proc_common_wait_some_cycles(st_clk, c_pps_period*10);
     ASSERT pps_stable='0'   REPORT "7) Wrong pps_stable" SEVERITY ERROR;
     ASSERT capture_cnt=1001 REPORT "7) Wrong capture_cnt" SEVERITY ERROR;
     -- 8
-    proc_common_wait_some_cycles(clk, c_pps_period*10);
+    proc_common_wait_some_cycles(st_clk, c_pps_period*10);
     ASSERT pps_stable='0'   REPORT "8) Wrong pps_stable" SEVERITY ERROR;
     ASSERT capture_cnt=1000 REPORT "8) Wrong capture_cnt" SEVERITY ERROR;
     -- 9
-    proc_common_wait_some_cycles(clk, c_pps_period*10);
+    proc_common_wait_some_cycles(st_clk, c_pps_period*10);
     ASSERT pps_stable='1'   REPORT "9) Wrong pps_stable" SEVERITY ERROR;
     ASSERT capture_cnt=1000 REPORT "9) Wrong capture_cnt" SEVERITY ERROR;
     -- 10
-    proc_common_wait_some_cycles(clk, c_pps_period/10);
+    proc_common_wait_some_cycles(st_clk, c_pps_period/10);
     ASSERT offset_cnt=last_offset_cnt REPORT "10) Wrong offset_cnt" SEVERITY ERROR;
     -- 11
-    proc_common_wait_some_cycles(clk, c_pps_period/10);
+    proc_common_wait_some_cycles(st_clk, c_pps_period/10);
     ASSERT offset_cnt=last_offset_cnt REPORT "11) Wrong offset_cnt" SEVERITY ERROR;
     WAIT;
   END PROCESS;
@@ -187,14 +195,14 @@ BEGIN
 
   dut : ENTITY work.mms_ppsh
   GENERIC MAP (
-    g_st_clk_freq    => c_clk_freq
+    g_st_clk_freq    => c_st_clk_freq
   )
   PORT MAP (
     -- Clocks and reset
-    mm_rst           => rst,
-    mm_clk           => clk,
-    st_rst           => rst,
-    st_clk           => clk,
+    mm_rst           => mm_rst,
+    mm_clk           => mm_clk,
+    st_rst           => st_rst,
+    st_clk           => st_clk,
     pps_ext          => pps_ext,
 
     -- Memory-mapped clock domain
diff --git a/libraries/io/ppsh/tb/vhdl/tb_ppsh.vhd b/libraries/io/ppsh/tb/vhdl/tb_ppsh.vhd
index 4887a8489d1df8bb0245cf12ddb2f6c75c31dbca..2c1e4a9e49f9dc1b8120f4fa3cf1eaa0fddb9cba 100644
--- a/libraries/io/ppsh/tb/vhdl/tb_ppsh.vhd
+++ b/libraries/io/ppsh/tb/vhdl/tb_ppsh.vhd
@@ -33,6 +33,7 @@ ARCHITECTURE tb OF tb_ppsh IS
   CONSTANT c_clk_period   : TIME    := 1000000 us / c_clk_freq;
   CONSTANT c_pps_default_period   : NATURAL := c_clk_freq;            -- 1 s takes c_clk_freq clk cycles
   CONSTANT c_pps_skew     : TIME    := 7*c_clk_period/10;
+  CONSTANT c_cnt_w        : NATURAL := ceil_log2(c_clk_freq);
 
   -- The state name tells what kind of test is being done
   TYPE t_state_enum IS (
@@ -54,11 +55,15 @@ ARCHITECTURE tb OF tb_ppsh IS
   SIGNAL pps_ext          : STD_LOGIC;
   SIGNAL pps_sys          : STD_LOGIC;
   SIGNAL pps_toggle       : STD_LOGIC;
+  SIGNAL pps_stable       : STD_LOGIC;
+  SIGNAL pps_stable_ack   : STD_LOGIC := '0';
   SIGNAL capture_edge     : STD_LOGIC;
-  SIGNAL capture_cnt      : STD_LOGIC_VECTOR(ceil_log2(c_clk_freq)-1 DOWNTO 0);
-  SIGNAL offset_cnt       : STD_LOGIC_VECTOR(ceil_log2(c_clk_freq)-1 DOWNTO 0);
+  SIGNAL capture_cnt      : STD_LOGIC_VECTOR(c_cnt_w-1 DOWNTO 0);
+  SIGNAL offset_cnt       : STD_LOGIC_VECTOR(c_cnt_w-1 DOWNTO 0);
+  SIGNAL expected_cnt     : STD_LOGIC_VECTOR(c_cnt_w-1 DOWNTO 0);
 
   -- Verify
+  SIGNAL verify_s         : REAL := 0.0;  -- provides time line marker for p_verify in Wave Window
 
 BEGIN
 
@@ -73,13 +78,44 @@ BEGIN
 
   -- Verify that using the falling capture edge indeed does change timing by
   -- using a c_pps_skew that is > 0.5 c_clk_period and < c_clk_period
-  capture_edge <= '0', '1' AFTER 5000 ms, '0' AFTER 7000 ms;
+  p_capture_edge : PROCESS
+  BEGIN
+    capture_edge <= '0';
+    WAIT FOR 5000 ms;
+    capture_edge <= '1';  -- will be verified by p_verify
+    WAIT FOR 2000 ms;
+    capture_edge <= '0';
+    WAIT;
+  END PROCESS;
+
+  p_verify_pps_stable : PROCESS
+  BEGIN
+    pps_stable_ack <= '0';
+    WAIT FOR 9000 ms;  -- wait until p_capture_edge is done
+    IF pps_stable /= '0' THEN
+      REPORT "PPSH : Unexpected pps_stable, should be 0." SEVERITY ERROR;
+    END IF;
+    -- ack PPS stable monitor
+    pps_stable_ack <= '1';
+    WAIT FOR 1*c_clk_period;
+    pps_stable_ack <= '0';
+    WAIT FOR 10 ms;
+    IF pps_stable /= '1' THEN
+      REPORT "PPSH : Unexpected pps_stable, should be 1." SEVERITY ERROR;
+    END IF;
+    WAIT FOR 13000 ms;  -- wait until first loop in p_pps_default_period is done
+    IF pps_stable /= '0' THEN
+      REPORT "PPSH : Unexpected pps_stable, should have become 0." SEVERITY ERROR;
+    END IF;
+    WAIT;
+  END PROCESS;
 
   -- Verify the capture_cnt
   p_pps_default_period : PROCESS
   BEGIN
     tb_state <= s_idle;
     pps <= '0';
+    expected_cnt <= TO_UVEC(c_pps_default_period, c_cnt_w);
     WAIT UNTIL rst='0';
     WAIT FOR 10*c_clk_period;
     WAIT UNTIL rising_edge(clk);  -- get synchronous to clk
@@ -130,8 +166,6 @@ BEGIN
       pps <= '0';
       WAIT FOR (c_pps_default_period-I)*c_clk_period;
     END LOOP;
-    -- Missing PPS pulses
-    tb_state <= s_missing_pps;
 
     -- End
     tb_state <= s_end;
@@ -158,11 +192,14 @@ BEGIN
     -- PPS
     pps_ext       => pps_ext,
     pps_sys       => pps_sys,
-    pps_toggle    => pps_toggle,
     -- MM control
-    capture_edge  => capture_edge,
-    capture_cnt   => capture_cnt,
-    offset_cnt    => offset_cnt
+    pps_toggle     => pps_toggle,
+    pps_stable     => pps_stable,
+    pps_stable_ack => pps_stable_ack,
+    capture_edge   => capture_edge,
+    capture_cnt    => capture_cnt,
+    offset_cnt     => offset_cnt,
+    expected_cnt   => expected_cnt
   );
 
   -----------------------------------------------------------------------------
@@ -187,18 +224,21 @@ BEGIN
         IF UNSIGNED(capture_cnt)/=c_clk_freq+1 THEN
           REPORT "PPSH : Unexpected capture count value at 6 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 6.0;
       END IF;
 
       IF (NOW > 7000 ms) AND (NOW <= 7000 ms + c_clk_period) THEN
         IF UNSIGNED(capture_cnt)/=c_clk_freq THEN
           REPORT "PPSH : Unexpected capture count value at 7 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 7.0;
       END IF;
 
       IF (NOW > 8000 ms) AND (NOW <= 8000 ms + c_clk_period) THEN
         IF UNSIGNED(capture_cnt)/=c_clk_freq-1 THEN
           REPORT "PPSH : Unexpected capture count value at 8 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 8.0;
       END IF;
 
       -- Verify external PPS period fluctuations at specific stimuli moments
@@ -206,57 +246,65 @@ BEGIN
         IF UNSIGNED(capture_cnt)/=c_clk_freq THEN
           REPORT "PPSH : Unexpected capture count value at 10 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 10.0;
       END IF;
 
       IF (NOW > 22000 ms) AND (NOW <= 22000 ms + c_clk_period) THEN
         IF UNSIGNED(capture_cnt)/=c_clk_freq-1 THEN
           REPORT "PPSH : Unexpected capture count value at 22 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 22.0;
       END IF;
 
       IF (NOW > 25000 ms) AND (NOW <= 25000 ms + c_clk_period) THEN
         IF UNSIGNED(capture_cnt)/=c_clk_freq THEN
           REPORT "PPSH : Unexpected capture count value at 25 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 25.0;
       END IF;
 
       IF (NOW > 28000 ms) AND (NOW <= 28000 ms + c_clk_period) THEN
         IF UNSIGNED(capture_cnt)/=c_clk_freq+1 THEN
           REPORT "PPSH : Unexpected capture count value at 28 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 28.0;
       END IF;
 
       IF (NOW > 30000 ms) AND (NOW <= 30000 ms + c_clk_period) THEN
         IF UNSIGNED(capture_cnt)/=c_clk_freq THEN
           REPORT "PPSH : Unexpected capture count value at 30 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 30.0;
       END IF;
 
       IF (NOW > 35000 ms) AND (NOW <= 35000 ms + c_clk_period) THEN
         IF UNSIGNED(capture_cnt)/=2**capture_cnt'LENGTH-1 THEN
           REPORT "PPSH : Unexpected capture count value at 35 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 35.0;
       END IF;
 
       IF (NOW > 49000 ms) AND (NOW <= 49000 ms + c_clk_period) THEN
         IF UNSIGNED(capture_cnt)/=2**capture_cnt'LENGTH-1 THEN
           REPORT "PPSH : Unexpected capture count value at 49 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 49.0;
       END IF;
 
       -- check if offset_cnt is counting
       IF (NOW > 7500 ms) AND (NOW <= 7500 ms + c_clk_period) THEN
         IF UNSIGNED(offset_cnt)/=475 THEN
-          REPORT "PPSH : Unexpected offset count value at 5.5 s." SEVERITY ERROR;
+          REPORT "PPSH : Unexpected offset count value at 7.5 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 7.5;
       END IF;
 
       IF (NOW > 7700 ms) AND (NOW <= 7700 ms + c_clk_period) THEN
         IF UNSIGNED(offset_cnt)/=675 THEN
-          REPORT "PPSH : Unexpected offset count value at 5.5 s." SEVERITY ERROR;
+          REPORT "PPSH : Unexpected offset count value at 7.7 s." SEVERITY ERROR;
         END IF;
+        verify_s <= 7.7;
       END IF;
-
     END IF;
   END PROCESS;