diff --git a/applications/apertif/designs/apertif_unb1_correlator/src/vhdl/apertif_unb1_correlator_pkg.vhd b/applications/apertif/designs/apertif_unb1_correlator/src/vhdl/apertif_unb1_correlator_pkg.vhd
index e4f2644dfa8e1773a9335b7266322436bccfd6e0..a37a81f51e236d9bbbbfece8d3cfd585c7b91b89 100644
--- a/applications/apertif/designs/apertif_unb1_correlator/src/vhdl/apertif_unb1_correlator_pkg.vhd
+++ b/applications/apertif/designs/apertif_unb1_correlator/src/vhdl/apertif_unb1_correlator_pkg.vhd
@@ -23,8 +23,14 @@
 LIBRARY IEEE, common_lib;
 USE IEEE.STD_LOGIC_1164.ALL;
 USE common_lib.common_pkg.ALL;
+USE common_lib.common_str_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
 
 PACKAGE apertif_unb1_correlator_pkg IS  
+
+  -----------------------------------------------------------------------------
+  -- Revision control
+  -----------------------------------------------------------------------------
   
   -- Revision configuration record for apertif_unb1_correlator. 
   TYPE t_apertif_unb1_correlator_config IS RECORD 
@@ -89,6 +95,61 @@ PACKAGE apertif_unb1_correlator_pkg IS
   -- Function to select the revision configuration. 
   FUNCTION func_sel_revision_rec(g_design_name : STRING) RETURN t_apertif_unb1_correlator_config;
 
+
+  -----------------------------------------------------------------------------
+  -- Derive visibility packet size
+  -----------------------------------------------------------------------------
+
+  TYPE t_apertif_unb1_correlator_packet_info IS RECORD 
+    vis_header_size       : NATURAL;
+    vis_payload_size      : NATURAL;
+    vis_payload_nof_bits  : NATURAL;
+    vis_packet_size       : NATURAL;
+    eth_tail_size         : NATURAL;
+    eth_gap_size          : NATURAL;
+    eth_packet_size       : NATURAL;
+    eth_packet_nof_bits   : NATURAL;
+    eth_packet_nof_dp_clk : NATURAL;
+    eth_packet_overhead   : REAL;
+  END RECORD;
+
+  FUNCTION func_apertif_unb1_correlator_packet_info(nof_visibilities : NATURAL;
+                                                    f_link           : REAL;
+                                                    f_dp_clk         : REAL) RETURN t_apertif_unb1_correlator_packet_info;
+
+  FUNCTION func_apertif_unb1_correlator_log_packet_info(pinfo : t_apertif_unb1_correlator_packet_info) RETURN BOOLEAN;
+
+  -----------------------------------------------------------------------------
+  -- Check inter channel delay
+  -----------------------------------------------------------------------------
+
+  FUNCTION func_apertif_unb1_correlator_inter_channel_delay_max(block_period          : NATURAL;
+                                                                nof_blocks_per_sync   : NATURAL;
+                                                                nof_beamlets          : NATURAL;
+                                                                nof_channels          : NATURAL;
+                                                                nof_visibilities      : NATURAL) RETURN INTEGER;
+                                        
+  FUNCTION func_apertif_unb1_correlator_inter_channel_delay_min(pinfo            : t_apertif_unb1_correlator_packet_info;
+                                                                nof_visibilities : NATURAL) RETURN INTEGER;
+
+  FUNCTION func_apertif_unb1_correlator_verify_inter_channel_delay(inter_channel_delay     : NATURAL;
+                                                                   inter_channel_delay_max : INTEGER;
+                                                                   inter_channel_delay_min : INTEGER) RETURN BOOLEAN;
+  
+  FUNCTION func_apertif_unb1_correlator_log_inter_channel_delay(inter_channel_delay     : NATURAL;
+                                                                inter_channel_delay_max : INTEGER;
+                                                                inter_channel_delay_min : INTEGER) RETURN BOOLEAN;
+
+  -- Combine derive visibility packet size and check inter channel delay
+  FUNCTION func_apertif_unb1_correlator_verify_and_log_output_rate(inter_channel_delay   : NATURAL;
+                                                                   block_period          : NATURAL;
+                                                                   nof_blocks_per_sync   : NATURAL;
+                                                                   nof_beamlets          : NATURAL;
+                                                                   nof_channels          : NATURAL;
+                                                                   nof_visibilities      : NATURAL;
+                                                                   f_link                : REAL;
+                                                                   f_dp_clk              : REAL) RETURN BOOLEAN;
+                                        
 END apertif_unb1_correlator_pkg;
 
 PACKAGE BODY apertif_unb1_correlator_pkg IS
