diff --git a/applications/lofar2/designs/lofar2_unb2b_adc/lofar2_unb2b_adc.fpga.yaml b/applications/lofar2/designs/lofar2_unb2b_adc/lofar2_unb2b_adc.fpga.yaml
index 96164e10b8f2196d96a764d4cefa044a3788d58b..d80778d4147dd8afeef1fa309fd9eb4d0348cbaf 100644
--- a/applications/lofar2/designs/lofar2_unb2b_adc/lofar2_unb2b_adc.fpga.yaml
+++ b/applications/lofar2/designs/lofar2_unb2b_adc/lofar2_unb2b_adc.fpga.yaml
@@ -8,7 +8,7 @@ fpga_description: "FPGA design lofar2_unb2b_adc"
 
 peripherals:
   #############################################################################
-  # Factory
+  # Factory / minimal (from ctrl_unb2b_board.vhd)
   #############################################################################
   - peripheral_name: unb2b_board/system_info
     slave_port_names:
@@ -58,7 +58,7 @@ peripherals:
       - REG_REMU
  
   #############################################################################
-  # Application
+  # AIT = ADC Input and Timing (from node_adc_input_and_timing.vhd)
   #############################################################################
   
   - peripheral_name: tech_jesd204b/jesd_ctrl
diff --git a/applications/lofar2/designs/lofar2_unb2b_beamformer/lofar2_unb2b_beamformer.fpga.yaml b/applications/lofar2/designs/lofar2_unb2b_beamformer/lofar2_unb2b_beamformer.fpga.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..de9540b6f918488b48dd31f3dc9fe227ddcbec0e
--- /dev/null
+++ b/applications/lofar2/designs/lofar2_unb2b_beamformer/lofar2_unb2b_beamformer.fpga.yaml
@@ -0,0 +1,277 @@
+schema_name: args
+schema_version: 1.0
+schema_type: fpga
+
+hdl_library_name: lofar2_unb2b_beamformer
+fpga_name: lofar2_unb2b_beamformer
+fpga_description: "FPGA design lofar2_unb2b_beamformer"
+parameters:
+  - { name: c_N_pol_bf,             value: 2 }  # NOTE: define c_N_pol_bf before c_N_pol, to avoid that c_N_pol_bf gets substituted by 2_bf
+  - { name: c_N_pol,                value: 2 }
+  - { name: c_N_beamsets,           value: 2 }
+  - { name: c_N_sub,                value: 512 }
+  - { name: c_N_fft,                value: 1024 }
+  - { name: c_S_pn,                 value: 12 }
+  - { name: c_Q_fft,                value: 2 }
+  - { name: c_N_taps,               value: 16 }
+  - { name: c_W_adc_jesd,           value: 16 }
+  - { name: c_W_adc,                value: 14 }
+  - { name: c_V_sample_delay,       value: 4096 }
+  - { name: c_V_si_db_large,        value: 131072 }
+  - { name: c_V_si_db,              value: 1024 }
+  - { name: c_W_fir_coef,           value: 16 }
+  - { name: c_W_subband,            value: 18 }
+  - { name: c_P_pfb,                value: c_S_pn / c_Q_fft }  # = 6
+  - { name: c_A_pn,                 value: c_S_pn / c_N_pol }  # = 6
+  - { name: c_S_sub_bf,             value: 488 }
+  - { name: c_f_adc_MHz,            value: 200 }
+  - { name: c_W_sub_weight,         value: 16 }
+  - { name: c_W_bf_weight,          value: 16 }
+  - { name: c_W_beamlet_scale,      value: 16 }
+  - { name: c_W_beamlet_resolution, value: 0 - 15 }  # EK: FIXME support passing on negative values, workaround use 0 - positive
+  - { name: c_W_beamlet,            value: 8 }
+  - { name: c_nof_clk_per_pps,      value: c_f_adc_MHz * 10**6 }  # = 200000000
+  - { name: c_nof_block_per_sync,   value: 195313 }  # TBD temporarily use 390625 = 2 * 195312, to have integer number of blocks in 2 s sync interval, TODO: remove when REG_BSN_SOURCE_V2 is used
+
+peripherals:
+  #############################################################################
+  # Factory / minimal (see ctrl_unb2b_board.vhd)
+  #############################################################################
+  - peripheral_name: unb2b_board/system_info
+    slave_port_names:
+      - ROM_SYSTEM_INFO
+      - PIO_SYSTEM_INFO
+    lock_base_address: 0x10000
+
+  - peripheral_name: unb2b_board/wdi
+    slave_port_names:
+      - PIO_WDI
+
+  - peripheral_name: unb2b_board/unb2_fpga_sens
+    slave_port_names:
+      - REG_FPGA_TEMP_SENS
+      - REG_FPGA_VOLTAGE_SENS
+    
+  - peripheral_name: unb2b_board/ram_scrap
+    slave_port_names:
+      - RAM_SCRAP
+      
+  - peripheral_name: eth/eth
+    slave_port_names:
+      - AVS_ETH_0_TSE
+      - AVS_ETH_0_REG
+      - AVS_ETH_0_RAM
+      
+  - peripheral_name: ppsh/ppsh
+    slave_port_names:
+      - PIO_PPS
+      
+  - peripheral_name: epcs/epcs
+    slave_port_names:
+      - REG_EPCS
+      
+  - peripheral_name: dp/dpmm
+    slave_port_names:
+      - REG_DPMM_CTRL
+      - REG_DPMM_DATA
+      
+  - peripheral_name: dp/mmdp
+    slave_port_names:
+      - REG_MMDP_CTRL
+      - REG_MMDP_DATA
+      
+  - peripheral_name: remu/remu
+    slave_port_names:
+      - REG_REMU
+ 
+  #############################################################################
+  # AIT = ADC Input and Timing (see node_adc_input_and_timing.vhd)
+  #############################################################################
+  
+  - peripheral_name: tech_jesd204b/jesd_ctrl
+    slave_port_names:
+      - PIO_JESD_CTRL
+      
+  - peripheral_name: tech_jesd204b/jesd204b_arria10
+    slave_port_names:
+      - JESD204B
+  
+  - peripheral_name: dp/dp_shiftram
+    parameter_overrides:
+      - { name: g_nof_streams, value: c_S_pn }
+      - { name: g_nof_words, value: c_V_sample_delay }
+      - { name: g_data_w, value: c_W_adc_jesd }
+    slave_port_names:
+      - REG_DP_SHIFTRAM
+
+  - peripheral_name: dp/dp_bsn_source
+    parameter_overrides:
+      - { name: g_nof_block_per_sync, value: c_nof_block_per_sync }
+    slave_port_names:
+      - REG_BSN_SOURCE
+      
+  # TODO: Use REG_BSN_SOURCE_V2 instead of REG_BSN_SOURCE
+  #peripheral_name: dp/dp_bsn_source_v2
+  #parameter_overrides:
+  #  - { name: g_nof_clk_per_sync, value: c_nof_clk_per_pps }
+  #  - { name: g_block_size, value: c_N_fft }
+  #  - { name: g_bsn_time_offset_w, value: ceil_log2(c_N_fft) }
+  #slave_port_names:
+  #  - REG_BSN_SOURCE_V2
+      
+  - peripheral_name: dp/dp_bsn_scheduler
+    slave_port_names:
+      - REG_BSN_SCHEDULER
+  
+  - peripheral_name: dp/dp_bsn_monitor
+    peripheral_group: input
+    slave_port_names:
+      - REG_BSN_MONITOR_INPUT
+  
+  - peripheral_name: diag/diag_wg_wideband
+    parameter_overrides:
+      - { name: g_nof_streams, value: c_S_pn }
+    slave_port_names:
+      - REG_DIAG_WG
+      - RAM_DIAG_WG
+      
+  - peripheral_name: aduh/aduh_mon_dc_power
+    parameter_overrides:
+      - { name: g_nof_streams, value: c_S_pn }
+    slave_port_names:
+      - REG_ADUH_MON
+
+  # Commented RAM_ADUH_MON, because use RAM_DIAG_DATA_BUF_BSN instead
+  #- peripheral_name: aduh/aduh_mon_data_buffer
+  #  parameter_overrides:
+  #    - { name: g_nof_streams, value: c_S_pn }
+  #    - { name: g_symbol_w, value: c_W_adc_jesd }
+  #    - { name: g_nof_symbols_per_data, value: 1 }
+  #    - { name: g_buffer_nof_symbols, value: 512 }
+  #    - { name: g_buffer_use_sync, value: True }
+  #  slave_port_names:
+  #    - RAM_ADUH_MON
+
+  - peripheral_name: diag/diag_data_buffer
+    peripheral_group: bsn
+    parameter_overrides:
+      - { name: g_nof_streams, value: c_S_pn }
+      - { name: g_data_w, value: c_W_adc_jesd }
+      - { name: g_nof_data, value: c_V_si_db }
+    slave_port_names:
+      - REG_DIAG_DATA_BUF_BSN
+      - RAM_DIAG_DATA_BUF_BSN
+  
+  #############################################################################
+  # Fsub = Subband Filterbank (from node_sdp_filterbank.vhd)
+  #############################################################################
+  
+  - peripheral_name: si/si
+    slave_port_names:
+      - REG_SI
+      
+  - peripheral_name: filter/fil_ppf_w
+    parameter_overrides:
+      - { name: g_nof_taps, value: c_N_taps }
+      - { name: g_nof_bands, value: c_N_fft }
+      - { name: g_coef_dat_w, value: c_W_fir_coef }
+    slave_port_names:
+      - RAM_FIL_COEFS
+      
+  - peripheral_name: sdp/sdp_subband_equalizer
+    slave_port_names:
+      - RAM_EQUALIZER_GAINS
+      
+  - peripheral_name: dp/dp_selector
+    slave_port_names:
+      - REG_DP_SELECTOR   # input_select = 0 for weighted subbands, input_select = 1 for raw subbands
+      
+  - peripheral_name: st/st_sst_for_sdp
+    slave_port_names:
+      - RAM_ST_SST
+      
+  - peripheral_name: common/common_variable_delay
+    peripheral_group: sst
+    slave_port_names:
+      - REG_STAT_ENABLE
+
+  - peripheral_name: sdp/sdp_statistics_offload_hdr_dat_sst
+    peripheral_group: sst
+    slave_port_names:
+      - REG_STAT_HDR_INFO
+
+  #############################################################################
+  # BF = Beamformer (from node_sdp_beamformer.vhd)
+  #############################################################################
+  
+  - peripheral_name: sdp/sdp_info
+    slave_port_names:
+      - REG_SDP_INFO
+      
+  - peripheral_name: reorder/reorder_col_wide
+    number_of_peripherals: c_N_beamsets  # lofar2_unb2b_beamformer.vhd
+    parameter_overrides:
+      - { name: g_wb_factor, value: c_P_pfb }
+      - { name: g_nof_ch_in, value: c_N_sub * c_Q_fft }
+      - { name: g_nof_ch_sel, value: c_S_sub_bf * c_Q_fft }
+    slave_port_names:
+      - RAM_SS_SS_WIDE
+
+  - peripheral_name: sdp/sdp_bf_weights
+    number_of_peripherals: c_N_beamsets  # lofar2_unb2b_beamformer.vhd
+    parameter_overrides:
+      - { name: g_nof_instances, value: c_N_pol_bf * c_A_pn }  # A_pn = P_pfb = 6
+      - { name: g_nof_gains, value: c_N_pol * c_S_sub_bf }  # N_pol = Q_fft = 2
+    slave_port_names:
+      - RAM_BF_WEIGHTS
+
+  - peripheral_name: sdp/sdp_bf_scale
+    number_of_peripherals: c_N_beamsets  # lofar2_unb2b_beamformer.vhd
+    parameter_overrides:
+      - { name: g_gain_w, value: c_W_beamlet_scale }
+      - { name: g_lsb_w, value: 0 - c_W_beamlet_resolution}
+    slave_port_names:
+      - REG_BF_SCALE
+
+  - peripheral_name: sdp/sdp_beamformer_output_hdr_dat
+    number_of_peripherals: c_N_beamsets  # lofar2_unb2b_beamformer.vhd
+    slave_port_names:
+      - REG_HDR_DAT
+
+  - peripheral_name: dp/dp_xonoff
+    number_of_peripherals: c_N_beamsets  # lofar2_unb2b_beamformer.vhd
+    parameter_overrides:
+      - { name: g_nof_streams, value: 1 }
+      - { name: g_combine_streams, value: False }
+    slave_port_names:
+      - REG_DP_XONOFF
+
+  - peripheral_name: st/st_bst_for_sdp
+    slave_port_names:
+      - RAM_ST_BST
+
+  - peripheral_name: common/common_variable_delay
+    peripheral_group: bst
+    slave_port_names:
+      - REG_STAT_ENABLE_BST
+
+  - peripheral_name: sdp/sdp_statistics_offload_hdr_dat_bst
+    peripheral_group: bst
+    slave_port_names:
+      - REG_STAT_HDR_INFO_BST
+
+  - peripheral_name: nw_10GbE/nw_10GbE_unb2legacy
+    peripheral_group: beamlet_output
+    parameter_overrides:
+      - { name: g_nof_macs, value: 1 }
+    slave_port_names:
+      - REG_NW_10GBE_MAC
+
+  - peripheral_name: nw_10GbE/nw_10GbE_eth10g
+    peripheral_group: beamlet_output
+    parameter_overrides:
+      - { name: g_nof_macs, value: 1 }
+    slave_port_names:
+      - REG_NW_10GBE_ETH10G
+
+
diff --git a/applications/lofar2/designs/lofar2_unb2b_filterbank/lofar2_unb2b_filterbank.fpga.yaml b/applications/lofar2/designs/lofar2_unb2b_filterbank/lofar2_unb2b_filterbank.fpga.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e67ea2505228fe54f7bb96bad02b7c7ce9f4f7fe
--- /dev/null
+++ b/applications/lofar2/designs/lofar2_unb2b_filterbank/lofar2_unb2b_filterbank.fpga.yaml
@@ -0,0 +1,173 @@
+schema_name   : args
+schema_version: 1.0
+schema_type   : fpga
+
+hdl_library_name: lofar2_unb2b_filterbank
+fpga_name       : lofar2_unb2b_filterbank
+fpga_description: "FPGA design lofar2_unb2b_filterbank"
+
+peripherals:
+  #############################################################################
+  # Factory / minimal (see ctrl_unb2b_board.vhd)
+  #############################################################################
+  - peripheral_name: unb2b_board/system_info
+    slave_port_names:
+      - ROM_SYSTEM_INFO
+      - PIO_SYSTEM_INFO
+    lock_base_address: 0x10000
+
+  - peripheral_name: unb2b_board/wdi
+    slave_port_names:
+      - PIO_WDI
+
+  - peripheral_name: unb2b_board/unb2_fpga_sens
+    slave_port_names:
+      - REG_FPGA_TEMP_SENS
+      - REG_FPGA_VOLTAGE_SENS
+    
+  - peripheral_name: unb2b_board/ram_scrap
+    slave_port_names:
+      - RAM_SCRAP
+      
+  - peripheral_name: eth/eth
+    slave_port_names:
+      - AVS_ETH_0_TSE
+      - AVS_ETH_0_REG
+      - AVS_ETH_0_RAM
+      
+  - peripheral_name: ppsh/ppsh
+    slave_port_names:
+      - PIO_PPS
+      
+  - peripheral_name: epcs/epcs
+    slave_port_names:
+      - REG_EPCS
+      
+  - peripheral_name: dp/dpmm
+    slave_port_names:
+      - REG_DPMM_CTRL
+      - REG_DPMM_DATA
+      
+  - peripheral_name: dp/mmdp
+    slave_port_names:
+      - REG_MMDP_CTRL
+      - REG_MMDP_DATA
+      
+  - peripheral_name: remu/remu
+    slave_port_names:
+      - REG_REMU
+ 
+  #############################################################################
+  # AIT = ADC Input and Timing (see node_adc_input_and_timing.vhd)
+  #############################################################################
+  
+  - peripheral_name: tech_jesd204b/jesd_ctrl
+    slave_port_names:
+      - PIO_JESD_CTRL
+      
+  - peripheral_name: tech_jesd204b/jesd204b_arria10
+    slave_port_names:
+      - JESD204B
+  
+  - peripheral_name: dp/dp_shiftram
+    parameter_overrides:
+      - { name: g_nof_streams, value: 12 }  # = S_pn
+      - { name: g_nof_words, value: 4096 }
+      - { name: g_data_w, value: 16 }
+    slave_port_names:
+      - REG_DP_SHIFTRAM
+
+  - peripheral_name: dp/dp_bsn_source
+    parameter_overrides:
+      - { name: g_nof_block_per_sync, value: 195313 }  # 390625 = 2 * 195312, to have integer number of blocks in 2 s sync interval
+    slave_port_names:
+      - REG_BSN_SOURCE
+      
+  # TODO: Use REG_BSN_SOURCE_V2 instead of REG_BSN_SOURCE
+  #peripheral_name: dp/dp_bsn_source_v2
+  #parameter_overrides:
+  #  - { name: g_nof_clk_per_sync, value: 200000000 }  # = f_adc
+  #  - { name: g_block_size, value: 1024 }       # = N_fft
+  #  - { name: g_bsn_time_offset_w, value: 10 }  # note: g_bsn_time_offset_w = ceil_log2(g_block_size)
+  #slave_port_names:
+  #  - REG_BSN_SOURCE_V2
+      
+  - peripheral_name: dp/dp_bsn_scheduler
+    slave_port_names:
+      - REG_BSN_SCHEDULER
+  
+  - peripheral_name: dp/dp_bsn_monitor
+    peripheral_group: input
+    slave_port_names:
+      - REG_BSN_MONITOR_INPUT
+  
+  - peripheral_name: diag/diag_wg_wideband
+    parameter_overrides:
+      - { name: g_nof_streams, value: 12 }  # = S_pn
+    slave_port_names:
+      - REG_DIAG_WG
+      - RAM_DIAG_WG
+      
+  - peripheral_name: aduh/aduh_mon_dc_power
+    parameter_overrides:
+      - { name: g_nof_streams, value: 12 }  # = S_pn
+    slave_port_names:
+      - REG_ADUH_MON
+
+  # Commented RAM_ADUH_MON, because use RAM_DIAG_DATA_BUF_BSN instead
+  #- peripheral_name: aduh/aduh_mon_data_buffer
+  #  parameter_overrides:
+  #    - { name: g_nof_streams, value: 12 }  # = S_pn
+  #    - { name: g_symbol_w, value: 16 }
+  #    - { name: g_nof_symbols_per_data, value: 1 }
+  #    - { name: g_buffer_nof_symbols, value: 512 }
+  #    - { name: g_buffer_use_sync, value: true }
+  #  slave_port_names:
+  #    - RAM_ADUH_MON
+
+  - peripheral_name: diag/diag_data_buffer
+    peripheral_group: bsn
+    parameter_overrides:
+      - { name: g_nof_streams, value: 12 }  # = S_pn
+      - { name: g_data_w, value: 16 }
+      - { name: g_nof_data, value: 1024 }
+    slave_port_names:
+      - REG_DIAG_DATA_BUF_BSN
+      - RAM_DIAG_DATA_BUF_BSN
+  
+  #############################################################################
+  # Fsub = Subband Filterbank (from node_sdp_filterbank.vhd)
+  #############################################################################
+  
+  - peripheral_name: si/si
+    slave_port_names:
+      - REG_SI
+      
+  - peripheral_name: filter/fil_ppf_w
+    parameter_overrides:
+      - { name: g_wb_factor, value: 1 }
+      - { name: g_nof_taps, value: 16 }  # = N_taps
+      - { name: g_nof_bands, value: 1024 }  # = N_fft
+      - { name: g_coef_dat_w, value: 16 }  # = W_fir_coef
+    slave_port_names:
+      - RAM_FIL_COEFS
+      
+  - peripheral_name: sdp/sdp_subband_equalizer
+    slave_port_names:
+      - RAM_EQUALIZER_GAINS
+      
+  - peripheral_name: dp/dp_selector
+    slave_port_names:
+      - REG_DP_SELECTOR   # input_select = 0 for weighted subbands, input_select = 1 for raw subbands
+      
+  - peripheral_name: st/st_sst_for_sdp
+    slave_port_names:
+      - RAM_ST_SST
+      
+  - peripheral_name: common/common_variable_delay
+    slave_port_names:
+      - REG_STAT_ENABLE
+
+  - peripheral_name: sdp/sdp_statistics_offload_hdr_dat_sst
+    slave_port_names:
+      - REG_STAT_HDR_INFO
diff --git a/applications/lofar2/libraries/sdp/sdp.peripheral.yaml b/applications/lofar2/libraries/sdp/sdp.peripheral.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..af6d7597820a47f309ad1172cd801911690575cd
--- /dev/null
+++ b/applications/lofar2/libraries/sdp/sdp.peripheral.yaml
@@ -0,0 +1,435 @@
+schema_name: args
+schema_version: 1.0
+schema_type: peripheral
+
+hdl_library_name: sdp
+hdl_library_description: "Station Digital Processor (SDP) for LOFAR2.0"
+
+peripherals:
+  - peripheral_name: sdp_info    # pi_sdp_info.py ?
+    peripheral_description: "SDP info."
+    slave_ports:
+      # MM port for sdp_info.vhd
+      - slave_name: REG_SDP_INFO
+        slave_description: |
+          "The SDP info contains central SDP information. The station_id applies to the entire station.
+           The other info fields apply per antenna band (low band or high band). An FPGA node only
+           participates in one band."
+        slave_type: REG
+        fields:
+          - - { field_name: station_id,              width: 16, access_mode: RW, address_offset: 0x0 }
+          - - { field_name: antenna_band_index,      width:  1, access_mode: RO, address_offset: 0x4 }
+          - - { field_name: observation_id,          width: 32, access_mode: RW, address_offset: 0x8 }
+          - - { field_name: nyquist_zone_index,      width:  2, access_mode: RW, address_offset: 0xC }
+          - - { field_name: f_adc,                   width:  1, access_mode: RO, address_offset: 0x10 }
+          - - { field_name: fsub_type,               width:  1, access_mode: RO, address_offset: 0x14 }
+          - - { field_name: beam_repositioning_flag, width:  1, access_mode: RW, address_offset: 0x18 }
+          - - { field_name: subband_calibrated_flag, width:  1, access_mode: RW, address_offset: 0x1C }
+          - - { field_name: O_si,                    width:  8, access_mode: RW, address_offset: 0x20 }
+          - - { field_name: N_si,                    width:  8, access_mode: RW, address_offset: 0x24 }
+          - - { field_name: O_rn,                    width:  8, access_mode: RW, address_offset: 0x28 }
+          - - { field_name: N_rn,                    width:  8, access_mode: RW, address_offset: 0x2C }
+          - - { field_name: block_period,            width: 16, access_mode: RO, address_offset: 0x30 }
+          - - { field_name: beamlet_scale,           width: 16, access_mode: RW, address_offset: 0x34 }
+
+
+  - peripheral_name: sdp_subband_equalizer    # pi_sdp_subband_equalizer.py
+    peripheral_description: "SDP Subband equalizer coefficients."
+    parameters:
+      # Parameters of pi_sdp_subband_equalizer.py, fixed in sdp_subband_equalizer.vhd / sdp_pkg.vhd
+      - { name: g_nof_instances, value: 6 }  # P_pfb = S_pn / Q_fft = 12 / 2 = 6
+    slave_ports:
+      # MM port for sdp_subband_equalizer.vhd
+      - slave_name: RAM_EQUALIZER_GAINS
+        slave_description: |
+          "The subband weigths are stored in g_nof_instances = P_pfb = S_pn / Q_fft = 6 blocks of
+           Q_fft * N_sub = 2 * 512 = 1024 complex coefficients as:
+
+           (cint16)subband_weights[S_pn/Q_fft]_[Q_fft][N_sub]
+
+           where S_pn = 12, Q_fft = 2 and N_sub = 512 are defined in sdp_pkg.vhd."
+        slave_type: RAM
+        number_of_slaves: g_nof_instances
+        fields:
+          - - field_name: coef
+              field_description: |
+                "Complex coefficient to calibrate the gain and phase per subband. Packed as imaginary in high part,
+                 real in low part of width = N_complex * W_sub_weight = 2 * 16 = 32 bit."
+              width: 32  # = N_complex * W_sub_weight
+              address_offset: 0x0
+              number_of_fields: 1024  # = Q_fft * N_sub = 2 signal inputs * 512 subbands
+              radix: complx
+
+
+  - peripheral_name: sdp_bf_weights    # pi_sdp_bf_weights.py
+    peripheral_description: "SDP Beamformer weights (= beamlet weights)."
+    parameters:
+      # Parameters of pi_sdp_bf_weights.py, fixed in sdp_bf_weights.vhd / sdp_pkg.vhd
+      - { name: g_nof_instances, value: 12 }  # = N_pol_bf * P_pfb
+      - { name: g_nof_gains, value: 976 }  # = Q_fft * S_sub_bf
+    slave_ports:
+      # MM port for sdp_beamformer_local.vhd / sdp_bf_weights.vhd / mms_dp_gain_serial_arr.vhd
+      - slave_name: RAM_BF_WEIGHTS
+        slave_description: |
+          "The beamlet weigths are stored in g_nof_instances = N_pol_bf * P_pfb = 2 * 6 = 12, where
+           P_pfb = S_pn / Q_fft = 6. Per instance there is a block of Q_fft * S_sub_bf =
+           2 * 488 = 976 complex BF weights. The N_pol_bf = 2 represents the two beamformer
+           polarizations, to distinguish these from the N_pol = 2 antenna polarizations. The
+           beamlet weigths for S_pn = P_pfb * Q_fft = 12 signal inputs are therefore defined by:
+
+           (cint16)bf_weights[N_pol_bf][P_pfb]_[Q_fft][S_sub_bf]
+
+           where N_pol_bf = 2, P_pfb = 6 and Q_fft = 2 and S_sub_bf = 488, defined in sdp_pkg.vhd.
+
+           The pairs of Q_fft signal inputs that are multiplexed per block are mapped to the N_pol = 2
+           polarizations of an antenna. Therefore A_pn = P_pfb = 6 is the number dual polarization
+           antennas per peripheral. The  beamlet weigths for S_pn = A_pn * N_pol = 12 signal inputs
+           are therefore defined by:
+
+           (cint16)bf_weights[N_pol_bf][A_pn]_[N_pol][S_sub_bf]
+
+           where N_pol_bf = 2, A_pn = 6 and N_pol = 2 and S_sub_bf = 488, defined in sdp_pkg.vhd.
+
+           The BF weights can implement the full 2x2 Jones matrix for weighting and adding the
+           signal input polarizations [x, y] per dual polarization antenna. The polarization index
+           mapping is index 0 = X and index 1 = Y. The co-polarization BF weights (XX, YY) are set
+           when index of N_pol_bf and index of N_pol are the same. The cross-polarization BF
+           weights (XY, YX) are set when index of N_pol_bf and index of N_pol are different. If
+           no cross-polarization weighting is needed, then these weights can be kept 0."
+        slave_type: RAM
+        number_of_slaves: g_nof_instances
+        fields:
+          - - field_name: coef
+              field_description: |
+                "Complex weight per subband. Packed as imaginary in high part, real in low part
+                 of width = N_complex * W_bf_weight = 2 * 16 = 32 bit."
+              width: 32  # = N_complex * W_bf_weight
+              address_offset: 0x0
+              number_of_fields: g_nof_gains
+              radix: complx
+
+
+  - peripheral_name: sdp_bf_scale    # pi_sdp_bf_scale.py
+    peripheral_description: "SDP BF beamlet data output scaling and requantization."
+    parameters:
+      # Parameters fixed in node_sdp_beamformer.vhd / mms_dp_scale.vhd / sdp_pkg.vhd
+      - { name: g_gain_w, value: 16 }
+      - { name: g_lsb_w, value: 15 }
+    slave_ports:
+      # MM port for node_sdp_beamformer.vhd / mms_dp_scale.vhd / mms_dp_gain.vhd / mms_dp_gain_arr.vhd
+      - slave_name: REG_BF_SCALE
+        slave_description: |
+          "The beamlet scale function scales the beamlet sum with a real scale factor and then
+           requantizes the result to beamlet data output with less bits.
+           The beamlet scale factor has g_gain_w bits and the value 2**g_lsb_w represents a gain of 1.
+           For example for g_gain_w = 16, g_lsb_w = 15, a beamlet sum of 18 bits and beamlet data
+           output of 8 bits, a scale value of:
+           . 2**g_lsb_w = 2**15 selects the lowest 8 bits of the beamlet sum and clips the highest
+             10 bits,
+           . 2**11 rounds the lowest 4 bits, selects the next 8 bits of the beamlet sum and clips
+             the highest 6 bits,
+           . 2**5 rounds the lowest 10 bits and selects the highest 8 bits of the beamlet sum."
+        slave_type: REG
+        fields:
+          - - field_name: scale
+              field_description: ""
+              width: g_gain_w
+              address_offset: 0x0
+              number_of_fields: 1
+              radix: unsigned
+              #radix_width: g_gain_w
+              radix_resolution: 0 - g_lsb_w
+          - - field_name: unused
+              field_description: "Not used."
+              address_offset: 0x4
+
+
+  - peripheral_name: sdp_beamformer_output_hdr_dat  #  pi_dp_offload_tx_hdr_dat_lofar2_beamformer_output.py
+    peripheral_description: "SDP BF beamlet data output header."
+    slave_ports:
+      # MM port for sdp_beamformer_output.vhd / dp_offload_tx_v3.vhd
+      - slave_name: REG_DP_OFFLOAD_TX_HDR_DAT
+        slave_description: |
+          "The ETH/IP/UDP/application header fields for the beamlet data output offload UDP packets.
+
+           The header fields are described in ICD STAT-CEP [1].
+
+           https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L1%20Interface%20Control%20Documents/STAT%20to%20CEP%20ICD
+
+           From tb_dp_offload_tx_v3.vhd simulation it follows that:
+           . the header fields are stored in reversed address order due to that the array in VHDL has
+             range (h downto 0) where the first header field (eth_destination_mac) is at index h.
+           . the RO fields are filled in by the logic, when the packet header is transmitted, however
+             the read value does not still represents the MM write value, not the transmitted value.
+           . dp_bsn with radix_width = 64 is stored as:
+              word  byte
+              addr  addr  bits
+                0   0x0 [31:0] = dp_bsn[31:0]
+                1   0x4 [31:0] = dp_bsn[63:32]
+           . eth_dst_mac with radix_width = 48 is stored as:
+              word  byte
+              addr  addr  bits
+               21   0x84 [31:0] = eth_dst_mac[31:0]
+               22   0x88 [15:0] = eth_dst_mac[47:32]
+          "
+        slave_type: REG
+        fields:
+          # eth field group
+          - - { field_name: eth_destination_mac,    width: 32,                 access_mode: RW, address_offset: 0x84, radix_width: 48 }
+          - - { field_name: eth_source_mac,         width: 32,                 access_mode: RO, address_offset: 0x7C, radix_width: 48 }
+          - - { field_name: eth_type,               width: 16,                 access_mode: RO, address_offset: 0x78 }
+          # ip field group
+          - - { field_name: ip_version,             width:  4,                 access_mode: RW, address_offset: 0x74 }
+          - - { field_name: ip_header_length,       width:  4,                 access_mode: RW, address_offset: 0x70 }
+          - - { field_name: ip_services,            width:  8,                 access_mode: RW, address_offset: 0x6C }
+          - - { field_name: ip_total_length,        width: 16,                 access_mode: RW, address_offset: 0x68 }
+          - - { field_name: ip_identification,      width: 16,                 access_mode: RW, address_offset: 0x64 }
+          - - { field_name: ip_flags,               width:  3,                 access_mode: RW, address_offset: 0x60 }
+          - - { field_name: ip_fragment_offset,     width: 13,                 access_mode: RW, address_offset: 0x5C }
+          - - { field_name: ip_time_to_live,        width:  8,                 access_mode: RW, address_offset: 0x58 }
+          - - { field_name: ip_protocol,            width:  8,                 access_mode: RW, address_offset: 0x54 }
+          - - { field_name: ip_header_checksum,     width: 16,                 access_mode: RW, address_offset: 0x50 }
+          - - { field_name: ip_source_address,      width: 32,                 access_mode: RW, address_offset: 0x4C }
+          - - { field_name: ip_destination_address, width: 32,                 access_mode: RW, address_offset: 0x48 }
+          # udp field group
+          - - { field_name: udp_source_port,        width: 16,                 access_mode: RW, address_offset: 0x44 }
+          - - { field_name: udp_destination_port,   width: 16,                 access_mode: RW, address_offset: 0x40 }
+          - - { field_name: udp_length,             width: 16,                 access_mode: RW, address_offset: 0x3C }
+          - - { field_name: udp_checksum,           width: 16,                 access_mode: RW, address_offset: 0x38 }
+          # application field group
+          - - { field_name: marker,                 width:  8,                 access_mode: RO, address_offset: 0x34 }
+          - - { field_name: version_id,             width:  8,                 access_mode: RO, address_offset: 0x30 }
+          - - { field_name: observation_id,         width: 32,                 access_mode: RW, address_offset: 0x2C }
+          - - { field_name: station_id,             width: 16,                 access_mode: RW, address_offset: 0x28 }
+          - - { field_name: source_info,            width: 16,                 access_mode: RW, address_offset: 0x24 }
+          - "source_info":
+            - { field_name: antenna_band_index,     width:  1, bit_offset: 15, access_mode: RW, address_offset: 0x24 }
+            - { field_name: nyquist_zone_index,     width:  2, bit_offset: 13, access_mode: RW, address_offset: 0x24 }
+            - { field_name: f_adc,                  width:  1, bit_offset: 12, access_mode: RW, address_offset: 0x24 }
+            - { field_name: fsub_type,              width:  1, bit_offset: 11, access_mode: RW, address_offset: 0x24 }
+            - { field_name: payload_error,          width:  1, bit_offset: 10, access_mode: RW, address_offset: 0x24 }
+            - { field_name: repositioning_flag,     width:  1, bit_offset:  9, access_mode: RW, address_offset: 0x24 }
+            - { field_name: beamlet_width,          width:  3, bit_offset:  5, access_mode: RW, address_offset: 0x24 }
+            - { field_name: gn_index,               width:  5, bit_offset:  0, access_mode: RW, address_offset: 0x24 }
+
+          - - { field_name: reserved,               width: 32,                 access_mode: RW, address_offset: 0x1C, radix_width: 40 }
+          - - { field_name: beamlet_scale,          width: 16,                 access_mode: RW, address_offset: 0x18 }
+          - - { field_name: beamlet_index,          width: 16,                 access_mode: RW, address_offset: 0x14 }
+          - - { field_name: nof_blocks_per_packet,  width:  8,                 access_mode: RW, address_offset: 0x10 }
+          - - { field_name: nof_beamlets_per_block, width: 16,                 access_mode: RW, address_offset: 0xC }
+          - - { field_name: block_period,           width: 16,                 access_mode: RW, address_offset: 0x8 }
+          - - { field_name: BSN,                    width: 32,                 access_mode: RW, address_offset: 0x0, radix_width: 64 }
+
+
+  - peripheral_name: sdp_statistics_offload_hdr_dat_sst  #  pi_dp_offload_tx_hdr_dat_lofar2_sdp_statistics_offload.py
+    peripheral_description: "SDP statistics offload header for the subband statistics (SST)."
+    slave_ports:
+      # MM port for sdp_statistics_offload.vhd / dp_offload_tx_v3.vhd
+      - slave_name: REG_DP_OFFLOAD_TX_HDR_DAT
+        slave_description: |
+          "The ETH/IP/UDP/application header fields for the SST offload UDP packets.
+
+           The Subband statistics (SST) are integrated auto power values of the subbands per signal input.
+           The SST specific settings are defined by data_id_sst.
+
+           The statistics offload header fields are described in ICD SC-SDP [1].
+
+           [1] https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L2%20Interface%20Control%20Documents/SC%20to%20SDP%20ICD
+          "
+        slave_type: REG
+        fields:
+          # eth field group
+          - - { field_name: eth_destination_mac,       width: 32,                 access_mode: RW, address_offset: 0x84, radix_width: 48 }
+          - - { field_name: eth_source_mac,            width: 32,                 access_mode: RO, address_offset: 0x7C, radix_width: 48 }
+          - - { field_name: eth_type,                  width: 16,                 access_mode: RO, address_offset: 0x78 }
+          # ip field group
+          - - { field_name: ip_version,                width:  4,                 access_mode: RW, address_offset: 0x74 }
+          - - { field_name: ip_header_length,          width:  4,                 access_mode: RW, address_offset: 0x70 }
+          - - { field_name: ip_services,               width:  8,                 access_mode: RW, address_offset: 0x6C }
+          - - { field_name: ip_total_length,           width: 16,                 access_mode: RW, address_offset: 0x68 }
+          - - { field_name: ip_identification,         width: 16,                 access_mode: RW, address_offset: 0x64 }
+          - - { field_name: ip_flags,                  width:  3,                 access_mode: RW, address_offset: 0x60 }
+          - - { field_name: ip_fragment_offset,        width: 13,                 access_mode: RW, address_offset: 0x5C }
+          - - { field_name: ip_time_to_live,           width:  8,                 access_mode: RW, address_offset: 0x58 }
+          - - { field_name: ip_protocol,               width:  8,                 access_mode: RW, address_offset: 0x54 }
+          - - { field_name: ip_header_checksum,        width: 16,                 access_mode: RW, address_offset: 0x50 }
+          - - { field_name: ip_source_address,         width: 32,                 access_mode: RW, address_offset: 0x4C }
+          - - { field_name: ip_destination_address,    width: 32,                 access_mode: RW, address_offset: 0x48 }
+          # udp field group
+          - - { field_name: udp_source_port,           width: 16,                 access_mode: RW, address_offset: 0x44 }
+          - - { field_name: udp_destination_port,      width: 16,                 access_mode: RW, address_offset: 0x40 }
+          - - { field_name: udp_length,                width: 16,                 access_mode: RW, address_offset: 0x3C }
+          - - { field_name: udp_checksum,              width: 16,                 access_mode: RW, address_offset: 0x38 }
+          # application field group
+          - - { field_name: marker,                    width:  8,                 access_mode: RO, address_offset: 0x34 }
+          - - { field_name: version_id,                width:  8,                 access_mode: RO, address_offset: 0x30 }
+          - - { field_name: observation_id,            width: 32,                 access_mode: RW, address_offset: 0x2C }
+          - - { field_name: station_id,                width: 16,                 access_mode: RW, address_offset: 0x28 }
+          - - { field_name: source_info,               width: 16,                 access_mode: RW, address_offset: 0x24 }
+          - "source_info":
+            - { field_name: antenna_band_index,        width:  1, bit_offset: 15, access_mode: RW, address_offset: 0x24 }
+            - { field_name: nyquist_zone_index,        width:  2, bit_offset: 13, access_mode: RW, address_offset: 0x24 }
+            - { field_name: f_adc,                     width:  1, bit_offset: 12, access_mode: RW, address_offset: 0x24 }
+            - { field_name: fsub_type,                 width:  1, bit_offset: 11, access_mode: RW, address_offset: 0x24 }
+            - { field_name: payload_error,             width:  1, bit_offset: 10, access_mode: RW, address_offset: 0x24 }
+            - { field_name: beam_repositioning_flag,   width:  1, bit_offset:  9, access_mode: RW, address_offset: 0x24 }
+            - { field_name: subband_calibrated_flag,   width:  1, bit_offset:  8, access_mode: RW, address_offset: 0x24 }
+            - { field_name: reserved,                  width:  3, bit_offset:  5, access_mode: RW, address_offset: 0x24 }
+            - { field_name: gn_index,                  width:  5, bit_offset:  0, access_mode: RW, address_offset: 0x24 }
+
+          - - { field_name: reserved,                  width:  8,                 access_mode: RW, address_offset: 0x20 }
+          - - { field_name: integration_interval,      width: 24,                 access_mode: RW, address_offset: 0x1C }
+          - - { field_name: data_id,                   width: 32,                 access_mode: RW, address_offset: 0x18 }
+          - "data_id_sst":
+            - { field_name: reserved,                  width: 24, bit_offset:  8, access_mode: RW, address_offset: 0x18 }
+            - { field_name: signal_input_index,        width:  8, bit_offset:  0, access_mode: RW, address_offset: 0x18 }
+
+          - - { field_name: nof_signal_inputs,         width:  8,                 access_mode: RW, address_offset: 0x14 }
+          - - { field_name: nof_bytes_per_statistic,   width:  8,                 access_mode: RW, address_offset: 0x10 }
+          - - { field_name: nof_statistics_per_packet, width: 16,                 access_mode: RW, address_offset: 0xC }
+          - - { field_name: block_period,              width: 16,                 access_mode: RW, address_offset: 0x8 }
+          - - { field_name: BSN,                       width: 32,                 access_mode: RW, address_offset: 0x0, radix_width: 64 }
+
+
+  - peripheral_name: sdp_statistics_offload_hdr_dat_bst  #  pi_dp_offload_tx_hdr_dat_lofar2_sdp_statistics_offload.py
+    peripheral_description: "SDP statistics offload header for the beamlet statistics (BST)."
+    slave_ports:
+      # MM port for sdp_statistics_offload.vhd / dp_offload_tx_v3.vhd
+      - slave_name: REG_DP_OFFLOAD_TX_HDR_DAT
+        slave_description: |
+          "The ETH/IP/UDP/application header fields for the BST offload UDP packets.
+
+           The beamlet statistics (BST) are integrated auto power values of the beamlets per beamset
+           The BST specific settings are defined by data_id_bst.
+
+           The statistics offload header fields are described in ICD SC-SDP [1].
+
+           [1] https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L2%20Interface%20Control%20Documents/SC%20to%20SDP%20ICD
+          "
+        slave_type: REG
+        fields:
+          # eth field group
+          - - { field_name: eth_destination_mac,       width: 32,                 access_mode: RW, address_offset: 0x84, radix_width: 48 }
+          - - { field_name: eth_source_mac,            width: 32,                 access_mode: RO, address_offset: 0x7C, radix_width: 48 }
+          - - { field_name: eth_type,                  width: 16,                 access_mode: RO, address_offset: 0x78 }
+          # ip field group
+          - - { field_name: ip_version,                width:  4,                 access_mode: RW, address_offset: 0x74 }
+          - - { field_name: ip_header_length,          width:  4,                 access_mode: RW, address_offset: 0x70 }
+          - - { field_name: ip_services,               width:  8,                 access_mode: RW, address_offset: 0x6C }
+          - - { field_name: ip_total_length,           width: 16,                 access_mode: RW, address_offset: 0x68 }
+          - - { field_name: ip_identification,         width: 16,                 access_mode: RW, address_offset: 0x64 }
+          - - { field_name: ip_flags,                  width:  3,                 access_mode: RW, address_offset: 0x60 }
+          - - { field_name: ip_fragment_offset,        width: 13,                 access_mode: RW, address_offset: 0x5C }
+          - - { field_name: ip_time_to_live,           width:  8,                 access_mode: RW, address_offset: 0x58 }
+          - - { field_name: ip_protocol,               width:  8,                 access_mode: RW, address_offset: 0x54 }
+          - - { field_name: ip_header_checksum,        width: 16,                 access_mode: RW, address_offset: 0x50 }
+          - - { field_name: ip_source_address,         width: 32,                 access_mode: RW, address_offset: 0x4C }
+          - - { field_name: ip_destination_address,    width: 32,                 access_mode: RW, address_offset: 0x48 }
+          # udp field group
+          - - { field_name: udp_source_port,           width: 16,                 access_mode: RW, address_offset: 0x44 }
+          - - { field_name: udp_destination_port,      width: 16,                 access_mode: RW, address_offset: 0x40 }
+          - - { field_name: udp_length,                width: 16,                 access_mode: RW, address_offset: 0x3C }
+          - - { field_name: udp_checksum,              width: 16,                 access_mode: RW, address_offset: 0x38 }
+          # application field group
+          - - { field_name: marker,                    width:  8,                 access_mode: RO, address_offset: 0x34 }
+          - - { field_name: version_id,                width:  8,                 access_mode: RO, address_offset: 0x30 }
+          - - { field_name: observation_id,            width: 32,                 access_mode: RW, address_offset: 0x2C }
+          - - { field_name: station_id,                width: 16,                 access_mode: RW, address_offset: 0x28 }
+          - - { field_name: source_info,               width: 16,                 access_mode: RW, address_offset: 0x24 }
+          - "source_info":
+            - { field_name: antenna_band_index,        width:  1, bit_offset: 15, access_mode: RW, address_offset: 0x24 }
+            - { field_name: nyquist_zone_index,        width:  2, bit_offset: 13, access_mode: RW, address_offset: 0x24 }
+            - { field_name: f_adc,                     width:  1, bit_offset: 12, access_mode: RW, address_offset: 0x24 }
+            - { field_name: fsub_type,                 width:  1, bit_offset: 11, access_mode: RW, address_offset: 0x24 }
+            - { field_name: payload_error,             width:  1, bit_offset: 10, access_mode: RW, address_offset: 0x24 }
+            - { field_name: beam_repositioning_flag,   width:  1, bit_offset:  9, access_mode: RW, address_offset: 0x24 }
+            - { field_name: subband_calibrated_flag,   width:  1, bit_offset:  8, access_mode: RW, address_offset: 0x24 }
+            - { field_name: reserved,                  width:  3, bit_offset:  5, access_mode: RW, address_offset: 0x24 }
+            - { field_name: gn_index,                  width:  5, bit_offset:  0, access_mode: RW, address_offset: 0x24 }
+
+          - - { field_name: reserved,                  width:  8,                 access_mode: RW, address_offset: 0x20 }
+          - - { field_name: integration_interval,      width: 24,                 access_mode: RW, address_offset: 0x1C }
+          - - { field_name: data_id,                   width: 32,                 access_mode: RW, address_offset: 0x18 }
+          - "data_id_bst":
+            - { field_name: reserved,                  width: 16, bit_offset: 16, access_mode: RW, address_offset: 0x18 }
+            - { field_name: beamlet_index,             width: 16, bit_offset:  0, access_mode: RW, address_offset: 0x18 }
+
+          - - { field_name: nof_signal_inputs,         width:  8,                 access_mode: RW, address_offset: 0x14 }
+          - - { field_name: nof_bytes_per_statistic,   width:  8,                 access_mode: RW, address_offset: 0x10 }
+          - - { field_name: nof_statistics_per_packet, width: 16,                 access_mode: RW, address_offset: 0xC }
+          - - { field_name: block_period,              width: 16,                 access_mode: RW, address_offset: 0x8 }
+          - - { field_name: BSN,                       width: 32,                 access_mode: RW, address_offset: 0x0, radix_width: 64 }
+
+
+  - peripheral_name: sdp_statistics_offload_hdr_dat_xst  #  pi_dp_offload_tx_hdr_dat_lofar2_sdp_statistics_offload.py
+    peripheral_description: "SDP statistics offload header for the cross-subband statistics (XST)."
+    slave_ports:
+      # MM port for sdp_statistics_offload.vhd / dp_offload_tx_v3.vhd
+      - slave_name: REG_DP_OFFLOAD_TX_HDR_DAT
+        slave_description: |
+          "The ETH/IP/UDP/application header fields for the XST offload UDP packets.
+
+           The crosslet statistics (XST) are integrated cross power values of the subbands from all
+           pairs of signal inputs per suband.
+           The XST specific settings are defined by data_id_xst.
+
+           The statistics offload header fields are described in ICD SC-SDP [1].
+
+           [1] https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L2%20Interface%20Control%20Documents/SC%20to%20SDP%20ICD
+          "
+        slave_type: REG
+        fields:
+          # eth field group
+          - - { field_name: eth_destination_mac,       width: 32,                 access_mode: RW, address_offset: 0x84, radix_width: 48 }
+          - - { field_name: eth_source_mac,            width: 32,                 access_mode: RO, address_offset: 0x7C, radix_width: 48 }
+          - - { field_name: eth_type,                  width: 16,                 access_mode: RO, address_offset: 0x78 }
+          # ip field group
+          - - { field_name: ip_version,                width:  4,                 access_mode: RW, address_offset: 0x74 }
+          - - { field_name: ip_header_length,          width:  4,                 access_mode: RW, address_offset: 0x70 }
+          - - { field_name: ip_services,               width:  8,                 access_mode: RW, address_offset: 0x6C }
+          - - { field_name: ip_total_length,           width: 16,                 access_mode: RW, address_offset: 0x68 }
+          - - { field_name: ip_identification,         width: 16,                 access_mode: RW, address_offset: 0x64 }
+          - - { field_name: ip_flags,                  width:  3,                 access_mode: RW, address_offset: 0x60 }
+          - - { field_name: ip_fragment_offset,        width: 13,                 access_mode: RW, address_offset: 0x5C }
+          - - { field_name: ip_time_to_live,           width:  8,                 access_mode: RW, address_offset: 0x58 }
+          - - { field_name: ip_protocol,               width:  8,                 access_mode: RW, address_offset: 0x54 }
+          - - { field_name: ip_header_checksum,        width: 16,                 access_mode: RW, address_offset: 0x50 }
+          - - { field_name: ip_source_address,         width: 32,                 access_mode: RW, address_offset: 0x4C }
+          - - { field_name: ip_destination_address,    width: 32,                 access_mode: RW, address_offset: 0x48 }
+          # udp field group
+          - - { field_name: udp_source_port,           width: 16,                 access_mode: RW, address_offset: 0x44 }
+          - - { field_name: udp_destination_port,      width: 16,                 access_mode: RW, address_offset: 0x40 }
+          - - { field_name: udp_length,                width: 16,                 access_mode: RW, address_offset: 0x3C }
+          - - { field_name: udp_checksum,              width: 16,                 access_mode: RW, address_offset: 0x38 }
+          # application field group
+          - - { field_name: marker,                    width:  8,                 access_mode: RO, address_offset: 0x34 }
+          - - { field_name: version_id,                width:  8,                 access_mode: RO, address_offset: 0x30 }
+          - - { field_name: observation_id,            width: 32,                 access_mode: RW, address_offset: 0x2C }
+          - - { field_name: station_id,                width: 16,                 access_mode: RW, address_offset: 0x28 }
+          - - { field_name: source_info,               width: 16,                 access_mode: RW, address_offset: 0x24 }
+          - "source_info":
+            - { field_name: antenna_band_index,        width:  1, bit_offset: 15, access_mode: RW, address_offset: 0x24 }
+            - { field_name: nyquist_zone_index,        width:  2, bit_offset: 13, access_mode: RW, address_offset: 0x24 }
+            - { field_name: f_adc,                     width:  1, bit_offset: 12, access_mode: RW, address_offset: 0x24 }
+            - { field_name: fsub_type,                 width:  1, bit_offset: 11, access_mode: RW, address_offset: 0x24 }
+            - { field_name: payload_error,             width:  1, bit_offset: 10, access_mode: RW, address_offset: 0x24 }
+            - { field_name: beam_repositioning_flag,   width:  1, bit_offset:  9, access_mode: RW, address_offset: 0x24 }
+            - { field_name: subband_calibrated_flag,   width:  1, bit_offset:  8, access_mode: RW, address_offset: 0x24 }
+            - { field_name: reserved,                  width:  3, bit_offset:  5, access_mode: RW, address_offset: 0x24 }
+            - { field_name: gn_index,                  width:  5, bit_offset:  0, access_mode: RW, address_offset: 0x24 }
+
+          - - { field_name: reserved,                  width:  8,                 access_mode: RW, address_offset: 0x20 }
+          - - { field_name: integration_interval,      width: 24,                 access_mode: RW, address_offset: 0x1C }
+          - - { field_name: data_id,                   width: 32,                 access_mode: RW, address_offset: 0x18 }
+          - "data_id_xst":
+            - { field_name: reserved,                  width:  7, bit_offset: 25, access_mode: RW, address_offset: 0x18 }
+            - { field_name: subband_index,             width:  9, bit_offset: 16, access_mode: RW, address_offset: 0x18 }
+            - { field_name: signal_input_A_index,      width:  8, bit_offset:  8, access_mode: RW, address_offset: 0x18 }
+            - { field_name: signal_input_B_index,      width:  8, bit_offset:  0, access_mode: RW, address_offset: 0x18 }
+
+          - - { field_name: nof_signal_inputs,         width:  8,                 access_mode: RW, address_offset: 0x14 }
+          - - { field_name: nof_bytes_per_statistic,   width:  8,                 access_mode: RW, address_offset: 0x10 }
+          - - { field_name: nof_statistics_per_packet, width: 16,                 access_mode: RW, address_offset: 0xC }
+          - - { field_name: block_period,              width: 16,                 access_mode: RW, address_offset: 0x8 }
+          - - { field_name: BSN,                       width: 32,                 access_mode: RW, address_offset: 0x0, radix_width: 64 }
+
diff --git a/boards/uniboard2b/designs/unb2b_minimal/unb2b_minimal.fpga.yaml b/boards/uniboard2b/designs/unb2b_minimal/unb2b_minimal.fpga.yaml
index b8f2a9cf8463ea1a5a2beb12b8d564152c105075..d565fd51e20fcc034393508de0e0949b45f2fdc7 100644
--- a/boards/uniboard2b/designs/unb2b_minimal/unb2b_minimal.fpga.yaml
+++ b/boards/uniboard2b/designs/unb2b_minimal/unb2b_minimal.fpga.yaml
@@ -7,6 +7,9 @@ fpga_name       : unb2b_minimal
 fpga_description: "FPGA design unb2b_minimal"
 
 peripherals:
