diff --git a/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd b/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd
index 9a8401456e7753a45023be5912ec77afb4eb0af7..26c9f6656e7eab03f42af23ad26e6ce03b71d75e 100644
--- a/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd
+++ b/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd
@@ -22,13 +22,21 @@
 -- Author: E. Kooistra
 -- Purpose: Unmerge each input packet into output packets of length g_pkt_len.
 -- Description:
--- . The merged packet length of the snk_in input packets must be an integer
---   multiple of g_pkt_len. The number of output packets g_nof_pkt_max is only
---   used to determine the maximum supported pkt_cnt range. The actual number
---   of output packets has to be <= g_nof_pkt_max, and is determined by input
---   packet length / g_pkt_len. Hence the dp_packet_unmerge can dynamically
---   handle different sizes of input packets, provided that their length is an
---   integer multiple of g_pkt_len.
+-- . The merged packet length of the snk_in input packets is unmerged into
+--   ceil(input packet length / pkt_len). The unmerged output packets have
+--   length pkt_len, but if input packet length mod pkt_len /= 0, then the
+--   last packet will contain the remaining data of the input packet and have
+--   length < pkt_len. Corner cases:
+--   - If pkt_len > input packet length, then the output = input
+--   - The length of the last output packet is input packet length mod
+--     pkt_len, so it can have minimal lenght 1.
+-- . The dynamic pkt_len value is captured at the input eop, or between input
+--   packets, to have a stable value during the unmerge.
+-- . The number of output packets g_nof_pkt is only used to determine the
+--   maximum supported pkt_cnt range. The actual number of output packets has
+--   to be <= g_nof_pkt, and is determined by input packet length /
+--   pkt_len. Hence the dp_packet_unmerge can dynamically handle different
+--   sizes of input packets.
 -- . The pkt_cnt is passed on as src_out.channel index.
 -- . The g_bsn_increment sets the BSN increment for the unmerged output
 --   packets relative to the BSN of the snk_in input packet. When
@@ -51,6 +59,9 @@
 --
 -- . Optional flow control dependent on g_use_ready and g_pipeline_ready, see
 --   description of dp_add_flow_control.
+-- . g_pkt_len statically sets the length of the unmerged packets in absence of
+--   dynamic pkt_len control. When the pkt_len control input is used, g_pkt_len
+--   sets the maximum number length of the unmerged packets.
 
 library IEEE,common_lib;
 use IEEE.std_logic_1164.all;
@@ -62,7 +73,7 @@ entity dp_packet_unmerge is
   generic (
     g_use_ready       : boolean := true;
     g_pipeline_ready  : boolean := false;
-    g_nof_pkt_max     : natural := 1;  -- Maximum nof packets to unmerge each incoming packet to
+    g_nof_pkt         : natural := 1;  -- Number of packets to unmerge each incoming packet to
     g_pkt_len         : natural := 1;  -- Length of the unmerged packets
     g_bsn_increment   : natural := 0
   );
@@ -70,6 +81,9 @@ entity dp_packet_unmerge is
     rst         : in  std_logic;
     clk         : in  std_logic;
 
+    pkt_len     : in  std_logic_vector(ceil_log2(g_pkt_len + 1) - 1 downto 0) := to_uvec(g_pkt_len, ceil_log2(g_pkt_len + 1));
+    pkt_len_out : out std_logic_vector(ceil_log2(g_pkt_len + 1) - 1 downto 0);  -- Valid at src_out.sop
+
     snk_out     : out t_dp_siso;
     snk_in      : in  t_dp_sosi;
 
@@ -79,20 +93,28 @@ entity dp_packet_unmerge is
 end dp_packet_unmerge;
 
 architecture rtl of dp_packet_unmerge is
+  constant c_nof_pkt_max : natural := g_nof_pkt + 1;
+  constant c_pkt_len_max : natural := g_pkt_len + 1;
+  constant c_pkt_len_w   : natural := ceil_log2(c_pkt_len_max);
+
   -- Internal state of logic function
   type t_reg is record
-    pkt_cnt     : natural range 0 to g_nof_pkt_max + 1;
-    val_cnt     : natural range 0 to g_pkt_len + 1;
+    pkt_cnt     : natural range 0 to c_nof_pkt_max;
+    pkt_len     : natural range 0 to c_pkt_len_max;
+    val_cnt     : natural range 0 to c_pkt_len_max;
+    busy        : std_logic;
     src_out     : t_dp_sosi;
   end record;
 
-  constant c_reg_rst : t_reg := (0, 0, c_dp_sosi_rst);
+  constant c_reg_rst : t_reg := (0, 0, 0, '0', c_dp_sosi_rst);
 
   signal r : t_reg;
   signal d : t_reg;
 
 begin
   -- Map logic function outputs to entity outputs
+  pkt_len_out <= to_uvec(r.pkt_len, c_pkt_len_w);
+
   u_dp_add_flow_control : entity work.dp_add_flow_control
     generic map (
       g_use_ready       => g_use_ready,
@@ -114,19 +136,19 @@ begin
   r <= d when rising_edge(clk);
 
   -- Logic function
-  p_comb : process(rst, r, snk_in)
+  p_comb : process(rst, r, snk_in, pkt_len)
     variable v : t_reg;
   begin
     -- Default
     v := r;
 
-    -- Function
-    --                   _                 _                 _
-    --   snk_in.sop   __| |_______________| |_______________| |_______________|
-    --                                  _                 _                 _
-    --   snk_in.eop   _________________| |_______________| |_______________| |_
-    --                   _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _
-    --   snk_in.valid __|
+    -- Function: unmerge input packet into output packets
+    --                    _                 _                 _
+    --   snk_in.sop    __| |_______________| |_______________| |_______________|
+    --                                   _                 _                 _
+    --   snk_in.eop    _________________| |_______________| |_______________| |_
+    --                    _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _
+    --   snk_in.valid  __|
     --   v.val_cnt        0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1
     --   v.pkt_cnt        0     1     2     0     1     2     0     1     2
     --                    ______________   _______________   _______________   _
@@ -154,6 +176,18 @@ begin
       v.pkt_cnt := r.pkt_cnt + 1;
     end if;
 
+    -- capture pkt_len between input packets when there is no unmerge busy
+    if snk_in.sop = '1' then
+      v.busy := '1';
+    end if;
+    if snk_in.eop = '1' then
+      v.busy := '0';
+    end if;
+
+    if v.busy = '0' then
+      v.pkt_len := to_uint(pkt_len);
+    end if;
+
     -- output packet bsn, sync, sop and eop
     -- . Default passes on snk_in.sync, valid, data, re, im
     -- . The sync, valid can be passed on from snk_in, without checking
@@ -173,7 +207,12 @@ begin
       if v.val_cnt = 0 then
         v.src_out.sop := '1';
       end if;
-      if v.val_cnt = g_pkt_len - 1 then
+      -- Unmerge packets of length r.pkt_len
+      if v.val_cnt = r.pkt_len - 1 then
+        v.src_out.eop := '1';
+      end if;
+      -- Unmerge last packet with length <= r.pkt_len
+      if snk_in.eop = '1' then
         v.src_out.eop := '1';
       end if;
     end if;