@@ -116,34 +177,156 @@ PACKAGE BODY apertif_unb1_correlator_pkg IS
     END IF;
   END; 
   
+  -- visibility packet size
+  FUNCTION func_apertif_unb1_correlator_packet_info(nof_visibilities : NATURAL;
+                                                    f_link           : REAL;
+                                                    f_dp_clk         : REAL) RETURN t_apertif_unb1_correlator_packet_info IS
+    VARIABLE v : t_apertif_unb1_correlator_packet_info;
+  BEGIN
+    -- size in number of 32b words
+    v.vis_header_size       := 21;  -- (pad(2) + eth(14) + ip(20) + udp(8) + app_id(16) + app_flags(24)) / 4 = 84 bytes / 4 = 21 words
+    v.vis_payload_size      := nof_visibilities * c_nof_complex;
+    v.vis_payload_nof_bits  := v.vis_payload_size * c_32;
+    v.vis_packet_size       := v.vis_header_size + v.vis_payload_size;
+    -- account for ethernet overhead
+    v.eth_tail_size         := 1;  -- for the eth CRC word
+    v.eth_gap_size          := c_network_eth_gap_len * c_8 / c_32;  -- = 3 words for some idle time between packets
+    v.eth_packet_size       := v.vis_packet_size + v.eth_tail_size + v.eth_gap_size;
+    -- express ethernet packet time in effective number of bits on the link and in equivalent number of dp_clk cycles
+    v.eth_packet_nof_bits   := v.eth_packet_size * c_32;
+    v.eth_packet_nof_dp_clk := NATURAL(REAL(v.eth_packet_nof_bits) * f_dp_clk / f_link);
+    -- Calculate ethernet packet overhead compared to visibility payload due to header, tail and interpacket gap
+    v.eth_packet_overhead   := REAL(v.eth_packet_nof_bits) / REAL(v.vis_payload_nof_bits);
+    RETURN v;
+  END;
+  
+
+  FUNCTION func_apertif_unb1_correlator_log_packet_info(pinfo : t_apertif_unb1_correlator_packet_info) RETURN BOOLEAN IS
+  BEGIN
+    -- Log packet size 
+    print_str("###############################################################################");
+    print_str("# func_apertif_unb1_correlator_log_packet_info:");
+    print_str(". vis_header_size       = " &  int_to_str(pinfo.vis_header_size));
+    print_str(". vis_payload_size      = " &  int_to_str(pinfo.vis_payload_size));
+    print_str(". vis_payload_nof_bits  = " &  int_to_str(pinfo.vis_payload_nof_bits));
+    print_str(". vis_packet_size       = " &  int_to_str(pinfo.vis_packet_size));
+    print_str(". eth_tail_size         = " &  int_to_str(pinfo.eth_tail_size));
+    print_str(". eth_gap_size          = " &  int_to_str(pinfo.eth_gap_size));
+    print_str(". eth_packet_size       = " &  int_to_str(pinfo.eth_packet_size));
+    print_str(". eth_packet_nof_bits   = " &  int_to_str(pinfo.eth_packet_nof_bits));
+    print_str(". eth_packet_nof_dp_clk = " &  int_to_str(pinfo.eth_packet_nof_dp_clk));
+    print_str(". eth_packet_overhead   = " & real_to_str(pinfo.eth_packet_overhead, 7, 5));
+    print_str("");
+    RETURN TRUE;
+  END;
+
   -- inter_channel_delay:
   -- . determines gaps between correlator output packets. 
   -- . This produces an even (non-bursting) output rate on the 1GbE interface.
 
   -- 300 visibilities interleaved onto 150 streams @ 200MHz * 64b =  1920 Gbps without integration