+  #############################################################################
+  # Factory / minimal (from ctrl_unb2b_board.vhd)
+  #############################################################################
   - peripheral_name: unb2b_board/system_info
     slave_port_names:
       - ROM_SYSTEM_INFO
diff --git a/boards/uniboard2b/libraries/unb2b_board/unb2b_board.peripheral.yaml b/boards/uniboard2b/libraries/unb2b_board/unb2b_board.peripheral.yaml
index f458a6c1d7f5b8b52a1c0b7c3714eca7f0712cac..b0fbfe3593fed32e2294895b053bd2a590eb965b 100644
--- a/boards/uniboard2b/libraries/unb2b_board/unb2b_board.peripheral.yaml
+++ b/boards/uniboard2b/libraries/unb2b_board/unb2b_board.peripheral.yaml
@@ -50,6 +50,12 @@ peripherals:
           #    number_of_fields: 32
 
           # Each field specified
+          - - field_name: info
+              field_description: "Info"
+              width: 32
+              bit_offset: 0
+              access_mode: RO
+              address_offset: 0x0
           - "info": # field_group
             - field_name: gn_index
               field_description: "Global node index, unb2 FPGA id = gn_index % 4, unb2 backplane id = gn_index // 4"
@@ -104,6 +110,7 @@ peripherals:
               address_offset: 0x8
               number_of_fields: 13
               radix: char
