diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd
index 9490efb8b0dee55a582acceef05f50a17bc198af..bf435936327d4cec914de36843cdb0103dccb0c9 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_bdo_multiple_destinations.vhd
@@ -22,7 +22,8 @@
 -- Purpose:
 --   Construct beamformer data output (BDO) payloads for multiple destinations.
 -- Description:
---   Merge, reorder and unmerge beamlet data for N_destinations > 1 from:
+-- * Get N_destinations from sdp_bdo_destinations_reg.
+-- * 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]
@@ -50,41 +51,75 @@ entity sdp_bdo_multiple_destinations is
     g_use_transpose : boolean := false
   );
   port (
+    mm_clk   : in  std_logic;
+    mm_rst   : in  std_logic;
+
     dp_clk   : in  std_logic;
     dp_rst   : in  std_logic;
 
+    reg_destinations_copi : in  t_mem_copi;
+    reg_destinations_cipo : out t_mem_cipo;
+
+    destinations_info     : out t_sdp_bdo_destinations_info;
+
     snk_in   : in  t_dp_sosi;
     src_out  : out t_dp_sosi
   );
 end sdp_bdo_multiple_destinations;
 
 architecture str of sdp_bdo_multiple_destinations is
-  -- 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_beamlets_per_block : natural := c_sdp_S_sub_bf;  -- = 488 dual pol beamlets
   constant c_nof_words_per_beamlet  : natural := 1;  -- 1 dual pol beamlet data per 32b word
-  constant c_nof_ch                 : natural := c_nof_blocks_per_packet * c_nof_beamlets_per_block * c_nof_words_per_beamlet;  -- = 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_bdo_multiple_destinations,
-  -- 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_beamlets_per_block,
-                                                                      c_nof_words_per_beamlet);
-  constant c_transpose_indices_inv : t_natural_arr(0 to c_nof_ch - 1) :=
-                                       func_reorder_transpose_indices(c_nof_beamlets_per_block,
-                                                                      c_nof_blocks_per_packet,
-                                                                      c_nof_words_per_beamlet);
-
-  -- 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_beamlets_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_beamlets_per_block : natural := c_nof_beamlets_per_block;
+
+  -- Reorder c_nof_ch = c_nof_ch_sel = c_nof_ch_in
+  constant c_reorder_nof_blocks_max : natural := c_sdp_bdo_reorder_nof_blocks_max;  -- = 16
+  constant c_reorder_nof_blocks_w   : natural := ceil_log2(c_reorder_nof_blocks_max + 1);
+  constant c_reorder_nof_ch_max     : natural := c_reorder_nof_blocks_max *
+                                                 c_nof_beamlets_per_block *
+                                                 c_nof_words_per_beamlet;  -- = 7808
+
+  -- Look up table constants as function of N_destinations
+  constant c_m                                               : natural := c_sdp_bdo_nof_destinations_max;  -- 16
+  constant c_nof_blocks_per_packet_arr                       : t_natural_arr(1 to c_m) := func_sdp_bdo_nof_blocks_per_packet_look_up_table;
+  constant c_reorder_nof_blocks_arr                          : t_natural_arr(1 to c_m) := func_sdp_bdo_reorder_nof_blocks_look_up_table;
+  constant c_reorder_nof_ch_arr                              : t_natural_arr(1 to c_m) := func_sdp_bdo_reorder_nof_ch_look_up_table;
+  constant c_nof_beamlets_per_block_first_destination_arr    : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_beamlets_per_block_first_destination_look_up_table;
+  constant c_nof_beamlets_per_block_last_destination_arr     : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_beamlets_per_block_last_destination_look_up_table;
+  constant c_sdp_sdo_nof_ch_per_packet_first_destination_arr : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_ch_per_packet_first_destination_look_up_table;
+  constant c_sdp_sdo_nof_ch_per_packet_last_destination_arr  : t_natural_arr(1 to c_m) := func_sdp_sdo_nof_ch_per_packet_last_destination_look_up_table;
+
+  constant c_beamlet_index_per_destination_mat : t_natural_matrix(1 to c_m, 0 to c_m - 1) :=
+                                                   func_sdp_sdo_beamlet_index_per_destination_look_up_matrix;
+
+--  -- 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_bdo_multiple_destinations,
+--  -- 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_beamlets_per_block,
+--                                                                      c_nof_words_per_beamlet);
+--  constant c_transpose_indices_inv : t_natural_arr(0 to c_nof_ch - 1) :=
+--                                       func_reorder_transpose_indices(c_nof_beamlets_per_block,
+--                                                                      c_nof_blocks_per_packet,
+--                                                                      c_nof_words_per_beamlet);
+
+  signal i_destinations_info     : t_sdp_bdo_destinations_info;
+
+  -- Dynamic merge, reorder, unmerge packet sizes
+  -- . default use values for N_destinations = 1
+  signal nof_blocks_per_packet                    : natural := c_nof_blocks_per_packet_arr(1);
+  signal reorder_nof_blocks                       : natural := c_reorder_nof_blocks_arr(1);
+  signal reorder_nof_blocks_slv                   : std_logic_vector(c_reorder_nof_blocks_w - 1 downto 0);
+  signal reorder_nof_ch                           : natural := c_reorder_nof_ch_arr(1);
+  signal nof_beamlets_per_block_first_destination : natural := c_nof_beamlets_per_block_first_destination_arr(1);
+  signal nof_beamlets_per_block_last_destination  : natural := c_nof_beamlets_per_block_last_destination_arr(1);
+  signal nof_beamlets_per_block                   : natural;
+  signal nof_ch_per_packet_first_destination      : natural := c_sdp_sdo_nof_ch_per_packet_first_destination_arr(1);
+  signal nof_ch_per_packet_last_destination       : natural := c_sdp_sdo_nof_ch_per_packet_last_destination_arr(1);
+  -- . default use values for N_destinations = 1 and destination index = 0
+  signal beamlet_index_per_destination            : natural := c_beamlet_index_per_destination_mat(1, 0);
+
   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;