-  -- . With 800000 samples per 64 channels integration (=12500 samples/channel): 1920 Gbps/ 12500 = 0.1536 Gbps (256 beamlets) or 0.1056 Gbps (176 beamlets)
-  -- ==============================================================
-  -- Inter channel delay   Bus rate during visibility buffer output
-  --                   0   12.8 Gbps
-  --                 300    6.4
-  --               3*300    3.2
-  --               7*300    1.6
-  --              15*300    0.8
-  --              31*300    0.4
-  --              63*300    0.2 <-- OK
-
-  -- 36 visibilities interleaved onto 18 streams @ 200MHz * 64b = 230.4 Gbps without integration
-  -- . With 20480 samples per 64 channels integration (320= samples/channel): 230.4 Gbps/ 320 = 0.72 Gbps (256 beamlets) or 0.495 Gbps (176 beamlets)
+  -- . The minimim capacity needed with 800000 samples per 64 channels integration (=12500 samples/channel) is
+  --   1920 Gbps/ 12500 = 0.1536 Gbps (256 beamlets) or 0.1056 Gbps (176 beamlets in 8 bit beamlet mode) or
+  --   0.144 Gbps (240 beamlets in 6 bit beamlet mode)
+  -- . The maximum capacity of the link is determined by the 2 * 10GbE to the data writer, so per PN that is
+  --   20G/128 = 0.15625 Gbps
+  
   -- ==============================================================
+  -- The table below shows the inter channel delay in units of 300 visibilities, because a visibilities payload
+  -- contains 300 visibilities. The packet is represented by 1 * 300 and the inter channel delay by (n-1) * 300,
+  -- so then the output visibility data rate becomes 12.8G / n.
+  --
   -- Inter channel delay   Bus rate during visibility buffer output
