diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd
index 159ec45ff849820c773119940314be928f451b05..c90b46a0f50d5c28de0362a63354e65f23d12fd6 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_beamformer_output.vhd
@@ -42,6 +42,7 @@ use common_lib.common_network_layers_pkg.all;
 use dp_lib.dp_stream_pkg.all;
 use reorder_lib.reorder_pkg.all;
 use work.sdp_pkg.all;
+use work.sdp_bdo_pkg.all;
 
 entity sdp_beamformer_output is
   generic (
@@ -92,38 +93,17 @@ architecture str of sdp_beamformer_output is
   constant c_fifo_fill      : natural := c_sdp_cep_payload_nof_longwords;  -- 976
   constant c_fifo_size      : natural := true_log_pow2(c_sdp_cep_payload_nof_longwords) * c_sdp_N_beamsets;  -- 2048
 
-  -- Reorder c_nof_ch = c_nof_ch_sel = c_nof_ch_in
-  constant c_nof_blocks_per_packet : natural := c_sdp_cep_nof_blocks_per_packet;  -- = 4
-  constant c_nof_data_per_block    : natural := c_sdp_S_sub_bf;  -- = 488 dual pol beamlets
-  constant c_nof_words_per_data    : natural := 1;  -- 1 dual pol beamlet data per 32b word
-  constant c_nof_ch                : natural := c_nof_blocks_per_packet * c_nof_data_per_block * c_nof_words_per_data;  -- = 1952
-
-  -- Use c_transpose_indices and c_transpose_indices_inv for debug view in Objects window.
-  -- Use c_transpose_indices for func_reorder_transpose() in this sdp_beamformer_output,
-  -- a tb can then use c_transpose_indices_inv to undo the transpose.
-  constant c_transpose_indices     : t_natural_arr(0 to c_nof_ch - 1) :=
-                                       func_reorder_transpose_indices(c_nof_blocks_per_packet,
-                                                                      c_nof_data_per_block,
-                                                                      c_nof_words_per_data);
-  constant c_transpose_indices_inv : t_natural_arr(0 to c_nof_ch - 1) :=
-                                       func_reorder_transpose_indices(c_nof_data_per_block,
-                                                                      c_nof_blocks_per_packet,
-                                                                      c_nof_words_per_data);
-
-  -- Dynamic reorder block size control input
-  -- . The data consists of 1 word = 1 ch, because 1 word contains 1 dual pol  beamlet.
-  -- . The input packet has nof_ch of data per packet.
-  -- . The transposed output packet will have blocks with nof_blocks_per_packet
-  --   data per block and nof_data_per_block blocks per packet.
-  signal nof_ch                : natural := c_nof_ch;
-  signal nof_blocks_per_packet : natural := c_nof_blocks_per_packet;
-  signal nof_data_per_block    : natural := c_nof_data_per_block;
-  signal select_copi           : t_mem_copi := c_mem_copi_rst;
-  signal select_cipo           : t_mem_cipo := c_mem_cipo_rst;
-  signal r_identity            : t_reorder_identity;
-  signal d_identity            : t_reorder_identity;
-  signal r_transpose           : t_reorder_transpose;
-  signal d_transpose           : t_reorder_transpose;
+  -- field_sel = '0' for DP (dynamic), '1' for MM (fixed or programmable via MM of dp_offload_tx_v3)
+  constant c_cep_hdr_field_sel : std_logic_vector(c_sdp_cep_nof_hdr_fields - 1 downto 0) :=
+                                   sel_a_b(g_use_multiple_destinations, func_sdp_bdo_cep_hdr_field_sel_dest('0'),
+                                                                        func_sdp_bdo_cep_hdr_field_sel_dest('1'));
+
+  -- BDO packet size control
+  -- . One 32b word contains 1 dual pol beamlet of 4 octets (Xre, Xim, Yre, Yim).
+  -- . The transposed output packet will have nof_blocks_per_packet time slots
+  --   per beamlet and nof_beamlets_per_block dual pol beamlets per time slot.
+  signal nof_blocks_per_packet      : natural;
+  signal nof_beamlets_per_block     : natural;
 
   signal snk_in_concat              : t_dp_sosi;
   signal snk_in_concat_data         : std_logic_vector(c_data_w - 1 downto 0);
@@ -131,11 +111,8 @@ architecture str of sdp_beamformer_output is
   signal snk_in_concat_im           : std_logic_vector(c_sdp_W_beamlet - 1 downto 0);
   signal dp_repack_beamlet_src_out  : t_dp_sosi;
   signal dp_repack_beamlet_word     : t_sdp_dual_pol_beamlet_in_word;
-  signal dp_packet_merge_src_out    : t_dp_sosi;
-  signal dp_packet_merge_word       : t_sdp_dual_pol_beamlet_in_word;
   signal dp_packet_reorder_src_out  : t_dp_sosi;
   signal dp_packet_reorder_word     : t_sdp_dual_pol_beamlet_in_word;
-  signal reorder_busy               : std_logic;
   signal dp_repack_longword_src_out : t_dp_sosi;
   signal dp_repack_longword         : t_sdp_dual_pol_beamlet_in_longword;
   signal dp_fifo_fill_eop_src_out   : t_dp_sosi;
@@ -153,6 +130,11 @@ architecture str of sdp_beamformer_output is
   signal payload_err        : std_logic_vector(0 downto 0);
   signal station_info       : std_logic_vector(15 downto 0) := (others => '0');
 
+  -- Multiple destinations
+  signal eth_dst_mac        : std_logic_vector(c_network_eth_mac_addr_w - 1 downto 0);
+  signal ip_dst_addr        : std_logic_vector(c_network_ip_addr_w - 1 downto 0);
+  signal udp_dst_port       : std_logic_vector(c_network_udp_port_w - 1 downto 0);
+
   -- Default set all data path driven header fields to 0
   signal dp_offload_tx_hdr_fields : std_logic_vector(1023 downto 0) := (others => '0');
   signal dp_offload_tx_header     : t_sdp_cep_header;  -- to view dp_offload_tx_hdr_fields in Wave window
@@ -181,32 +163,34 @@ begin
     -- Force BSN error in simulation to verify payload error in
     -- tb_lofar2_unb2c_sdp_station_bf.vhd, this will cause two times payload
     -- errors, one when BSN goes wrong and one when BSN goes ok again.
-    dbg_bsn_offset <= '0';
-    if v_ref_time = 0 ns then
-      if in_sosi.sop = '1' then
-        -- Use start of input as reference time, rather than e.g. fixed 50 us,
-        -- to be independent of how long it takes for the tb to deliver the
-        -- first block.
-        v_ref_time := NOW;
-        -- Offset the v_ref_time to the second block of the
-        -- c_nof_blocks_per_packet = 4 blocks that will be merged.
-        v_ref_time := v_ref_time + c_sdp_block_period * 1 ns;
+    if g_use_multiple_destinations = false then
+      dbg_bsn_offset <= '0';
+      if v_ref_time = 0 ns then
+        if in_sosi.sop = '1' then
+          -- Use start of input as reference time, rather than e.g. fixed 50 us,
+          -- to be independent of how long it takes for the tb to deliver the
+          -- first block.
+          v_ref_time := NOW;
+          -- Offset the v_ref_time to the second block of the
+          -- c_sdp_cep_nof_blocks_per_packet = 4 blocks that will be merged.
+          v_ref_time := v_ref_time + c_sdp_block_period * 1 ns;
+        end if;
+      elsif NOW > v_ref_time + 1 * c_sdp_cep_nof_blocks_per_packet * c_sdp_block_period * 1 ns and
+            NOW < v_ref_time + 4 * c_sdp_cep_nof_blocks_per_packet * c_sdp_block_period * 1 ns then
+        -- Disturb BSN to cause merged payload error. Expected results for the
+        -- merged blocks:
+        -- . index 0 : First merged block bsn ok and payload_error = '0'.
+        -- . index 1 : bsn still ok, but payload error = '1', due to bsn++
+        --             after first block
+        -- . index 2,3 : bsn wrong due to bsn++, but payload error = '0',
+        --               because all 4 merged blocks have incrementing bsn
+        -- . index 4 : bsn still wrong due to bsn++, and payload error = '1',
+        --             because the bsn is restored after first block, so the
+        --             merged blocks do not have incrementing bsn
+        -- . index >= 5 : bsn ok and payload_error = '0'.
+        dbg_bsn_offset <= '1';
+        snk_in_concat.bsn <= INCR_UVEC(in_sosi.bsn, 1);
       end if;
-    elsif NOW > v_ref_time + 1 * c_nof_blocks_per_packet * c_sdp_block_period * 1 ns and
-          NOW < v_ref_time + 4 * c_nof_blocks_per_packet * c_sdp_block_period * 1 ns then
-      -- Disturb BSN to cause merged payload error. Expected results for the
-      -- merged blocks:
-      -- . index 0 : First merged block bsn ok and payload_error = '0'.
-      -- . index 1 : bsn still ok, but payload error = '1', due to bsn++
-      --             after first block
-      -- . index 2,3 : bsn wrong due to bsn++, but payload error = '0',
-      --               because all 4 merged blocks have incrementing bsn
-      -- . index 4 : bsn still wrong due to bsn++, and payload error = '1',
-      --             because the bsn is restored after first block, so the
-      --             merged blocks do not have incrementing bsn
-      -- . index >= 5 : bsn ok and payload_error = '0'.
-      dbg_bsn_offset <= '1';
-      snk_in_concat.bsn <= INCR_UVEC(in_sosi.bsn, 1);
     end if;
     -- synthesis translate_on
     ---------------------------------------------------------------------------
@@ -240,116 +224,64 @@ begin
   -- [0:3] = [Xre, Xim, Yre, Yim]
   dp_repack_beamlet_word <= unpack_data(dp_repack_beamlet_src_out.data(c_sdp_W_dual_pol_beamlet - 1 downto 0));
 
-  -----------------------------------------------------------------------------
-  -- dp_packet_merge
-  -----------------------------------------------------------------------------
-  u_dp_packet_merge : entity dp_lib.dp_packet_merge
-  generic map(
-    g_use_ready     => false,  -- no flow control
-    g_nof_pkt       => c_nof_blocks_per_packet,
-    g_bsn_increment => 1
-  )
-  port map(
-    rst     => dp_rst,
-    clk     => dp_clk,
-    snk_in  => dp_repack_beamlet_src_out,
-    src_out => dp_packet_merge_src_out
-  );
-
-  -- Debug signals for view in Wave window
-  dp_packet_merge_word <= unpack_data(dp_packet_merge_src_out.data(c_sdp_W_dual_pol_beamlet - 1 downto 0));
-
-  -----------------------------------------------------------------------------
-  -- reorder_col_select
-  -- . Reorder beamlet data from:
-  --     (int8) [t] [N_blocks_per_packet][S_sub_bf] [N_pol_bf][N_complex]
-  --   to:
-  --     (int8) [t] [S_sub_bf][N_blocks_per_packet] [N_pol_bf][N_complex]
-  --
-  -- . where (int8) [N_pol_bf][N_complex] = c_sdp_W_dual_pol_beamlet = 32b
-  --   dual polarization beamlet word
-  -- See tb_reorder_col_select_all.vhd for how to control col_select_copi/cipo.
-  -----------------------------------------------------------------------------
-  u_reorder_col_select : entity reorder_lib.reorder_col_select
-  generic map (
-    g_dsp_data_w  => c_sdp_W_dual_pol_beamlet / c_nof_complex,  -- = 32b / 2
-    g_nof_ch_in   => c_nof_ch,
-    g_nof_ch_sel  => c_nof_ch,
-    g_use_complex => false
-  )
-  port map (
-    dp_rst          => dp_rst,
-    dp_clk          => dp_clk,
-
-    reorder_busy    => reorder_busy,
-
-    -- Dynamic reorder block size control input
-    nof_ch_in       => nof_ch,
-    nof_ch_sel      => nof_ch,
-
-    -- Captured reorder block size control used for output_sosi
-    output_nof_ch_in  => open,
-    output_nof_ch_sel => open,
-
-    -- Memory Mapped
-    col_select_mosi => select_copi,
-    col_select_miso => select_cipo,
-
-    -- Streaming
-    input_sosi      => dp_packet_merge_src_out,
-    output_sosi     => dp_packet_reorder_src_out
-  );
+  gen_one_destination : if g_use_multiple_destinations = false generate
+    -----------------------------------------------------------------------------
+    -- Merge and reorder beamlet data for one destination from:
+    --     (int8) [t] [N_blocks_per_packet][S_sub_bf] [N_pol_bf][N_complex]
+    --   to:
+    --     (int8) [t] [S_sub_bf][N_blocks_per_packet] [N_pol_bf][N_complex]
+    --
+    -- . where (int8) [N_pol_bf][N_complex] = c_sdp_W_dual_pol_beamlet = 32b
+    --   dual polarization beamlet word
+    -----------------------------------------------------------------------------
+    u_sdp_bdo_one_destination : entity work.sdp_bdo_one_destination
+      generic map (
+        g_use_transpose => g_use_transpose
+      )
+      port map (
+        dp_clk   => dp_clk,
+        dp_rst   => dp_rst,
+
+        snk_in   => dp_repack_beamlet_src_out,
+        src_out  => dp_packet_reorder_src_out
+      );
+
+    -- Use constant defaults for beamlet data output to one destination.
+    nof_blocks_per_packet  <= c_sdp_cep_nof_blocks_per_packet;  -- = 4;
+    nof_beamlets_per_block <= c_sdp_S_sub_bf;  -- = 488 dual pol beamlets;
+  end generate;
+
+  gen_multiple_destinations : if g_use_multiple_destinations = true generate
+    -----------------------------------------------------------------------------
+    -- Merge, reorder and unmerge beamlet data for N_destinations >= 1 from:
+    --     (int8) [t] [N_blocks_per_packet][S_sub_bf / N_destinations] [N_pol_bf][N_complex]
+    --   to:
+    --     (int8) [t] [S_sub_bf / N_destinations][N_blocks_per_packet] [N_pol_bf][N_complex]
+    --
+    -- . where (int8) [N_pol_bf][N_complex] = c_sdp_W_dual_pol_beamlet = 32b
+    --   dual polarization beamlet word
+    -- . where N_destinations packets together transport the S_sub_bf beamlets.
+    -----------------------------------------------------------------------------
+    u_sdp_bdo_multiple_destinations : entity work.sdp_bdo_multiple_destinations
+      generic map (
+        g_use_transpose => g_use_transpose
+      )
+      port map (
+        dp_clk   => dp_clk,
+        dp_rst   => dp_rst,
+
+        snk_in   => dp_repack_beamlet_src_out,
+        src_out  => dp_packet_reorder_src_out
+      );
+
+    -- Use dynamic sizes for beamlet data output to multiple destination.
+    nof_blocks_per_packet  <= c_sdp_cep_nof_blocks_per_packet;  -- = 4;
+    nof_beamlets_per_block <= c_sdp_S_sub_bf;  -- = 488 dual pol beamlets;
+  end generate;
 
   -- Debug signals for view in Wave window
   dp_packet_reorder_word <= unpack_data(dp_packet_reorder_src_out.data(c_sdp_W_dual_pol_beamlet - 1 downto 0));
 
-  -- Use synchronous reset in d signals
-  p_dp_clk : process(dp_clk)
-  begin
-    if rising_edge(dp_clk) then
-      r_identity  <= d_identity;
-      r_transpose <= d_transpose;
-    end if;
-  end process;
-
-  -- Pass on beamlet data in original order or in transposed order
-  select_copi <= r_transpose.select_copi when g_use_transpose else r_identity.select_copi;
-
-  p_reorder_identity : process(dp_rst, select_cipo, nof_ch, r_identity)
-    variable v : t_reorder_identity;
-  begin
-    if select_cipo.waitrequest = '0' then
-      -- Read from reorder_col_select page
-      v := func_reorder_identity(nof_ch, r_identity);
-    else
-      -- No read, new reorder_col_select page not available yet
-      v := c_reorder_identity_rst;
-    end if;
-    -- Synchronous reset
-    if dp_rst = '1' then
-      v := c_reorder_identity_rst;
-    end if;
-    d_identity <= v;
-  end process;
-
-  p_reorder_transpose : process(dp_rst, select_cipo,
-                                nof_blocks_per_packet, nof_data_per_block, r_transpose)
-    variable v : t_reorder_transpose;
-  begin
-    if select_cipo.waitrequest = '0' then
-      -- Read from reorder_col_select page
-      v := func_reorder_transpose(nof_blocks_per_packet, nof_data_per_block, r_transpose);
-    else
-      -- No read, new reorder_col_select page not available yet
-      v := c_reorder_transpose_rst;
-    end if;
-    -- Synchronous reset
-    if dp_rst = '1' then
-      v := c_reorder_transpose_rst;
-    end if;
-    d_transpose <= v;
-  end process;
-
   -----------------------------------------------------------------------------
   -- dp_repack_data
   -- . Repack 32b -> 64b, to get 64b longwords for network packet data
@@ -378,8 +310,8 @@ begin
   -----------------------------------------------------------------------------
   -- FIFO
   -----------------------------------------------------------------------------
-  -- Pass on dp_repack_longword_src_out.err field (from u_dp_packet_merge) via
-  -- separate u_common_fifo_sc_err
+  -- Pass on dp_repack_longword_src_out.err field not here, but via separate
+  -- u_common_fifo_sc_err.
   u_dp_fifo_fill_eop_sc : entity dp_lib.dp_fifo_fill_eop_sc
   generic map (
     g_data_w         => c_longword_w,
@@ -445,7 +377,7 @@ begin
   --   where 0 = data path, 1 = MM controlled. The '0' fields are assigned here
   --   via dp_offload_tx_hdr_fields. In order:
   --     access   field
-  --     MM       eth_dst_mac
+  --     MM,DP    eth_dst_mac
   --     MM       eth_src_mac
   --     MM       eth_type
   --
@@ -460,10 +392,10 @@ begin
   --     MM       ip_protocol
   --        DP    ip_header_checksum --> added by u_tr_10GbE_ip_checksum
   --     MM       ip_src_addr
-  --     MM       ip_dst_addr
+  --     MM,DP    ip_dst_addr
   --
   --     MM       udp_src_port
-  --     MM       udp_dst_port
+  --     MM,DP    udp_dst_port
   --     MM       udp_total_length
   --        DP    udp_checksum --> default fixed 0, so not used, not calculated
   --                               here or in tr_10GbE because would require
@@ -487,38 +419,45 @@ begin
   --     MM       sdp_reserved
   --        DP    sdp_beamlet_scale
   --        DP    sdp_beamlet_index
-  --     MM       sdp_nof_blocks_per_packet
-  --     MM       sdp_nof_beamlets_per_block
+  --        DP    sdp_nof_blocks_per_packet
+  --        DP    sdp_nof_beamlets_per_block
   --        DP    sdp_block_period
   --
   --        DP    dp_bsn
 
+  station_info <= sdp_info.antenna_field_index & sdp_info.station_id;
+
   -- Use MM programmable source MAC/IP/UDP instead of source MAC/IP/UDP based
   -- on node ID. This is necessary because beamlet packets from different
   -- stations must have different source MAC/IP/UDP. Hence the eth_src_mac,
   -- udp_src_port and ip_src_addr are ignored, because c_sdp_cep_hdr_field_sel
   -- selects MM control, but keep the code to be able to enable using them by
   -- just changing the selection bit.
-
-  station_info <= sdp_info.antenna_field_index & sdp_info.station_id;
-
   dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "eth_src_mac" ) downto field_lo(c_sdp_cep_hdr_field_arr, "eth_src_mac" )) <= eth_src_mac;
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "udp_src_port") downto field_lo(c_sdp_cep_hdr_field_arr, "udp_src_port")) <= udp_src_port;
   dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "ip_src_addr" ) downto field_lo(c_sdp_cep_hdr_field_arr, "ip_src_addr" )) <= ip_src_addr;
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "udp_src_port") downto field_lo(c_sdp_cep_hdr_field_arr, "udp_src_port")) <= udp_src_port;
 
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_observation_id"                      ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_observation_id"                      )) <= sdp_info.observation_id;
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_station_info"                        ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_station_info"                        )) <= station_info;
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_antenna_band_id"         ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_source_info_antenna_band_id"         )) <= SLV(sdp_info.antenna_band_index);
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_nyquist_zone_id"         ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_source_info_nyquist_zone_id"         )) <= sdp_info.nyquist_zone_index;
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_f_adc"                   ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_source_info_f_adc"                   )) <= SLV(sdp_info.f_adc);
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_fsub_type"               ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_source_info_fsub_type"               )) <= SLV(sdp_info.fsub_type);
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_payload_error"           ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_source_info_payload_error"           )) <= payload_err;
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_beam_repositioning_flag" ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_source_info_beam_repositioning_flag" )) <= SLV(sdp_info.beam_repositioning_flag);
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_gn_id"                   ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_source_info_gn_id"                   )) <= gn_id;
-
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_beamlet_scale" ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_beamlet_scale" )) <= beamlet_scale;
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_beamlet_index" ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_beamlet_index" )) <= TO_UVEC(c_beamlet_index, c_halfword_w);
-  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_block_period"  ) downto field_lo(c_sdp_cep_hdr_field_arr,  "sdp_block_period"  )) <= sdp_info.block_period;
+  -- Use MM programmable destination MAC/IP/UDP from dp_offload_tx_v3 for one destination
+  -- Use DP programmable destination MAC/IP/UDP from sdp_bdo_destinations_reg for multiple destinations
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "eth_dst_mac" ) downto field_lo(c_sdp_cep_hdr_field_arr, "eth_dst_mac" )) <= eth_dst_mac;
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "ip_dst_addr" ) downto field_lo(c_sdp_cep_hdr_field_arr, "ip_dst_addr" )) <= ip_dst_addr;
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "udp_dst_port") downto field_lo(c_sdp_cep_hdr_field_arr, "udp_dst_port")) <= udp_dst_port;
+
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_observation_id"                     ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_observation_id"                     )) <= sdp_info.observation_id;
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_station_info"                       ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_station_info"                       )) <= station_info;
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_antenna_band_id"        ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_antenna_band_id"        )) <= SLV(sdp_info.antenna_band_index);
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_nyquist_zone_id"        ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_nyquist_zone_id"        )) <= sdp_info.nyquist_zone_index;
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_f_adc"                  ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_f_adc"                  )) <= SLV(sdp_info.f_adc);
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_fsub_type"              ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_fsub_type"              )) <= SLV(sdp_info.fsub_type);
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_payload_error"          ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_payload_error"          )) <= payload_err;
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_beam_repositioning_flag") downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_beam_repositioning_flag")) <= SLV(sdp_info.beam_repositioning_flag);
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_source_info_gn_id"                  ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_source_info_gn_id"                  )) <= gn_id;
+
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_beamlet_scale"         ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_beamlet_scale"         )) <= beamlet_scale;
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_beamlet_index"         ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_beamlet_index"         )) <= TO_UVEC(c_beamlet_index, c_halfword_w);
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_nof_blocks_per_packet" ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_nof_blocks_per_packet" )) <= TO_UVEC(nof_blocks_per_packet, c_octet_w);
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_nof_beamlets_per_block") downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_nof_beamlets_per_block")) <= TO_UVEC(nof_beamlets_per_block, c_halfword_w);
+  dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "sdp_block_period"          ) downto field_lo(c_sdp_cep_hdr_field_arr, "sdp_block_period"          )) <= sdp_info.block_period;
 
   dp_offload_tx_hdr_fields(field_hi(c_sdp_cep_hdr_field_arr, "dp_bsn" ) downto field_lo(c_sdp_cep_hdr_field_arr, "dp_bsn" )) <= dp_pipeline_src_out.bsn(63 downto 0);
 
@@ -534,7 +473,7 @@ begin
     g_data_w        => c_longword_w,
     g_symbol_w      => c_byte_w,
     g_hdr_field_arr => c_sdp_cep_hdr_field_arr,
-    g_hdr_field_sel => c_sdp_cep_hdr_field_sel,
+    g_hdr_field_sel => c_cep_hdr_field_sel,
     g_pipeline_ready => true
   )
   port map (