+              radix_width: 8
           - - field_name: stamp_date
               field_description: "FPGA FW compile date string."
               access_mode: RO
@@ -126,6 +133,7 @@ peripherals:
               address_offset: 0x50
               number_of_fields: 13
               radix: char
+              radix_width: 8
               
   - peripheral_name: wdi  # pi_wdi.py
     peripheral_description: ""
diff --git a/libraries/base/common/common.peripheral.yaml b/libraries/base/common/common.peripheral.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..88f2140b6f59c94fea39c199cb4d881f3f913ede
--- /dev/null
+++ b/libraries/base/common/common.peripheral.yaml
@@ -0,0 +1,26 @@
+schema_name: args
+schema_version: 1.0
+schema_type: peripheral
+
+hdl_library_name: common
+hdl_library_description: "Common peripherals for common logic and memory."
+
+peripherals:
+  - peripheral_name: common_variable_delay    # pi_common_variable_delay.py ???
+    peripheral_description: |
+      "The common_variable_delay.vhd logic can delay an input pulse by a number of clock cycles.
+       The delay depends on an internal signal input, such that it the delay is not fixed, but
+       can be different for different instances.
+       The delay is not programmable, but delayed output pulse can be enabled when enable = 1
+       or disabled when enable = 0."
+    slave_ports:
+      # MM port for mms_common_variable_delay.vhd / mms_common_reg.vhd
+      - slave_name: REG_COMMON_VARIABLE_DELAY
+        slave_type: REG
+        slave_description: ""
+        fields:
+          - - field_name: enable
+              field_description: "When 1 pass on delayed pulse to the output, else disable the output pulse."
+              width: 1
+              access_mode: RW
+              address_offset: 0x0
diff --git a/libraries/base/diag/diag.peripheral.yaml b/libraries/base/diag/diag.peripheral.yaml
index f14f4ef25e3863234a5217b761a91fc35313e9d2..6369308df94344a9e2cf815b0101a55d468ad42f 100644
--- a/libraries/base/diag/diag.peripheral.yaml
+++ b/libraries/base/diag/diag.peripheral.yaml
@@ -39,7 +39,7 @@ peripherals:
               bit_offset: 0
               address_offset: 0x4
           - - field_name: freq