-  --                   0   12.8 Gbps
-  --                  36    6.4
-  --                3*36    3.2
-  --                7*36    1.6
-  --               15*36    0.8
-  --               31*36    0.4 <-- Too slow as our average is 0.495
-  --               23*36    0.533 <-- OK
+  --                   0   12.8 Gbps   = 64b * 200MHz
+  --                 300    6.4        = 12.8G/2
+  --               3*300    3.2        = 12.8G/4
+  --               7*300    1.6        = 12.8G/8
+  --              15*300    0.8        = 12.8G/16
+  --              31*300    0.4        = 12.8G/32
+  --              63*300    0.2        = 12.8G/64 > 0.156.25 Gbps, so too large for the available link capacity
+  --             127*300    0.1        = 12.8G/128 < 0.144 Gbps, so too small for the required capacity
+  -- 
+  -- From the available link capacity 0.15625 Gbps it follows that the minimal n = 12.8G / 0.15625 G = 81.92
+  -- and c_inter_channel_delay_min = 24576.
+  -- Choose a required capacity of 0.144 Gbps to fit both 8 bit and 6 bit beamlet mode, however due to packet
+  -- overhead the required capacity needs to be about 4.2 % more than for the payload data alone. This packet
+  -- overhead can be accounted for by increasing the required link capacity by 1.042, so then
+  -- n = 12.8 / (0.144 * 1.042) = 85.3 and c_inter_channel_delay_max = 25591.
+  -- Use func_apertif_unb1_correlator_inter_channel_delay_max/min() to more accurately determine the min,max
+  -- range for c_inter_channel_delay. This yields 25300 < c_inter_channel_delay < 26366.
+
+  FUNCTION func_apertif_unb1_correlator_inter_channel_delay_max(block_period          : NATURAL;
+                                                                nof_blocks_per_sync   : NATURAL;
+                                                                nof_beamlets          : NATURAL;
+                                                                nof_channels          : NATURAL;
+                                                                nof_visibilities      : NATURAL) RETURN INTEGER IS
+    -- Derive maximum inter_channel_delay from required visibility data rate
+    CONSTANT c_nof_clk_per_sync         : NATURAL := nof_blocks_per_sync * block_period;
+    CONSTANT c_vis_nof_packets_per_sync : NATURAL := nof_beamlets * nof_channels;
+    CONSTANT c_inter_channel_delay_max  : INTEGER := c_nof_clk_per_sync / c_vis_nof_packets_per_sync - nof_visibilities;
+  BEGIN
+    RETURN c_inter_channel_delay_max;
+  END;
+  
+  FUNCTION func_apertif_unb1_correlator_inter_channel_delay_min(pinfo            : t_apertif_unb1_correlator_packet_info;
+                                                                nof_visibilities : NATURAL) RETURN INTEGER IS
+    -- Derive minimum inter_channel_delay from avaliable link data rate (independent of nof_beamlets, because the
+    -- burst rate is the same)
+    CONSTANT c_inter_channel_delay_min  : INTEGER := pinfo.eth_packet_nof_dp_clk - nof_visibilities;
+  BEGIN
+    RETURN c_inter_channel_delay_min;
+  END;
+  
+  FUNCTION func_apertif_unb1_correlator_verify_inter_channel_delay(inter_channel_delay     : NATURAL;
+                                                                   inter_channel_delay_max : INTEGER;
+                                                                   inter_channel_delay_min : INTEGER) RETURN BOOLEAN IS
+  BEGIN
+    -- Verify inter channel delay
+    ASSERT (inter_channel_delay >= inter_channel_delay_min) AND (inter_channel_delay <= inter_channel_delay_max)
+      REPORT  "Inter channel delay " & int_to_str(inter_channel_delay) &
+                      " must be >= " & int_to_str(inter_channel_delay_min) &
+                          " and <= " & int_to_str(inter_channel_delay_max)
+      SEVERITY FAILURE;
+    RETURN TRUE;
+  END;
+  
+  FUNCTION func_apertif_unb1_correlator_log_inter_channel_delay(inter_channel_delay     : NATURAL;
+                                                                inter_channel_delay_max : INTEGER;
+                                                                inter_channel_delay_min : INTEGER) RETURN BOOLEAN IS
+  BEGIN
+    -- Log inter channel delay
+    print_str("###############################################################################");
+    print_str("# func_apertif_unb1_correlator_log_inter_channel_delay:");
+    print_str(". Inter channel delay = " & int_to_str(inter_channel_delay));
+    print_str("              Minimum = " & int_to_str(inter_channel_delay_min));
+    print_str("              Maximum = " & int_to_str(inter_channel_delay_max));
+    print_str("");
+    RETURN TRUE;
+  END;
  
+  FUNCTION func_apertif_unb1_correlator_verify_and_log_output_rate(inter_channel_delay   : NATURAL;
+                                                                   block_period          : NATURAL;
+                                                                   nof_blocks_per_sync   : NATURAL;
+                                                                   nof_beamlets          : NATURAL;
+                                                                   nof_channels          : NATURAL;
+                                                                   nof_visibilities      : NATURAL;
+                                                                   f_link                : REAL;
+                                                                   f_dp_clk              : REAL) RETURN BOOLEAN IS
+    CONSTANT c_pinfo : t_apertif_unb1_correlator_packet_info := func_apertif_unb1_correlator_packet_info(nof_visibilities, f_link, f_dp_clk);
+    CONSTANT c_max   : INTEGER := func_apertif_unb1_correlator_inter_channel_delay_max(block_period,
+                                                                                       nof_blocks_per_sync,
+                                                                                       nof_beamlets,
+                                                                                       nof_channels,
+                                                                                       nof_visibilities);
+    CONSTANT c_min   : INTEGER := func_apertif_unb1_correlator_inter_channel_delay_min(c_pinfo,
+                                                                                       nof_visibilities);
+    VARIABLE v_bool  : BOOLEAN;
+  BEGIN
+    IF func_apertif_unb1_correlator_verify_inter_channel_delay(inter_channel_delay, c_max, c_min) THEN
+      v_bool := func_apertif_unb1_correlator_log_packet_info(c_pinfo);
+      v_bool := func_apertif_unb1_correlator_log_inter_channel_delay(inter_channel_delay, c_max, c_min);
+    END IF;
+    RETURN TRUE;
+  END;
+                                                                                     
 END apertif_unb1_correlator_pkg;
-
-