@@ -97,21 +132,74 @@ architecture str of sdp_bdo_multiple_destinations is
   signal reorder_src_out        : t_dp_sosi;
   signal reorder_word           : t_sdp_dual_pol_beamlet_in_word;
   signal reorder_busy           : std_logic;
+  signal unmerge_src_out        : t_dp_sosi;
+  signal unmerge_word           : t_sdp_dual_pol_beamlet_in_word;
 begin
-  src_out <= reorder_src_out;
+  src_out <= unmerge_src_out;
+  destinations_info <= i_destinations_info;
+
+  -----------------------------------------------------------------------------
+  -- Multiple destinations info register
+  -----------------------------------------------------------------------------
+  -- Use dynamic sizes for beamlet data output to multiple destination.
+  u_sdp_bdo_destinations_reg : entity work.sdp_bdo_destinations_reg
+    port map (
+      -- Clocks and reset
+      mm_clk   => mm_clk,
+      mm_rst   => mm_rst,
+
+      dp_clk   => dp_clk,
+      dp_rst   => dp_rst,
+
+      reg_copi => reg_destinations_copi,
+      reg_cipo => reg_destinations_cipo,
+
+      -- sdp info
+      destinations_info => i_destinations_info
+    );
+
+  -----------------------------------------------------------------------------
+  -- Multiple destinations info look up values
+  -----------------------------------------------------------------------------
+  -- Pipeline values from look up tables to ease timing closure
+  p_pipeline : process(dp_clk)
+    variable v_DN : natural;  -- number of destinations
+    variable v_DI : natural;  -- destination index
+  begin
+    if rising_edge(dp_clk) then
+      v_DN := i_destinations_info.nof_destinations_act;
+      nof_blocks_per_packet                    <= i_destinations_info.nof_blocks_per_packet_act;
+      reorder_nof_blocks                       <= c_reorder_nof_blocks_arr(v_DN);
+      reorder_nof_ch                           <= c_reorder_nof_ch_arr(v_DN);
+      nof_beamlets_per_block_first_destination <= c_nof_beamlets_per_block_first_destination_arr(v_DN);
+      nof_beamlets_per_block_last_destination  <= c_nof_beamlets_per_block_last_destination_arr(v_DN);
+      v_DI := 0;
+      beamlet_index_per_destination            <= c_beamlet_index_per_destination_mat(v_DN, v_DI);
+    end if;
+  end process;
+
+  nof_beamlets_per_block <= nof_beamlets_per_block_first_destination;
 
   -----------------------------------------------------------------------------
   -- dp_packet_merge
   -----------------------------------------------------------------------------
+  -- Use slv in port map to avoid vcom-1436: Actual expression (function call
+  -- "TO_UVEC") of formal "nof_pkt" is not globally static.
+  reorder_nof_blocks_slv <= to_uvec(reorder_nof_blocks, c_reorder_nof_blocks_w);
+
   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_nof_pkt       => c_reorder_nof_blocks_max,
       g_bsn_increment => 1
     )
     port map(
       rst     => dp_rst,
       clk     => dp_clk,
+
+      nof_pkt     => reorder_nof_blocks_slv,
+      nof_pkt_out => open,  -- Valid at src_out.sop
+
       snk_in  => snk_in,
       src_out => merge_src_out
     );
@@ -127,8 +215,8 @@ begin
   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_nof_ch_in   => c_reorder_nof_ch_max,
+      g_nof_ch_sel  => c_reorder_nof_ch_max,
       g_use_complex => false
     )
     port map (
@@ -138,8 +226,8 @@ begin
       reorder_busy    => reorder_busy,
 
       -- Dynamic reorder block size control input
-      nof_ch_in       => nof_ch,
-      nof_ch_sel      => nof_ch,
+      nof_ch_in       => reorder_nof_ch,
+      nof_ch_sel      => reorder_nof_ch,
 
       -- Captured reorder block size control used for output_sosi
       output_nof_ch_in  => open,
@@ -169,12 +257,12 @@ begin
   -- 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)
+  p_reorder_identity : process(dp_rst, select_cipo, reorder_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);
+      v := func_reorder_identity(reorder_nof_ch, r_identity);
     else
       -- No read, new reorder_col_select page not available yet
       v := c_reorder_identity_rst;
@@ -202,4 +290,29 @@ begin
     end if;
     d_transpose <= v;
   end process;
+
+  -----------------------------------------------------------------------------
+  -- dp_packet_unmerge for N_destinations
+  -----------------------------------------------------------------------------
+  u_dp_packet_unmerge : entity dp_lib.dp_packet_unmerge
+    generic map (
+      g_use_ready       => false,  -- no flow control
+      g_nof_pkt_max     => c_reorder_nof_blocks_max,
+      g_pkt_len         => 99,  -- Length of the unmerged packets
+      g_bsn_increment   => 1
+    )
+    port map (
+      rst     => dp_rst,
+      clk     => dp_clk,
+
+      snk_in      => reorder_src_out,
+      src_out     => unmerge_src_out
+    );
+
+    -- TODO:
+    -- . add dynamic pkt_len input port
+    -- . support unmerge of pkt_len and remaining last packet shorter than pkt_len.
+
+  -- Debug signals for view in Wave window
+  unmerge_word <= unpack_data(unmerge_src_out.data(c_sdp_W_dual_pol_beamlet - 1 downto 0));
 end str;