-              field_description: "Frequency of WG sinus, freq = int('frequency in 0 to 1' * f_clk * 2**width), where f_clk = f_adc in Hz."
+              field_description: "Frequency of WG sinus, freq = int('frequency in range 0 to 1' * f_adc * 2**width), where f_adc is sample frequency in Hz."
               width: 31
               bit_offset: 0
               address_offset: 0x8
@@ -67,7 +67,7 @@ peripherals:
       - { name: g_nof_streams, value: 1 }
       - { name: g_data_w, value: 16 }
       - { name: g_nof_data, value: 1024 }
-      - { name: g_use_in_sync, value: true }
+      - { name: g_use_in_sync, value: True }
     slave_ports:                            
       # MM port for mms_diag_data_buffer.vhd
       - slave_name: REG_DIAG_DB
@@ -85,7 +85,7 @@ peripherals:
               address_offset: 0x4
       # MM port for mms_diag_data_buffer.vhd
       - slave_name: RAM_DIAG_DB
-        slave_description: "Data buffer memory, gets filled after the sync when g_use_in_sync = true, else after the last word was read."
+        slave_description: "Data buffer memory, gets filled after the sync when g_use_in_sync = True, else after the last word was read."
         slave_type: RAM
         number_of_slaves: g_nof_streams
         fields:
diff --git a/libraries/base/dp/dp.peripheral.yaml b/libraries/base/dp/dp.peripheral.yaml
index 30d8efd01b1b5006110e7d8e43e546b8dedfa624..d5c525b5dbf92d87bbaa4480bf373711d4fbf4e2 100644
--- a/libraries/base/dp/dp.peripheral.yaml
+++ b/libraries/base/dp/dp.peripheral.yaml
@@ -18,7 +18,6 @@ peripherals:
               field_description: "Number of words that can be read from the FIFO."
               access_mode: RO
               address_offset: 0x0
-      
       # MM port for mms_dp_fifo_to_mm.vhd / dp_fifo_to_mm.vhd
       - slave_name: REG_DPMM_DATA   # Use REG_, instead of preferred FIFO_, to match slave_port_name in pi_dpmm.py
         slave_type: FIFO
@@ -29,6 +28,7 @@ peripherals:
               access_mode: RO
               address_offset: 0x0
         
+
   - peripheral_name: mmdp    # pi_mmdp.py
     peripheral_description: "MM to DP FIFO to provide memory mapped MM write access to Data Path (DP) streaming interface."
     slave_ports:                            
@@ -46,7 +46,6 @@ peripherals:
               field_description: "Number of words that can be written to the write FIFO."
               access_mode: RO
               address_offset: 0x4
-      
       # MM port for mms_dp_fifo_from_mm.vhd / dp_fifo_from_mm.vhd
       - slave_name: REG_MMDP_DATA   # Use REG_, instead of preferred FIFO_, to match slave_port_name in pi_mmdp.py
         slave_type: FIFO
@@ -56,7 +55,30 @@ peripherals:
               field_description: "Write data to the FIFO."
               access_mode: WO
               address_offset: 0x0
