diff --git a/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd
index 8ec87e33d5e660fcffebb90920322adf73704d99..f661fdbf53d60631f26d0328690dd4269fcf177e 100644
--- a/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd
+++ b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd
@@ -39,6 +39,10 @@
 --     a gap between blocks the dp_fifo_fill_eop needs 1 cycle to process a block.
 --     Streaming without gaps may cause the fifo to overflow. Bursts of blocks
 --     can be handled by increasing g_fifo_size.
+--   . g_max/min_block_size indicate the minimum / maximum length of incoming blocks.
+--     The ratio of max / min is used to determine a fifo size for the outgoing
+--     sosi.valid signals. To minimize logic the g_min_block_size can be set to
+--     the expected minimum block size.
 -------------------------------------------------------------------------------
 -- REGMAP
 -------------------------------------------------------------------------------
diff --git a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd
index 955bb5968ff5487340784c8025c9f4f5c1667e7e..74776150ed3d99824cde735d1f16483cae61616b 100644
--- a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd
+++ b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd
@@ -32,6 +32,10 @@
 --   after the fifo has been filled sufficiently, a frame is also available when
 --   the in_eop has been received earlier than the specified g_fifo_fill. For
 --   more details, please consult the description of dp_fill_fifo_core.
+-- Remark:
+--   . dp_fifo_fill_eop needs 1 clock cycle gap between eop and sop to process
+--     the block. Therefore it cannot handle contious streams without gaps. It
+--     can handle bursts by increasing g_fifo_size.
 -------------------------------------------------------------------------------
 
 LIBRARY IEEE, common_lib, technology_lib;
diff --git a/libraries/base/dp/src/vhdl/dp_offload_rx.vhd b/libraries/base/dp/src/vhdl/dp_offload_rx.vhd
index 37fe038a0f9641d39c805dea801b4abba307403b..9effa4c7f350bc97dcadd99b59682feabad782f9 100644
--- a/libraries/base/dp/src/vhdl/dp_offload_rx.vhd
+++ b/libraries/base/dp/src/vhdl/dp_offload_rx.vhd
@@ -32,8 +32,8 @@ ENTITY dp_offload_rx IS
     g_nof_streams   : NATURAL;
     g_data_w        : NATURAL;
     g_hdr_field_arr : t_common_field_arr;
-    g_remove_crc    : BOOLEAN;
-    g_crc_nof_words : NATURAL
+    g_remove_crc    : BOOLEAN := FALSE;
+    g_crc_nof_words : NATURAL := 0
   ); 
   PORT (
     mm_rst             : IN  STD_LOGIC;
@@ -46,10 +46,10 @@ ENTITY dp_offload_rx IS
     reg_hdr_dat_miso   : OUT t_mem_miso;
 
     snk_in_arr         : IN  t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); 
-    snk_out_arr        : OUT t_dp_siso_arr(g_nof_streams-1 DOWNTO 0);
+    snk_out_arr        : OUT t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
 
     src_out_arr        : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); 
-    src_in_arr         : IN  t_dp_siso_arr(g_nof_streams-1 DOWNTO 0);
+    src_in_arr         : IN  t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
 
     hdr_fields_out_arr : OUT t_slv_1024_arr(g_nof_streams-1 DOWNTO 0); -- Valid at src_out_arr(i).sop, use for sosi.sync
     hdr_fields_raw_arr : OUT t_slv_1024_arr(g_nof_streams-1 DOWNTO 0)  -- Valid at src_out_arr(i).sop and beyond, use for sosi.bsn
diff --git a/libraries/base/ring/hdllib.cfg b/libraries/base/ring/hdllib.cfg
index 96d39f35a78c464ee187bd900cb60c8890fee9c6..05ea894b803b961ed19893a98d196a74a6ab7730 100644
--- a/libraries/base/ring/hdllib.cfg
+++ b/libraries/base/ring/hdllib.cfg
@@ -9,6 +9,7 @@ synth_files =
     src/vhdl/ring_lane_info_reg.vhd
     src/vhdl/ring_lane_info.vhd
     src/vhdl/ring_tx.vhd
+    src/vhdl/ring_rx.vhd
 test_bench_files =
     tb/vhdl/tb_ring_lane_info.vhd
 