-              
+
+
+  - peripheral_name: dp_xonoff    # pi_dp_xonoff.py
+    peripheral_description: "Enable or disable a data path (DP) stream."
+    parameters:
+      # Parameters of mms_dp_xonoff.vhd
+      - { name: g_nof_streams, value: 1 }
+      - { name: g_combine_streams, value: False }
+    slave_ports:
+      # MM port for mms_dp_xonoff.vhd
+      - slave_name: REG_DP_XONOFF
+        slave_type: REG
+        slave_description: "When g_combine_streams = False then there is one enable bit per stream, else there is one enable bit for all streams."
+        fields:
+          - - field_name: enable_stream
+              field_description: |
+                "When enable_stream = 0 the data stream is stopped, else when 1 then the data stream is passed on.
+                 Toggling the data stream on or off happens at block or packet boundaries."
+              width: 1
+              access_mode: RW
+              address_offset: 0x0
+              number_of_fields: 1 #g_nof_streams #sel_a_b(g_combine_streams, 1, g_nof_streams)
+
+
   - peripheral_name: dp_shiftram    # pi_dp_shiftram.py
     peripheral_description: "Sample delay buffer with programmable delay for streaming data."
     parameters:
@@ -77,6 +99,7 @@ peripherals:
               access_mode: RW
               address_offset: 0x0
 
+
   - peripheral_name: dp_bsn_source    # pi_dp_bsn_source.py
     peripheral_description: "Block Sequence Number (BSN) source for timestamping blocks of data samples."
     parameters:
@@ -106,14 +129,20 @@ peripherals:
               field_description: "Number of blocks per sync interval."
               access_mode: RW
               address_offset: 0x4
-          - - field_name: bsn_lo
-              field_description: "Initial BSN[31:0]"
+          #- - field_name: bsn_lo
+          #    field_description: "Initial BSN[31:0]"
+          #    access_mode: RW
+          #    address_offset: 0x8
+          #- - field_name: bsn_hi
+          #    field_description: "Initial BSN[63:32]"
+          #    access_mode: RW
+          #    address_offset: 0xC
+          - - field_name: bsn
+              field_description: "Initial BSN"
               access_mode: RW
               address_offset: 0x8
-          - - field_name: bsn_hi
-              field_description: "Initial BSN[63:32]"
-              access_mode: RW
-              address_offset: 0xC
+              radix_width: 64
+
 
   - peripheral_name: dp_bsn_source_v2    # pi_dp_bsn_source_v2.py
     peripheral_description: "Block Sequence Number (BSN) source with block time offset, for timestamping blocks of data samples."
@@ -146,19 +175,25 @@ peripherals:
               field_description: "Number of clock cycles per sync interval."
               access_mode: RW
               address_offset: 0x4
-          - - field_name: bsn_init_lo
-              field_description: "Initial BSN[31:0]"
+          #- - field_name: bsn_init_lo
+          #    field_description: "Initial BSN[31:0]"
+          #    access_mode: RW
+          #    address_offset: 0x8
+          #- - field_name: bsn_init_hi
+          #    field_description: "Initial BSN[63:32]"
+          #    access_mode: RW
+          #    address_offset: 0xC
+          - - field_name: bsn_init
+              field_description: "Initial BSN"
               access_mode: RW
               address_offset: 0x8
-          - - field_name: bsn_init_hi
-              field_description: "Initial BSN[63:32]"
-              access_mode: RW
-              address_offset: 0xC
+              radix_width: 64
           - - field_name: bsn_time_offset
               field_description: "The BSN block time offset in number of clock cycles, with respect to the PPS."
               width: g_bsn_time_offset_w
               access_mode: RW
               address_offset: 0x10
+
               
   - peripheral_name: dp_bsn_scheduler    # pi_dp_bsn_scheduler.py
     peripheral_description: "Schedule a trigger at a certain Block Sequence Number (BSN) instant."
@@ -168,14 +203,20 @@ peripherals:
         slave_type: REG
         slave_description: ""
         fields:
-          - - field_name: scheduled_bsn_lo
-              field_description: "Write scheduled BSN lo, read current BSN lo. First access lo, then hi."
+          #- - field_name: scheduled_bsn_lo
+          #    field_description: "Write scheduled BSN lo, read current BSN lo. First access lo, then hi."
+          #    access_mode: RW
+          #    address_offset: 0x0
+          #- - field_name: scheduled_bsn_hi
+          #    field_description: "Write scheduled BSN hi, read current BSN hi. First access lo, then hi."
+          #    access_mode: RW
+          #    address_offset: 0x4
+          - - field_name: scheduled_bsn
+              field_description: "Write scheduled BSN. First access lo, then hi."
               access_mode: RW
               address_offset: 0x0
-          - - field_name: scheduled_bsn_hi
-              field_description: "Write scheduled BSN hi, read current BSN hi. First access lo, then hi."
-              access_mode: RW
-              address_offset: 0x4
+              radix_width: 64
+
               
   - peripheral_name: dp_bsn_monitor    # pi_dp_bsn_monitor.py
     peripheral_description: "Monitor the Block Sequence Number (BSN) status of streaming data."
@@ -204,17 +245,22 @@ peripherals:
           - - field_name: sync_timeout
               field_description: "Data stream sync did not occur during last sync interval."
               width: 1
-              bit_offset: 2      # EK TODO: using 1 cause gen_doc.py to fail without clear error, because fields then overlap
+              bit_offset: 2      # EK TODO: 2 is correct, but using 1 cause gen_doc.py to fail without clear error, because fields then overlap
               access_mode: RO
               address_offset: 0x0
-          - - field_name: bsn_at_sync_lo
-              field_description: "Data stream BSN lo at sync."
+          #- - field_name: bsn_at_sync_lo
+          #    field_description: "Data stream BSN lo at sync."
+          #    access_mode: RO
+          #    address_offset: 0x4
+          #- - field_name: bsn_at_sync_hi
+          #    field_description: "Data stream BSN hi at sync."
+          #    access_mode: RO
+          #    address_offset: 0x8
+          - - field_name: bsn_at_sync
+              field_description: "Data stream BSN at sync."
               access_mode: RO
               address_offset: 0x4
-          - - field_name: bsn_at_sync_hi
-              field_description: "Data stream BSN hi at sync."
-              access_mode: RO
-              address_offset: 0x8
+              radix_width: 64
           - - field_name: nof_sop
               field_description: "Number data blocks (sop = start of packet) during last sync interval."
               access_mode: RO
@@ -227,19 +273,25 @@ peripherals:
               field_description: "Number data blocks with error indication during last sync interval."
               access_mode: RO
               address_offset: 0x14
-          - - field_name: bsn_first_lo
-              field_description: "First data stream BSN lo ever."
+          #- - field_name: bsn_first_lo
+          #    field_description: "First data stream BSN lo ever."
+          #    access_mode: RO
+          #    address_offset: 0x18
+          #- - field_name: bsn_first_hi
+          #    field_description: "First data stream BSN hi ever."
+          #    access_mode: RO
+          #    address_offset: 0x1C
+          - - field_name: bsn_first
+              field_description: "First data stream BSN ever."
               access_mode: RO
               address_offset: 0x18
-          - - field_name: bsn_first_hi
-              field_description: "First data stream BSN hi ever."
-              access_mode: RO
-              address_offset: 0x1C
+              radix_width: 64
           - - field_name: bsn_first_cycle_cnt
               field_description: "Arrival latency of first data stream BSN ever, relative to local sync."
               access_mode: RO
               address_offset: 0x20
 
+
   - peripheral_name: dp_bsn_monitor_v2    # pi_dp_bsn_monitor_v2.py
     peripheral_description: "Monitor the Block Sequence Number (BSN) status and latency of streaming data."
     parameters:
@@ -270,14 +322,19 @@ peripherals:
               bit_offset: 1
               access_mode: RO
               address_offset: 0x0
-          - - field_name: bsn_at_sync_lo
-              field_description: "Data stream BSN lo at sync."
+          #- - field_name: bsn_at_sync_lo
+          #    field_description: "Data stream BSN lo at sync."
+          #    access_mode: RO
+          #    address_offset: 0x4
+          #- - field_name: bsn_at_sync_hi
+          #    field_description: "Data stream BSN hi at sync."
+          #    access_mode: RO
+          #    address_offset: 0x8
+          - - field_name: bsn_at_sync
+              field_description: "Data stream BSN at sync."
               access_mode: RO
               address_offset: 0x4
-          - - field_name: bsn_at_sync_hi
-              field_description: "Data stream BSN hi at sync."
-              access_mode: RO
-              address_offset: 0x8
+              radix_width: 64
           - - field_name: nof_sop
               field_description: "Number data blocks (sop = start of packet) during last sync interval."
               access_mode: RO
@@ -294,3 +351,20 @@ peripherals:
               field_description: "Arrival latency of data stream BSN at sync, relative to local sync."
               access_mode: RO
               address_offset: 0x20
+
+
+  - peripheral_name: dp_selector    # pi_dp_selector.py
+    peripheral_description: "Select between two data streams or between two arrays of data streams."
+    slave_ports:
+      # MM port for dp_selector_arr.vhd
+      - slave_name: REG_DP_SELECTOR
+        slave_type: REG
+        slave_description: ""
+        fields:
+          - - field_name: input_select
+              field_description: |
+                "When input_select = 0 select the reference data stream(s), else when 1 select the other data stream(s).
+                 The input_select is synchronsized to the start of a sync interval."
+              width: 1
+              access_mode: RW
+              address_offset: 0x0
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_offload_tx_v3.vhd b/libraries/base/dp/tb/vhdl/tb_dp_offload_tx_v3.vhd
index 08566621228bb4e41e719517306f6497d1c6e96e..0481f2ff99f2ea88456c65a93dc800f136537c9b 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_offload_tx_v3.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_offload_tx_v3.vhd
@@ -42,7 +42,9 @@ USE common_lib.common_pkg.ALL;
 USE common_lib.common_lfsr_sequences_pkg.ALL;
 USE common_lib.common_mem_pkg.ALL;
 USE common_lib.common_field_pkg.ALL;
+USE common_lib.common_str_pkg.ALL;
 USE common_lib.tb_common_pkg.ALL;
+USE common_lib.tb_common_mem_pkg.ALL;
 USE work.dp_stream_pkg.ALL;
 USE work.tb_dp_pkg.ALL;
 
@@ -84,7 +86,8 @@ ARCHITECTURE tb OF tb_dp_offload_tx_v3 IS
   CONSTANT c_expected_pkt_len         : NATURAL := g_pkt_len;
   CONSTANT c_sync_period              : NATURAL := 5;
   CONSTANT c_sync_offset              : NATURAL := 2;
-  
+  CONSTANT c_bsn_init                 : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := TO_DP_BSN(0);
+
   CONSTANT c_hdr_len                  : NATURAL := 7;
   CONSTANT c_wait_last_evt            : NATURAL := 100 + g_nof_repeat * c_hdr_len;
 
@@ -92,36 +95,96 @@ ARCHITECTURE tb OF tb_dp_offload_tx_v3 IS
   -- Tx offload
   -----------------------------------------------------------------------------
   -- From apertif_udp_offload_pkg.vhd:
-  CONSTANT c_udp_offload_nof_hdr_fields : NATURAL := 3+12+4+3; -- 448b; 7 64b words
-  -- Notes: 
+  CONSTANT c_udp_offload_nof_hdr_fields : NATURAL := 3+12+4+3; -- 22, 448b; 7 64b words
+  CONSTANT c_udp_offload_nof_hdr_words  : NATURAL := 26;       -- 23 single word + 3 double word = 26 32b words
+  -- Notes:
   -- . pre-calculated ip_header_checksum is valid only for UNB0, FN0 targeting IP 10.10.10.10
   -- . udp_total_length = 176 beamlets * 64b / 8b = 1408B + 14 DP bytes + 8 UDP bytes = 1430B 
-  CONSTANT c_udp_offload_hdr_field_arr : t_common_field_arr(c_udp_offload_nof_hdr_fields-1 DOWNTO 0) := (
-         ( field_name_pad("eth_dst_mac"            ), "RW", 48, field_default(x"001B214368AC") ),
-         ( field_name_pad("eth_src_mac"            ), "RW", 48, field_default(0) ),
-         ( field_name_pad("eth_type"               ), "RW", 16, field_default(x"0800") ),
-         ( field_name_pad("ip_version"             ), "RW",  4, field_default(4) ),
-         ( field_name_pad("ip_header_length"       ), "RW",  4, field_default(5) ),
-         ( field_name_pad("ip_services"            ), "RW",  8, field_default(0) ),
-         ( field_name_pad("ip_total_length"        ), "RW", 16, field_default(1450) ), 
-         ( field_name_pad("ip_identification"      ), "RW", 16, field_default(0) ),
-         ( field_name_pad("ip_flags"               ), "RW",  3, field_default(2) ),
-         ( field_name_pad("ip_fragment_offset"     ), "RW", 13, field_default(0) ),
-         ( field_name_pad("ip_time_to_live"        ), "RW",  8, field_default(127) ),
-         ( field_name_pad("ip_protocol"            ), "RW",  8, field_default(17) ),
-         ( field_name_pad("ip_header_checksum"     ), "RW", 16, field_default(29928) ),
-         ( field_name_pad("ip_src_addr"            ), "RW", 32, field_default(x"C0A80009") ),
-         ( field_name_pad("ip_dst_addr"            ), "RW", 32, field_default(x"C0A80001") ),
-         ( field_name_pad("udp_src_port"           ), "RW", 16, field_default(0) ), 
-         ( field_name_pad("udp_dst_port"           ), "RW", 16, field_default(0) ), 
-         ( field_name_pad("udp_total_length"       ), "RW", 16, field_default(1430) ),
-         ( field_name_pad("udp_checksum"           ), "RW", 16, field_default(0) ),
-         ( field_name_pad("dp_reserved"            ), "RW", 47, field_default(0) ),
-         ( field_name_pad("dp_sync"                ), "RW",  1, field_default(0) ),
-         ( field_name_pad("dp_bsn"                 ), "RW", 64, field_default(0) ) );
-
-  -- From apertif_unb1_fn_beamformer_udp_offload.vhd:
-  -- Override ('1') only the Ethernet fields so we can use MM defaults there.
+  CONSTANT c_udp_offload_hdr_field_arr : t_common_field_arr(c_udp_offload_nof_hdr_fields-1 DOWNTO 0) := ( -- index
+         ( field_name_pad("eth_dst_mac"            ), "RW", 48, field_default(x"001B214368AC") ),         -- 21
+         ( field_name_pad("eth_src_mac"            ), "RW", 48, field_default(x"0123456789AB") ),         -- 20
+         ( field_name_pad("eth_type"               ), "RW", 16, field_default(x"0800") ),                 -- 19
+         ( field_name_pad("ip_version"             ), "RW",  4, field_default(4) ),                       -- 18
+         ( field_name_pad("ip_header_length"       ), "RW",  4, field_default(5) ),                       -- 17
+         ( field_name_pad("ip_services"            ), "RW",  8, field_default(0) ),                       -- 16
+         ( field_name_pad("ip_total_length"        ), "RW", 16, field_default(1450) ),                    -- 15
+         ( field_name_pad("ip_identification"      ), "RW", 16, field_default(0) ),                       -- 14
+         ( field_name_pad("ip_flags"               ), "RW",  3, field_default(2) ),                       -- 13
+         ( field_name_pad("ip_fragment_offset"     ), "RW", 13, field_default(0) ),                       -- 12
+         ( field_name_pad("ip_time_to_live"        ), "RW",  8, field_default(127) ),                     -- 11
+         ( field_name_pad("ip_protocol"            ), "RW",  8, field_default(17) ),                      -- 10
+         ( field_name_pad("ip_header_checksum"     ), "RW", 16, field_default(29928) ),                   -- 9
+         ( field_name_pad("ip_src_addr"            ), "RW", 32, field_default(x"C0A80009") ),             -- 8
+         ( field_name_pad("ip_dst_addr"            ), "RW", 32, field_default(x"C0A80001") ),             -- 7
+         ( field_name_pad("udp_src_port"           ), "RW", 16, field_default(0) ),                       -- 6
+         ( field_name_pad("udp_dst_port"           ), "RW", 16, field_default(0) ),                       -- 5
+         ( field_name_pad("udp_total_length"       ), "RW", 16, field_default(1430) ),                    -- 4
+         ( field_name_pad("udp_checksum"           ), "RW", 16, field_default(0) ),                       -- 3
+         ( field_name_pad("dp_reserved"            ), "RW", 47, field_default(x"010203040506") ),         -- 2
+         ( field_name_pad("dp_sync"                ), "RW",  1, field_default(0) ),                       -- 1
+         ( field_name_pad("dp_bsn"                 ), "RW", 64, field_default(0) ) );                     -- 0
+
+  -- TX: Corresponding storage of c_udp_offload_hdr_field_arr in MM register words
+  -- . Note: It appears that the tx_hdr_word read values are the MM write values, so read of value from logic fields (with MM override '0', e.g. dp_bsn, eth_src_mac) is not supported.
+  CONSTANT c_expected_tx_hdr_word_arr : t_slv_32_arr(0 TO c_udp_offload_nof_hdr_words-1) := ( -- word address
+                                                                             X"00000000",     -- 0   = dp_bsn[31:0]        -- readback is MM value, not the logic value
+                                                                             X"00000000",     -- 1   = dp_bsn[63:32]
+                                                                             X"00000000",     -- 2   = dp_sync
+                                                                             X"03040506",     -- 3   = dp_reserved[31:0]
+                                                                             X"00000102",     -- 4   = dp_reserved[47:32]
+                                                                             X"00000000",     -- 5   = udp_checksum
+                                                                             X"00000596",     -- 6   = udp_total_length
+                                                                             X"00000000",     -- 7   = udp_dst_port
+                                                                             X"00000000",     -- 8   = udp_src_port        -- readback is MM value, not the logic value
+                                                                             X"C0A80001",     -- 9   = ip_dst_addr
+                                                                             X"C0A80009",     -- 10  = ip_src_addr
+                                                                             X"000074E8",     -- 11  = ip_header_checksum
+                                                                             X"00000011",     -- 12  = ip_protocol
+                                                                             X"0000007F",     -- 13  = ip_time_to_live
+                                                                             X"00000000",     -- 14  = ip_fragment_offset
+                                                                             X"00000002",     -- 15  = ip_flags
+                                                                             X"00000000",     -- 16  = ip_identification
+                                                                             X"000005AA",     -- 17  = ip_total_length
+                                                                             X"00000000",     -- 18  = ip_services
+                                                                             X"00000005",     -- 19  = ip_header_length
+                                                                             X"00000004",     -- 20  = ip_version
+                                                                             X"00000800",     -- 21  = eth_type[15:0]
+                                                                             X"456789AB",     -- 22  = eth_src_mac[31:0]   -- readback is MM value, not the logic value
+                                                                             X"00000123",     -- 23  = eth_src_mac[47:32]
+                                                                             X"214368AC",     -- 24  = eth_dst_mac[31:0]
+                                                                             X"0000001B");    -- 25  = eth_dst_mac[47:32]
+
+  -- RX: Corresponding storage of c_udp_offload_hdr_field_arr in MM register words
+  CONSTANT c_expected_rx_hdr_word_arr : t_slv_32_arr(0 TO c_udp_offload_nof_hdr_words-1) := ( -- word address
+                                                                             X"0000000B",     -- 0   = dp_bsn[31:0]        -- dynamic value obtained from simulation
+                                                                             X"00000000",     -- 1   = dp_bsn[63:32]
+                                                                             X"00000000",     -- 2   = dp_sync             -- dynamic value obtained from simulation
+                                                                             X"03040506",     -- 3   = dp_reserved[31:0]
+                                                                             X"00000102",     -- 4   = dp_reserved[47:32]
+                                                                             X"00000000",     -- 5   = udp_checksum
+                                                                             X"00000596",     -- 6   = udp_total_length
+                                                                             X"00000000",     -- 7   = udp_dst_port
+                                                                             X"00000000",     -- 8   = udp_src_port
+                                                                             X"C0A80001",     -- 9   = ip_dst_addr
+                                                                             X"C0A80009",     -- 10  = ip_src_addr
+                                                                             X"000074E8",     -- 11  = ip_header_checksum
+                                                                             X"00000011",     -- 12  = ip_protocol
+                                                                             X"0000007F",     -- 13  = ip_time_to_live
+                                                                             X"00000000",     -- 14  = ip_fragment_offset
+                                                                             X"00000002",     -- 15  = ip_flags
+                                                                             X"00000000",     -- 16  = ip_identification
+                                                                             X"000005AA",     -- 17  = ip_total_length
+                                                                             X"00000000",     -- 18  = ip_services
+                                                                             X"00000005",     -- 19  = ip_header_length
+                                                                             X"00000004",     -- 20  = ip_version
+                                                                             X"00000800",     -- 21  = eth_type[15:0]
+                                                                             X"86080000",     -- 22  = eth_src_mac[31:0]   -- readback is the logic value x"00228608" & id_backplane = 0 & id_chip = 0 (c_NODE_ID = 0)
+                                                                             X"00000022",     -- 23  = eth_src_mac[47:32]
+                                                                             X"214368AC",     -- 24  = eth_dst_mac[31:0]
+                                                                             X"0000001B");    -- 25  = eth_dst_mac[47:32]
+
+  -- From apertif_unb1_fn_beamformer_udp_offload.vhd:                                           221   111111111000   0000   000
+  -- Override ('1') only the Ethernet fields so we can use MM defaults there.                   109   876543210987   6543   210
   CONSTANT c_hdr_field_ovr_init : STD_LOGIC_VECTOR(c_udp_offload_nof_hdr_fields-1 DOWNTO 0) := "101"&"111111111111"&"1111"&"100";
 
   CONSTANT c_NODE_ID                    : STD_LOGIC_VECTOR(7 DOWNTO 0) := TO_UVEC(0, 8);
@@ -137,7 +200,10 @@ ARCHITECTURE tb OF tb_dp_offload_tx_v3 IS
   
   SIGNAL tx_hdr_fields_in_arr           : t_slv_1024_arr(0 DOWNTO 0);
   SIGNAL tx_hdr_fields_out_arr          : t_slv_1024_arr(0 DOWNTO 0);
-  
+
+  SIGNAL tx_hdr_word                    : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
+  SIGNAL rx_hdr_word                    : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
+
   SIGNAL reg_dp_offload_tx_hdr_dat_mosi : t_mem_mosi := c_mem_mosi_rst;
   SIGNAL reg_dp_offload_tx_hdr_dat_miso : t_mem_miso;
 
@@ -210,6 +276,7 @@ BEGIN
     -- initializations
     g_sync_period    => c_sync_period,
     g_sync_offset    => c_sync_offset,
+    g_bsn_init       => c_bsn_init,
     -- specific
     g_in_dat_w       => g_data_w,
     g_nof_repeat     => g_nof_repeat,
@@ -366,6 +433,29 @@ BEGIN
     hdr_fields_out_arr    => tx_hdr_fields_out_arr
   );
 
+
+  p_rd_tx_hdr_words : PROCESS
+    VARIABLE v_word : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
+  BEGIN
+    proc_common_wait_until_hi_lo(dp_clk, tx_offload_sosi_arr(0).sync);
+    proc_common_wait_until_hi_lo(dp_clk, tx_offload_sosi_arr(0).sync);
+    print_str("");
+    FOR I IN 0 TO c_udp_offload_nof_hdr_words-1 LOOP
+      proc_mem_mm_bus_rd(I, mm_clk, reg_dp_offload_tx_hdr_dat_mosi);
+      proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk);
+      v_word := reg_dp_offload_tx_hdr_dat_miso.rddata(31 DOWNTO 0);
+      -- Log word in transcript window
+      print_str("tx_hdr_word(" & int_to_str(I) & ") = " & slv_to_hex(v_word));
+      -- View word in wave window
+      tx_hdr_word <= v_word;
+      -- Verify expected word
+      ASSERT c_expected_tx_hdr_word_arr(I) = v_word REPORT "Unexpected tx_hdr_word at address " & int_to_str(I) & ", expected " & slv_to_hex(c_expected_tx_hdr_word_arr(I)) SEVERITY ERROR;
+    END LOOP;
+    print_str("");
+    WAIT;
+  END PROCESS;
+
+
   ------------------------------------------------------------------------------
   -- Link
   ------------------------------------------------------------------------------
@@ -424,7 +514,31 @@ BEGIN
 
   dp_offload_rx_src_in_arr    <= (OTHERS=>c_dp_siso_rdy);
   dp_offload_rx_src_in_arr(0) <= verify_snk_out;
-  
+
+
+  p_rd_rx_hdr_words : PROCESS
+    VARIABLE v_word : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
+  BEGIN
+    proc_common_wait_until_hi_lo(dp_clk, verify_snk_in.sync);
+    proc_common_wait_until_hi_lo(dp_clk, verify_snk_in.sync);
+    proc_common_wait_until_hi_lo(dp_clk, verify_snk_in.sync);
+    print_str("");
+    FOR I IN 0 TO c_udp_offload_nof_hdr_words-1 LOOP
+      proc_mem_mm_bus_rd(I, mm_clk, reg_dp_offload_rx_hdr_dat_mosi);
+      proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk);
+      v_word := reg_dp_offload_rx_hdr_dat_miso.rddata(31 DOWNTO 0);
+      -- Log word in transcript window
+      print_str("rx_hdr_word(" & int_to_str(I) & ") : " & slv_to_hex(v_word));
+      -- View word in wave window
+      rx_hdr_word <= v_word;
+      -- Verify expected word
+      ASSERT c_expected_rx_hdr_word_arr(I) = v_word REPORT "Unexpected rx_hdr_word at address " & int_to_str(I) & ", expected " & slv_to_hex(c_expected_rx_hdr_word_arr(I)) SEVERITY ERROR;
+    END LOOP;
+    print_str("");
+    WAIT;
+  END PROCESS;
+
+
   ------------------------------------------------------------------------------
   -- Auxiliary
   ------------------------------------------------------------------------------