diff --git a/libraries/base/ring/src/vhdl/ring_rx.vhd b/libraries/base/ring/src/vhdl/ring_rx.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..7597142cc45c3d3cecb8bdf052d9e8880ea02e76
--- /dev/null
+++ b/libraries/base/ring/src/vhdl/ring_rx.vhd
@@ -0,0 +1,232 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2021
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------
+--
+-- Author: R. van der Walle
+
+-- Purpose: Handle TX side of ring design.
+-- Description: See https://support.astron.nl/confluence/x/jyu7Ag
+-- Remark:
+-- . Note that the dp_fifo_fill_eop in dp_block_validate_err cannot handle
+--   continues stream of blocks without a gap between blocks the dp_fifo_fill_eop 
+--   needs 1 cycle to process a block. Streaming without gaps may cause the fifo 
+--   to overflow. Bursts of blocks can be handled by increasing g_fifo_size.
+
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, mm_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE work.ring_pkg.ALL;
+
+ENTITY ring_rx IS
+  GENERIC (
+    g_use_dp_layer     : BOOLEAN := TRUE;
+    g_lane_direction   : NATURAL := 1;
+    g_data_w           : NATURAL := 64;
+    g_nof_rx_monitors  : NATURAL := 1;
+    g_err_bi           : NATURAL := 0;  
+    g_block_size       : NATURAL := 1024; 
+    g_nof_err_counts   : NATURAL := 1; 
+    g_fifo_size        : NATURAL := 1536; 
+    g_check_channel    : NATURAL := 1 
+  );
+  PORT (
+    -- Clocks and reset
+    mm_rst                  : IN  STD_LOGIC;   -- reset synchronous with mm_clk
+    mm_clk                  : IN  STD_LOGIC;   -- memory-mapped bus clock
+
+    dp_clk                  : IN  STD_LOGIC;
+    dp_rst                  : IN  STD_LOGIC;
+
+    from_lane_sosi          : OUT t_dp_sosi;
+    lane_rx_cable_sosi      : IN  t_dp_sosi;
+    lane_rx_board_sosi      : IN  t_dp_sosi;
+    bs_sosi                 : IN  t_dp_sosi;
+
+    reg_bsn_monitor_v2_copi                : IN  t_mem_copi;
+    reg_bsn_monitor_v2_cipo                : OUT t_mem_cipo;
+    reg_dp_block_validate_err_copi         : IN  t_mem_copi;
+    reg_dp_block_validate_err_cipo         : OUT t_mem_cipo;
+    reg_dp_block_validate_bsn_at_sync_copi : IN  t_mem_copi;
+    reg_dp_block_validate_bsn_at_sync_cipo : OUT t_mem_cipo;
+
+    ref_sync  : IN  STD_LOGIC; 
+    rx_select : IN  STD_LOGIC;
+    this_rn   : IN  STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+    N_rn      : IN  STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0)
+  );
+END ring_rx;
+
+ARCHITECTURE str OF ring_rx IS
+
+  CONSTANT c_nof_hdr_fields : NATURAL := sel_a_b(g_use_dp_layer, c_ring_dp_nof_hdr_fields, c_ring_eth_nof_hdr_fields);
+  CONSTANT c_hdr_field_arr  : t_common_field_arr(c_nof_hdr_fields-1 DOWNTO 0) := sel_a_b(g_use_dp_layer, c_ring_dp_hdr_field_arr, c_ring_eth_hdr_field_arr);
+
+  SIGNAL lane_rx_sosi     : t_dp_sosi;
+  SIGNAL packet_sosi      : t_dp_sosi;
+  SIGNAL validated_sosi   : t_dp_sosi;
+  SIGNAL offload_rx_sosi  : t_dp_sosi;
+  SIGNAL decoded_sosi     : t_dp_sosi;
+  SIGNAL monitor_sosi     : t_dp_sosi;
+  SIGNAL monitor_sosi_arr : t_dp_sosi_arr(g_nof_rx_monitors-1 DOWNTO 0);
+
+  SIGNAL hdr_fields_out   : STD_LOGIC_VECTOR(1023 DOWNTO 0);
+
+BEGIN
+
+  -- Select input based on rx_select
+  lane_rx_sosi <= lane_rx_cable_sosi WHEN rx_select = '1' ELSE lane_rx_board_sosi;
+
+  -- Validate length 
+  u_dp_block_validate_length : ENTITY dp_lib.dp_block_validate_length
+  GENERIC MAP (
+    g_err_bi          => g_err_bi,
+    g_expected_length => g_block_size
+  )
+  PORT MAP (
+    rst => dp_rst,
+    clk => dp_clk,
+
+    snk_in  => lane_rx_sosi,
+    src_out => packet_sosi
+  );
+
+  -- Validate error field 
+  u_dp_block_validate_err : ENTITY dp_lib.dp_block_validate_err
+  GENERIC MAP (
+    g_max_block_size  => g_block_size,
+    g_min_block_size  => g_block_size,
+    g_nof_err_counts  => g_nof_err_counts,
+    g_fifo_size       => g_fifo_size,
+    g_data_w          => g_data_w
+  )
+  PORT MAP (
+    dp_rst => dp_rst,
+    dp_clk => dp_clk,
+
+    snk_in  => packet_sosi,
+    src_out => validated_sosi,
+
+    mm_rst => mm_rst,
+    mm_clk => mm_clk,
+
+    reg_mosi => reg_dp_block_validate_err_copi,
+    reg_miso => reg_dp_block_validate_err_cipo
+  );
+
+  -- Removing ETH/DP header
+  u_dp_offload_rx: ENTITY dp_lib.dp_offload_rx
+  GENERIC MAP (
+    g_nof_streams   => 1,
+    g_data_w        => g_data_w,
+    g_hdr_field_arr => c_hdr_field_arr
+  )
+  PORT MAP (
+    mm_rst => mm_rst,
+    mm_clk => mm_clk,
+
+    dp_rst => dp_rst,
+    dp_clk => dp_clk,
+
+    snk_in_arr(0)  => validated_sosi,
+    src_out_arr(0) => offload_rx_sosi,
+
+    hdr_fields_out_arr(0)  => hdr_fields_out
+  );
+
+  -- Use dp layer
+  gen_dp_layer : IF g_use_dp_layer GENERATE
+    p_set_meta: PROCESS(offload_rx_sosi, hdr_fields_out)
+    BEGIN
+      decoded_sosi         <= offload_rx_sosi;
+      decoded_sosi.sync    <=                   hdr_fields_out(field_hi(c_hdr_field_arr, "dp_sync"    ) DOWNTO field_lo(c_hdr_field_arr, "dp_sync"     ))(0);
+      decoded_sosi.channel <= RESIZE_DP_CHANNEL(hdr_fields_out(field_hi(c_hdr_field_arr, "dp_channel" ) DOWNTO field_lo(c_hdr_field_arr, "dp_channel"  )));
+      decoded_sosi.bsn     <= RESIZE_DP_BSN(    hdr_fields_out(field_hi(c_hdr_field_arr, "dp_bsn"     ) DOWNTO field_lo(c_hdr_field_arr, "dp_bsn"      )));
+    END PROCESS;
+
+    -- Validate bsn at sync 
+    u_dp_block_validate_bsn_at_sync : ENTITY dp_lib.dp_block_validate_bsn_at_sync
+    GENERIC MAP (
+      g_check_channel => g_check_channel
+    )
+    PORT MAP (
+      dp_rst => dp_rst,
+      dp_clk => dp_clk,
+
+      in_sosi  => decoded_sosi,
+      bs_sosi  => bs_sosi,
+      out_sosi => from_lane_sosi,
+
+      mm_rst => mm_rst,
+      mm_clk => mm_clk,
+
+      reg_mosi => reg_dp_block_validate_bsn_at_sync_copi,
+      reg_miso => reg_dp_block_validate_bsn_at_sync_cipo
+    );
+
+    -- Convert nof_hops to source RN
+    p_hop_to_src_rn: PROCESS(validated_sosi, this_rn, N_rn)
+    BEGIN
+      monitor_sosi <= decoded_sosi;
+      monitor_sosi.channel <= func_nof_hops_to_source_rn(decoded_sosi.channel, this_rn, N_rn, g_lane_direction);
+    END PROCESS;
+
+    u_dp_demux : ENTITY dp_lib.dp_demux
+    GENERIC MAP (
+      g_nof_output => g_nof_rx_monitors,
+      g_sel_ctrl_invert => TRUE
+    )
+    PORT MAP (
+      rst         => dp_rst,
+      clk         => dp_clk,
+      snk_in      => monitor_sosi,
+      src_out_arr => monitor_sosi_arr 
+    );
+
+    -- BSN Monitors
+    u_mms_dp_bsn_monitor_v2 : ENTITY dp_lib.mms_dp_bsn_monitor_v2
+    GENERIC MAP (
+      g_nof_streams => g_nof_rx_monitors
+    )
+    PORT MAP (
+      mm_rst      => mm_rst,
+      mm_clk      => mm_clk,
+      reg_mosi    => reg_bsn_monitor_v2_copi,
+      reg_miso    => reg_bsn_monitor_v2_cipo,
+
+      dp_rst      => dp_rst,
+      dp_clk      => dp_clk,
+      in_sosi_arr => monitor_sosi_arr,
+      ref_sync    => ref_sync
+    );
+
+  END GENERATE; 
+
+  -- Do not use dp layer
+  gen_no_dp_layer : IF NOT g_use_dp_layer GENERATE 
+    from_lane_sosi <= offload_rx_sosi;
+  END GENERATE;
+
+END str;