diff --git a/libraries/base/reorder/reorder.peripheral.yaml b/libraries/base/reorder/reorder.peripheral.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..77d3417d71cb0ae94c0a84cd8a552e651bf87193
--- /dev/null
+++ b/libraries/base/reorder/reorder.peripheral.yaml
@@ -0,0 +1,34 @@
+schema_name: args
+schema_version: 1.0
+schema_type: peripheral
+
+hdl_library_name: reorder
+hdl_library_description: "Reorder data within and between data streams."
+
+peripherals:
+  - peripheral_name: reorder_col_wide    # pi_ss_ss_wide.py
+    peripheral_description: |
+      "Reorder the data serially per stream.
+       Each block of g_nof_ch_in input data gets stored, and then a block of g_nof_ch_sel
+       selected data is passed on. The index fields specify the order and the index of
+       the input data that is passed on.
+       There are g_wb_factor parallel data streams. All data streams can be reordered
+       independently."
+    parameters:
+      # Parameters of reorder_col_wide.vhd / reorder_col.vhd
+      - { name: g_wb_factor, value: 1 }
+      - { name: g_nof_ch_in, value: 256 }
+      - { name: g_nof_ch_sel, value: 192 }  # g_nof_ch_sel < g_nof_ch_in
+    slave_ports:                            
+      # MM port for reorder_col_wide.vhd / reorder_col.vhd
+      - slave_name: RAM_SS_SS_WIDE
+        slave_description: ""
+        slave_type: RAM
+        number_of_slaves: g_wb_factor
+        fields:
+          - - field_name: index
+              field_description: ""
+              width: ceil_log2(g_nof_ch_in)
+              address_offset: 0x0
+              number_of_fields: g_nof_ch_sel
+
diff --git a/libraries/dsp/filter/filter.peripheral.yaml b/libraries/dsp/filter/filter.peripheral.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a9d61075825e5e97ac9f65cde3ff69016d75bec6
--- /dev/null
+++ b/libraries/dsp/filter/filter.peripheral.yaml
@@ -0,0 +1,44 @@
+schema_name: args
+schema_version: 1.0
+schema_type: peripheral
+
+hdl_library_name: filter
+hdl_library_description: "Poly-phase filter (PPF) for a Wideband Poly-phase filterbank (WPFB)"
+
+peripherals:
+  - peripheral_name: fil_ppf_w    # pi_fil_ppf_w.py
+    peripheral_description: |
+      "PPF FIR filter for wideband data streams, all data streams use the same FIR coefficients.
+       The PPF has g_nof_bands phases, where g_nof_bands is equal to the size of the FFT in the
+       PFB. The PPF has g_nof_taps FIR taps per phase. Hence the total number of FIR coefficients
+       is g_nof_taps * g_nof_bands. 
+       The PPF can process a data stream that is clocked at a wideband factor g_wb_factor higher
+       data rate, by running g_wb_factor parts in parallel.
+       The FIR coefficients are real values."
+    parameters:
+      # Parameters of fil_ppf_wide.vhd
+      - { name: g_wb_factor, value: 1 }
+      - { name: g_nof_taps, value: 8 }
+      - { name: g_nof_bands, value: 256 }
+      - { name: g_coef_dat_w, value: 16 }
+    slave_ports:                            
+      # MM port for fil_ppf_wide.vhd / fil_ppf_single.vhd
+      - slave_name: RAM_FIL_COEFS
+        slave_description: | 
+           "The FIR filter coefficients are stored in blocks of g_nof_bands/g_wb_factor real
+            coefficients:
+           
+            (int16)coefs[g_wb_factor][g_nof_taps][g_nof_bands/g_wb_factor]
+           
+            For g_wb_factor = 1 this reduces to g_nof_taps blocks of g_nof_bands/g_wb_factor
+            coefficients:
+           
+            (int16)coefs[g_nof_taps][g_nof_bands]"
+        slave_type: RAM
+        number_of_slaves: g_wb_factor * g_nof_taps
+        fields:
+          - - field_name: coef
+              field_description: "Real FIR filter coefficient"
+              width: g_coef_dat_w
+              address_offset: 0x0
+              number_of_fields: g_nof_bands / g_wb_factor
diff --git a/libraries/dsp/si/si.peripheral.yaml b/libraries/dsp/si/si.peripheral.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c8310c476acdf661fc6406027aaaad5ea77d6bb2
--- /dev/null
+++ b/libraries/dsp/si/si.peripheral.yaml
@@ -0,0 +1,20 @@
+schema_name: args
+schema_version: 1.0
+schema_type: peripheral
+
+hdl_library_name: si
+hdl_library_description: "Spectral Inversion (SI)"
+
+peripherals:
+  - peripheral_name: si    # pi_si.py
+    peripheral_description: "Spectral Inversion control."
+    slave_ports:                            
+      # MM port for si_arr.vhd
+      - slave_name: REG_SI
+        slave_description: "In the even Nyquist zones the sampled spectrum gets flipped in frequency. This flip can be compensated for by enabling spectral inversion (SI)."
+        slave_type: REG
+        fields:
+          - - field_name: enable
+              field_description: "When 0 then pass on the array of input signals, when 1 then enable spectral inversion for all the input signals."
+              width: 1
+              address_offset: 0x0
diff --git a/libraries/dsp/st/st.peripheral.yaml b/libraries/dsp/st/st.peripheral.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..346577aa51c26a934bcffeee521c76caddece2ac
--- /dev/null
+++ b/libraries/dsp/st/st.peripheral.yaml
@@ -0,0 +1,99 @@
+schema_name: args
+schema_version: 1.0
+schema_type: peripheral
+
+hdl_library_name: st
+hdl_library_description: "Statistics (ST)"
+
+peripherals:
+  - peripheral_name: st_sst  # pi_st_sst.py
+    peripheral_description: |
+       "Accumulate the signal power values during a sync interval:
+        . g_xst_enable = False : Auto power statistics for subbands (SST), beamlets (BST)
+        . g_xst_enable = True : Cross power statistics for subbands = crosslets (XST)."
+    parameters:
+      # Parameters of pi_st_sst.py
+      - { name: g_nof_instances, value: 1 }
+      # Parameters of st_sst.vhd
+      - { name: g_nof_stat, value: 512 }  # nof accumulators
+      - { name: g_xst_enable, value: False }  # False for auto powers, True for cross powers
+      - { name: g_stat_data_w, value: 64 }  # statistics accumulator width in bits
+      - { name: g_stat_data_sz, value: 2 }  # statistics accumulator width in 32b MM words
+    slave_ports:                            
+      # MM port for st_sst.vhd
+      - slave_name: RAM_ST_SST
+        slave_description: |
+           "The statistics are calculated for blocks of g_nof_stat time multiplexed data streams.
+            There are g_nof_instances parallel time multiplexed data streams.
+            The statistic power values have g_stat_data_w bits. The memory format is:
+            . g_xst_enable = False, for real powers : (uint32 * g_stat_data_sz)st[g_nof_instances]_[g_nof_stat]
+            . g_xst_enable = True, for complex powers : (cuint32 * g_stat_data_sz)st[g_nof_instances]_[g_nof_stat]"
+        slave_type: RAM
+        number_of_slaves: g_nof_instances
+        fields:
+          - - field_name: power
+              field_description: ""
+              width: g_stat_data_w
+              address_offset: 0x0
+              number_of_fields: g_nof_stat * g_stat_data_sz
+
+              
+  - peripheral_name: st_sst_for_sdp  # pi_st_sst.py
+    peripheral_description: |
+       "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 }
+      # 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 width in bits: W_statistic = 64
+      - { name: g_stat_data_sz, value: 2 }  # statistics accumulator width in 32b MM words: W_statistic_sz = 2
+    slave_ports:                            
+      # MM port for st_sst.vhd
+      - slave_name: RAM_ST_SST
+        slave_description: |
+          "The subband statistics per PN are stored in g_nof_instances = P_pfb = S_pn / Q_fft = 6 blocks of 
+           N_sub * Q_fft = 512 * 2 = 1024 real values as:
+          
+           (uint64)SST[g_nof_instances]_[g_nof_stat] = (uint64)SST[S_pn/Q_fft]_[N_sub][Q_fft]
+          
+           where S_pn = 12, Q_fft = 2 and N_sub = 512 are defined in sdp_pkg.vhd."
+        slave_type: RAM
+        number_of_slaves: g_nof_instances
+        fields:
+          - - field_name: power
+              field_description: ""
+              width: 32
+              address_offset: 0x0
+              number_of_fields: g_nof_stat * g_stat_data_sz
+              radix_width: g_stat_data_w
+
+
+  - peripheral_name: st_bst_for_sdp  # pi_st_bst.py
+    peripheral_description: |
+       "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 }
+      # 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 width in bits: W_statistic = 64
+      - { name: g_stat_data_sz, value: 2 }  # statistics accumulator width in 32b MM words: W_statistic_sz = 2
+    slave_ports:
+      # MM port for st_sst.vhd
+      - slave_name: RAM_ST_SST
+        slave_description: |
+          "The beamlet statistics per PN are stored in 1 block of S_sub_bf * N_pol_bf = 488 * 2 = 976 real values as:
+
+           (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."
+        slave_type: RAM
+        number_of_slaves: 1
+        fields:
+          - - field_name: power
+              field_description: ""
+              width: 32
+              address_offset: 0x0
+              number_of_fields: g_nof_stat * g_stat_data_sz
+              radix_width: g_stat_data_w
diff --git a/libraries/io/aduh/aduh.peripheral.yaml b/libraries/io/aduh/aduh.peripheral.yaml
index 6d8ab929cf20183d2c5dd4d88812fb4be2f7cf61..403480b22f33ef9c1c4ce2b7d3de47612b93ded6 100644
--- a/libraries/io/aduh/aduh.peripheral.yaml
+++ b/libraries/io/aduh/aduh.peripheral.yaml
@@ -43,12 +43,12 @@ peripherals:
       - { name: g_symbol_w, value: 16 }
       - { name: g_nof_symbols_per_data, value: 1 }
       - { name: g_buffer_nof_symbols, value: 512 }
-      - { name: g_buffer_use_sync, value: true }
+      - { name: g_buffer_use_sync, value: True }
     slave_ports:
       # MM port for mms_aduh_monitor_arr.vhd
       - slave_name: RAM_ADUH_MON
         slave_type: RAM
-        slave_description: "Data buffer memory, gets filled after the sync when g_buffer_use_sync = true, else after the last word was read."
+        slave_description: "Data buffer memory, gets filled after the sync when g_buffer_use_sync = True, else after the last word was read."
         number_of_slaves: g_nof_streams
         fields:
           - - field_name: data
diff --git a/libraries/io/nw_10GbE/nw_10GbE.peripheral.yaml b/libraries/io/nw_10GbE/nw_10GbE.peripheral.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ea93bed46fa0b98954cf8603d0915b3618978938
--- /dev/null
+++ b/libraries/io/nw_10GbE/nw_10GbE.peripheral.yaml
@@ -0,0 +1,179 @@
+schema_name: args
+schema_version: 1.0
+schema_type: peripheral
+
+hdl_library_name: nw_10GbE
+hdl_library_description: "Network peripherals for 10GbE."
+
+peripherals:
+  - peripheral_name: nw_10GbE_unb2legacy    # pi_nw_10GbE_unb2legacy.py / pi_tr_10GbE.py / pi_tr_10GbE_unb2.py
+    peripheral_description: |
+      "M&C of Intel Low Latency (LL) 10GbE MAC control status register (CSR) see [1]
+
+       The LL 10GbE MAC is used with the legacy address map option of the old 10GbE MAC, see [2], this implies:
+       . Some registers have a different address offset in [1] and [2]
+       . The 36 bit registers are stored at word 0 = [31:0] and word 1 = [3:0] = [35:32] in [1], but in [2]
+         they are stored with their 4 most significant bits first and their 32 least significant bits last, so
+         with word 0 = [3:0] = [35:32] and word 1 = [31:0].
+       Here the address map and 36 bit word order from [2] are used.
+
+       [1] LL 10GbE MAC, https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_32b_10g_ethernet_mac.pdf
+       [2] Legacy 10GbE MAC, https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/10gbps_mac.pdf
+      "
+    parameters:
+      # Parameters of nw_10GbE.vhd / tr_10GbE.vhd
+      - { name: g_nof_macs, value: 1 }
+    slave_ports:
+      # MM port for reg_mac_mosi = mac_mosi in ip_arria10_e1sg_eth_10g.vhd
+      # Use nw_10GbE_word_to_byte_address.py to derive the byte addresses from the word addresses
+      - slave_name: REG_NW_10GBE_MAC
+        slave_type: REG
+        slave_description: "MAC registers"
+        number_of_slaves: g_nof_macs
+        fields:
+          - - {field_name: rx_transfer_control,                     width:  1, access_mode: RW, address_offset: 0x0000                  }  # = 0x0000
+          - - {field_name: rx_transfer_status,                      width:  1, access_mode: RO, address_offset: 0x0004                  }  # = 0x0001
+          - - {field_name: rx_padcrc_control,                       width:  2, access_mode: RW, address_offset: 0x0100                  }  # = 0x0040
+          - - {field_name: rx_crccheck_control,                     width:  2, access_mode: RW, address_offset: 0x0200                  }  # = 0x0080
+          - - {field_name: rx_pktovrflow_error,                     width: 32, access_mode: RO, address_offset: 0x0300, radix_width: 36 }  # = 0x00C0
+          - - {field_name: rx_pktovrflow_etherStatsDropEvents,      width: 32, access_mode: RO, address_offset: 0x0308, radix_width: 36 }  # = 0x00C2
+          - - {field_name: rx_lane_decoder_preamble_control,        width:  1, access_mode: RW, address_offset: 0x0400                  }  # = 0x0100
+          - - {field_name: rx_preamble_inserter_control,            width:  1, access_mode: RW, address_offset: 0x0500                  }  # = 0x0140
+          - - {field_name: rx_frame_control,                        width: 20, access_mode: RW, address_offset: 0x2000                  }  # = 0x0800
+          - - {field_name: rx_frame_maxlength,                      width: 16, access_mode: RW, address_offset: 0x2004                  }  # = 0x0801
+          - - {field_name: rx_frame_addr0,                          width: 16, access_mode: RW, address_offset: 0x2008                  }  # = 0x0802
+          - - {field_name: rx_frame_addr1,                          width: 16, access_mode: RW, address_offset: 0x200c                  }  # = 0x0803
+          - - {field_name: rx_frame_spaddr0_0,                      width: 16, access_mode: RW, address_offset: 0x2010                  }  # = 0x0804
+          - - {field_name: rx_frame_spaddr0_1,                      width: 16, access_mode: RW, address_offset: 0x2014                  }  # = 0x0805
+          - - {field_name: rx_frame_spaddr1_0,                      width: 16, access_mode: RW, address_offset: 0x2018                  }  # = 0x0806
+          - - {field_name: rx_frame_spaddr1_1,                      width: 16, access_mode: RW, address_offset: 0x201c                  }  # = 0x0807
+          - - {field_name: rx_frame_spaddr2_0,                      width: 16, access_mode: RW, address_offset: 0x2020                  }  # = 0x0808
+          - - {field_name: rx_frame_spaddr2_1,                      width: 16, access_mode: RW, address_offset: 0x2024                  }  # = 0x0809
+          - - {field_name: rx_frame_spaddr3_0,                      width: 16, access_mode: RW, address_offset: 0x2028                  }  # = 0x080A
+          - - {field_name: rx_frame_spaddr3_1,                      width: 16, access_mode: RW, address_offset: 0x202c                  }  # = 0x080B
+          - - {field_name: rx_pfc_control,                          width: 17, access_mode: RW, address_offset: 0x2060                  }  # = 0x0818
+          - - {field_name: tx_transfer_control,                     width:  1, access_mode: RW, address_offset: 0x4000                  }  # = 0x1000
+          - - {field_name: tx_transfer_status,                      width:  1, access_mode: RO, address_offset: 0x4004                  }  # = 0x1001
+          - - {field_name: tx_padins_control,                       width:  1, access_mode: RW, address_offset: 0x4100                  }  # = 0x1040
+          - - {field_name: tx_crcins_control,                       width:  2, access_mode: RW, address_offset: 0x4200                  }  # = 0x1080
+          - - {field_name: tx_pktunderflow_error,                   width: 32, access_mode: RO, address_offset: 0x4300, radix_width: 36 }  # = 0x10C0
+          - - {field_name: tx_preamble_control,                     width:  1, access_mode: RW, address_offset: 0x4400                  }  # = 0x1100
+          - - {field_name: tx_pauseframe_control,                   width:  2, access_mode: RW, address_offset: 0x4500                  }  # = 0x1140
+          - - {field_name: tx_pauseframe_quanta,                    width: 16, access_mode: RW, address_offset: 0x4504                  }  # = 0x1141
+          - - {field_name: tx_pauseframe_enable,                    width:  1, access_mode: RW, address_offset: 0x4508                  }  # = 0x1142
+          # Altera is unclear about the width of the quanta registers. Assuming 32 bits, where bits 16:31 are reserved:
+          - - {field_name: pfc_pause_quanta_0,                      width: 32, access_mode: RW, address_offset: 0x4600                  }  # = 0x1180
+          - - {field_name: pfc_pause_quanta_1,                      width: 32, access_mode: RW, address_offset: 0x4604                  }  # = 0x1181
+          - - {field_name: pfc_pause_quanta_2,                      width: 32, access_mode: RW, address_offset: 0x4608                  }  # = 0x1182
+          - - {field_name: pfc_pause_quanta_3,                      width: 32, access_mode: RW, address_offset: 0x460c                  }  # = 0x1183
+          - - {field_name: pfc_pause_quanta_4,                      width: 32, access_mode: RW, address_offset: 0x4610                  }  # = 0x1184
+          - - {field_name: pfc_pause_quanta_5,                      width: 32, access_mode: RW, address_offset: 0x4614                  }  # = 0x1185
+          - - {field_name: pfc_pause_quanta_6,                      width: 32, access_mode: RW, address_offset: 0x4618                  }  # = 0x1186
+          - - {field_name: pfc_pause_quanta_7,                      width: 32, access_mode: RW, address_offset: 0x461c                  }  # = 0x1187
+          - - {field_name: pfc_holdoff_quanta_0,                    width: 32, access_mode: RW, address_offset: 0x4640                  }  # = 0x1190
+          - - {field_name: pfc_holdoff_quanta_1,                    width: 32, access_mode: RW, address_offset: 0x4644                  }  # = 0x1191
+          - - {field_name: pfc_holdoff_quanta_2,                    width: 32, access_mode: RW, address_offset: 0x4648                  }  # = 0x1192
+          - - {field_name: pfc_holdoff_quanta_3,                    width: 32, access_mode: RW, address_offset: 0x464c                  }  # = 0x1193
+          - - {field_name: pfc_holdoff_quanta_4,                    width: 32, access_mode: RW, address_offset: 0x4650                  }  # = 0x1194
+          - - {field_name: pfc_holdoff_quanta_5,                    width: 32, access_mode: RW, address_offset: 0x4654                  }  # = 0x1195
+          - - {field_name: pfc_holdoff_quanta_6,                    width: 32, access_mode: RW, address_offset: 0x4658                  }  # = 0x1196
+          - - {field_name: pfc_holdoff_quanta_7,                    width: 32, access_mode: RW, address_offset: 0x465c                  }  # = 0x1197
+          - - {field_name: tx_pfc_priority_enable,                  width:  8, access_mode: RW, address_offset: 0x4680                  }  # = 0x11A0
+          - - {field_name: tx_addrins_control,                      width:  1, access_mode: RW, address_offset: 0x4800                  }  # = 0x1200
+          - - {field_name: tx_addrins_macaddr0,                     width: 32, access_mode: RW, address_offset: 0x4804                  }  # = 0x1201
+          - - {field_name: tx_addrins_macaddr1,                     width: 16, access_mode: RW, address_offset: 0x4808                  }  # = 0x1202
+          - - {field_name: tx_frame_maxlength,                      width: 16, access_mode: RW, address_offset: 0x6004                  }  # = 0x1801
+          - - {field_name: rx_stats_clr,                            width:  1, access_mode: RW, address_offset: 0x3000                  }  # = 0x0C00
+          - - {field_name: tx_stats_clr,                            width:  1, access_mode: RW, address_offset: 0x7000                  }  # = 0x1C00
+          - - {field_name: rx_stats_framesOK,                       width: 32, access_mode: RO, address_offset: 0x3008, radix_width: 36 }  # = 0x0C02
+          - - {field_name: tx_stats_framesOK,                       width: 32, access_mode: RO, address_offset: 0x7008, radix_width: 36 }  # = 0x1C02
+          - - {field_name: rx_stats_framesErr,                      width: 32, access_mode: RO, address_offset: 0x3010, radix_width: 36 }  # = 0x0C04
+          - - {field_name: tx_stats_framesErr,                      width: 32, access_mode: RO, address_offset: 0x7010, radix_width: 36 }  # = 0x1C04
+          - - {field_name: rx_stats_framesCRCErr,                   width: 32, access_mode: RO, address_offset: 0x3018, radix_width: 36 }  # = 0x0C06
+          - - {field_name: tx_stats_framesCRCErr,                   width: 32, access_mode: RO, address_offset: 0x7018, radix_width: 36 }  # = 0x1C06
+          - - {field_name: rx_stats_octetsOK,                       width: 32, access_mode: RO, address_offset: 0x3020, radix_width: 36 }  # = 0x0C08
+          - - {field_name: tx_stats_octetsOK,                       width: 32, access_mode: RO, address_offset: 0x7020, radix_width: 36 }  # = 0x1C08
+          - - {field_name: rx_stats_pauseMACCtrl_Frames,            width: 32, access_mode: RO, address_offset: 0x3028, radix_width: 36 }  # = 0x0C0A
+          - - {field_name: tx_stats_pauseMACCtrl_Frames,            width: 32, access_mode: RO, address_offset: 0x7028, radix_width: 36 }  # = 0x1C0A
+          - - {field_name: rx_stats_ifErrors,                       width: 32, access_mode: RO, address_offset: 0x3030, radix_width: 36 }  # = 0x0C0C
+          - - {field_name: tx_stats_ifErrors,                       width: 32, access_mode: RO, address_offset: 0x7030, radix_width: 36 }  # = 0x1C0C
+          - - {field_name: rx_stats_unicast_FramesOK,               width: 32, access_mode: RO, address_offset: 0x3038, radix_width: 36 }  # = 0x0C0E
+          - - {field_name: tx_stats_unicast_FramesOK,               width: 32, access_mode: RO, address_offset: 0x7038, radix_width: 36 }  # = 0x1C0E
+          - - {field_name: rx_stats_unicast_FramesErr,              width: 32, access_mode: RO, address_offset: 0x3040, radix_width: 36 }  # = 0x0C10
+          - - {field_name: tx_stats_unicast_FramesErr,              width: 32, access_mode: RO, address_offset: 0x7040, radix_width: 36 }  # = 0x1C10
+          - - {field_name: rx_stats_multicastFramesOK,              width: 32, access_mode: RO, address_offset: 0x3048, radix_width: 36 }  # = 0x0C12
+          - - {field_name: tx_stats_multicastFramesOK,              width: 32, access_mode: RO, address_offset: 0x7048, radix_width: 36 }  # = 0x1C12
+          - - {field_name: rx_stats_multicast_FramesErr,            width: 32, access_mode: RO, address_offset: 0x3050, radix_width: 36 }  # = 0x0C14
+          - - {field_name: tx_stats_multicast_FramesErr,            width: 32, access_mode: RO, address_offset: 0x7050, radix_width: 36 }  # = 0x1C14
+          - - {field_name: rx_stats_broadcastFramesOK,              width: 32, access_mode: RO, address_offset: 0x3058, radix_width: 36 }  # = 0x0C16
+          - - {field_name: tx_stats_broadcastFramesOK,              width: 32, access_mode: RO, address_offset: 0x7058, radix_width: 36 }  # = 0x1C16
+          - - {field_name: rx_stats_broadcast_FramesErr,            width: 32, access_mode: RO, address_offset: 0x3060, radix_width: 36 }  # = 0x0C18
+          - - {field_name: tx_stats_broadcast_FramesErr,            width: 32, access_mode: RO, address_offset: 0x7060, radix_width: 36 }  # = 0x1C18
+          - - {field_name: rx_stats_etherStatsOctets,               width: 32, access_mode: RO, address_offset: 0x3068, radix_width: 36 }  # = 0x0C1A
+          - - {field_name: tx_stats_etherStatsOctets,               width: 32, access_mode: RO, address_offset: 0x7068, radix_width: 36 }  # = 0x1C1A
+          - - {field_name: rx_stats_etherStatsPkts,                 width: 32, access_mode: RO, address_offset: 0x3070, radix_width: 36 }  # = 0x0C1C
+          - - {field_name: tx_stats_etherStatsPkts,                 width: 32, access_mode: RO, address_offset: 0x7070, radix_width: 36 }  # = 0x1C1C
+          - - {field_name: rx_stats_etherStats_UndersizePkts,       width: 32, access_mode: RO, address_offset: 0x3078, radix_width: 36 }  # = 0x0C1E
+          - - {field_name: tx_stats_etherStats_UndersizePkts,       width: 32, access_mode: RO, address_offset: 0x7078, radix_width: 36 }  # = 0x1C1E
+          - - {field_name: rx_stats_etherStats_OversizePkts,        width: 32, access_mode: RO, address_offset: 0x3080, radix_width: 36 }  # = 0x0C20
+          - - {field_name: tx_stats_etherStats_OversizePkts,        width: 32, access_mode: RO, address_offset: 0x7080, radix_width: 36 }  # = 0x1C20
+          - - {field_name: rx_stats_etherStats_Pkts64Octets,        width: 32, access_mode: RO, address_offset: 0x3088, radix_width: 36 }  # = 0x0C22
+          - - {field_name: tx_stats_etherStats_Pkts64Octets,        width: 32, access_mode: RO, address_offset: 0x7088, radix_width: 36 }  # = 0x1C22
+          - - {field_name: rx_stats_etherStats_Pkts65to127Octets,   width: 32, access_mode: RO, address_offset: 0x3090, radix_width: 36 }  # = 0x0C24
+          - - {field_name: tx_stats_etherStats_Pkts65to127Octets,   width: 32, access_mode: RO, address_offset: 0x7090, radix_width: 36 }  # = 0x1C24
+          - - {field_name: rx_stats_etherStats_Pkts128to255Octets,  width: 32, access_mode: RO, address_offset: 0x3098, radix_width: 36 }  # = 0x0C26
+          - - {field_name: tx_stats_etherStats_Pkts128to255Octets,  width: 32, access_mode: RO, address_offset: 0x7098, radix_width: 36 }  # = 0x1C26
+          - - {field_name: rx_stats_etherStats_Pkts256to511Octets,  width: 32, access_mode: RO, address_offset: 0x30a0, radix_width: 36 }  # = 0x0C28
+          - - {field_name: tx_stats_etherStats_Pkts256to511Octets,  width: 32, access_mode: RO, address_offset: 0x70a0, radix_width: 36 }  # = 0x1C28
+          - - {field_name: rx_stats_etherStats_Pkts512to1023Octets, width: 32, access_mode: RO, address_offset: 0x30a8, radix_width: 36 }  # = 0x0C2A
+          - - {field_name: tx_stats_etherStats_Pkts512to1023Octets, width: 32, access_mode: RO, address_offset: 0x70a8, radix_width: 36 }  # = 0x1C2A
+          - - {field_name: rx_stats_etherStat_Pkts1024to1518Octets, width: 32, access_mode: RO, address_offset: 0x30b0, radix_width: 36 }  # = 0x0C2C
+          - - {field_name: tx_stats_etherStat_Pkts1024to1518Octets, width: 32, access_mode: RO, address_offset: 0x70b0, radix_width: 36 }  # = 0x1C2C
+          - - {field_name: rx_stats_etherStats_Pkts1519toXOctets,   width: 32, access_mode: RO, address_offset: 0x30b8, radix_width: 36 }  # = 0x0C2E
+          - - {field_name: tx_stats_etherStats_Pkts1519toXOctets,   width: 32, access_mode: RO, address_offset: 0x70b8, radix_width: 36 }  # = 0x1C2E
+          - - {field_name: rx_stats_etherStats_Fragments,           width: 32, access_mode: RO, address_offset: 0x30c0, radix_width: 36 }  # = 0x0C30
+          - - {field_name: tx_stats_etherStats_Fragments,           width: 32, access_mode: RO, address_offset: 0x70c0, radix_width: 36 }  # = 0x1C30
+          - - {field_name: rx_stats_etherStats_Jabbers,             width: 32, access_mode: RO, address_offset: 0x30c8, radix_width: 36 }  # = 0x0C32
+          - - {field_name: tx_stats_etherStats_Jabbers,             width: 32, access_mode: RO, address_offset: 0x70c8, radix_width: 36 }  # = 0x1C32
+          - - {field_name: rx_stats_etherStatsCRCErr,               width: 32, access_mode: RO, address_offset: 0x30d0, radix_width: 36 }  # = 0x0C34
+          - - {field_name: tx_stats_etherStatsCRCErr,               width: 32, access_mode: RO, address_offset: 0x70d0, radix_width: 36 }  # = 0x1C34
+          - - {field_name: rx_stats_unicastMACCtrlFrames,           width: 32, access_mode: RO, address_offset: 0x30d8, radix_width: 36 }  # = 0x0C36
+          - - {field_name: tx_stats_unicastMACCtrlFrames,           width: 32, access_mode: RO, address_offset: 0x70d8, radix_width: 36 }  # = 0x1C36
+          - - {field_name: rx_stats_multicastMAC_CtrlFrames,        width: 32, access_mode: RO, address_offset: 0x30e0, radix_width: 36 }  # = 0x0C38
+          - - {field_name: tx_stats_multicastMAC_CtrlFrames,        width: 32, access_mode: RO, address_offset: 0x70e0, radix_width: 36 }  # = 0x1C38
+          - - {field_name: rx_stats_broadcastMAC_CtrlFrames,        width: 32, access_mode: RO, address_offset: 0x30e8, radix_width: 36 }  # = 0x0C3A
+          - - {field_name: tx_stats_broadcastMAC_CtrlFrames,        width: 32, access_mode: RO, address_offset: 0x70e8, radix_width: 36 }  # = 0x1C3A
+          - - {field_name: rx_stats_PFCMACCtrlFrames,               width: 32, access_mode: RO, address_offset: 0x30f0, radix_width: 36 }  # = 0x0C3C
+          - - {field_name: tx_stats_PFCMACCtrlFrames,               width: 32, access_mode: RO, address_offset: 0x70f0, radix_width: 36 }  # = 0x1C3C
+
+
+  - peripheral_name: nw_10GbE_eth10g    # pi_nw_10GbE_eth10g.py / pi_10GbE.py
+    peripheral_description: "10GbE link status register"
+    parameters:
+      # Parameters of nw_10GbE.vhd / tr_10GbE.vhd
+      - { name: g_nof_macs, value: 1 }
+    slave_ports:
+      # MM port for reg_eth10g_mosi in ip_arria10_e1sg_eth_10g.vhd / common_reg_r_w_dc.vhd
+      - slave_name: REG_NW_10GBE_ETH10G
+        slave_type: REG
+        slave_description: ""
+        number_of_slaves: g_nof_macs
+        fields:
+          - - field_name: tx_snk_out_xon
+              field_description: ""
+              width: 1
+              bit_offset: 0
+              access_mode: RO
+              address_offset: 0x0
+          - - field_name: xgmii_tx_ready
+              field_description: ""
+              width: 1
+              bit_offset: 1
+              access_mode: RO
+              address_offset: 0x0
+          - - field_name: xgmii_link_status
+              field_description: ""
+              width: 2
+              bit_offset: 2
+              access_mode: RO
+              address_offset: 0x0
diff --git a/libraries/io/nw_10GbE/nw_10GbE_word_to_byte_address.py b/libraries/io/nw_10GbE/nw_10GbE_word_to_byte_address.py
new file mode 100644
index 0000000000000000000000000000000000000000..49a6ab205d6a9c84eb75a35c25f21d8831d07546
--- /dev/null
+++ b/libraries/io/nw_10GbE/nw_10GbE_word_to_byte_address.py
@@ -0,0 +1,120 @@
+wo = [0x0000,
+      0x0001,
+      0x0040,
+      0x0080,
+      0x00C0,
+      0x00C2,
+      0x0100,
+      0x0140,
+      0x0800,
+      0x0801,
+      0x0802,
+      0x0803,
+      0x0804,
+      0x0805,
+      0x0806,
+      0x0807,
+      0x0808,
+      0x0809,
+      0x080A,
+      0x080B,
+      0x0818,
+      0x1000,
+      0x1001,
+      0x1040,
+      0x1080,
+      0x10C0,
+      0x1100,
+      0x1140,
+      0x1141,
+      0x1142,
+
+      0x1180,
+      0x1181,
+      0x1182,
+      0x1183,
+      0x1184,
+      0x1185,
+      0x1186,
+      0x1187,
+      0x1190,
+      0x1191,
+      0x1192,
+      0x1193,
+      0x1194,
+      0x1195,
+      0x1196,
+      0x1197,
+
+      0x11A0,
+      0x1200,
+      0x1201,
+      0x1202,
+      0x1801,
+      0x0C00,
+      0x1C00,
+      0x0C02,
+      0x1C02,
+      0x0C04,
+      0x1C04,
+      0x0C06,
+      0x1C06,
+      0x0C08,
+      0x1C08,
+      0x0C0A,
+      0x1C0A,
+      0x0C0C,
+      0x1C0C,
+      0x0C0E,
+      0x1C0E,
+      0x0C10,
+      0x1C10,
+      0x0C12,
+      0x1C12,
+      0x0C14,
+      0x1C14,
+      0x0C16,
+      0x1C16,
+      0x0C18,
+      0x1C18,
+      0x0C1A,
+      0x1C1A,
+      0x0C1C,
+      0x1C1C,
+      0x0C1E,
+      0x1C1E,
+      0x0C20,
+      0x1C20,
+      0x0C22,
+      0x1C22,
+      0x0C24,
+      0x1C24,
+      0x0C26,
+      0x1C26,
+      0x0C28,
+      0x1C28,
+      0x0C2A,
+      0x1C2A,
+      0x0C2C,
+      0x1C2C,
+      0x0C2E,
+      0x1C2E,
+      0x0C30,
+      0x1C30,
+      0x0C32,
+      0x1C32,
+      0x0C34,
+      0x1C34,
+      0x0C36,
+      0x1C36,
+      0x0C38,
+      0x1C38,
+      0x0C3A,
+      0x1C3A,
+      0x0C3C,
+      0x1C3C]
+
+for a in wo:
+    #print '%x' % (a*4)                 # python v2
+    print('0x{:04x}'.format(a*4))       # python3
+