diff --git a/libraries/base/diag/src/vhdl/mms_diag_data_buffer_dev.vhd b/libraries/base/diag/src/vhdl/mms_diag_data_buffer_dev.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..4f8c6f02c2a5807a8c13d5e33b1fbe4a14dabb66
--- /dev/null
+++ b/libraries/base/diag/src/vhdl/mms_diag_data_buffer_dev.vhd
@@ -0,0 +1,224 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2011
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose: MM data buffer and Rx seq for multiple parallel SOSI streams
+-- Description:                             
+-- . g_use_db
+--   The mms_diag_data_buffer can capture data from an input stream in a data
+--   buffer when g_use_db=TRUE. Dependend on g_buf_use_sync the data buffer
+--   is rewritten after each in_sync or when the last word was read via MM.
+-- . g_use_rx_seq
+--   The mms_diag_data_buffer can continously verify a input Rx data sequence
+--   when g_use_rx_seq=TRUE. The expected sequence data is typically generated
+--   by an remote upstream tx_seq source.
+-- . The advantage of the rx_seq is that is can continously verify the
+--   correctness of all rx data in hardware, whereas the DB can only take a
+--   snapshot that then needs to be examined via MM. The advandage of the DB
+--   is that it can take a snapshot of the values of the received data. The
+--   DB requires RAM resources and the rx_seq does not.
+--
+-- Block diagram:
+--
+--                           g_use_db 
+--                           g_buf_use_sync
+--                              .
+--                              .      g_use_tx_seq
+--                              .          .
+--                              .          .
+--                      /-------------> Rx seq 
+--                      |       .         |
+--     in_sosi_arr -----*---> DB RAM      |
+--     in_sync -------------> DB reg      |
+--                              ||        |
+--                              ||        |
+--              MM ================================
+--
+-- Remark:
+-- . A nice new feature would be to continuously write the DB and to stop
+--   writting it on a trigger. This trigger can then eg. be when the rx_seq
+--   detects an error. By delaying the trigger somewhat it the DB can then
+--   capture some data before and after the trigger event.
+
+LIBRARY IEEE, common_lib, technology_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL; 
+USE work.diag_pkg.ALL;
+USE technology_lib.technology_select_pkg.ALL;
+
+ENTITY mms_diag_data_buffer_dev IS
+  GENERIC (    
+    g_technology   : NATURAL := c_tech_select_default;
+    -- Generate configurationsc_diag_db
+    g_use_db       : BOOLEAN := TRUE;
+    g_use_rx_seq   : BOOLEAN := FALSE;
+    -- General
+    g_nof_streams  : POSITIVE := 16;    -- each stream gets an data buffer
+    -- DB settings
+    g_data_type    : t_diag_data_type_enum := e_data;      -- define the sosi field that gets stored: e_data=data, e_complex=im&re, e_real=re, e_imag=im
+    g_data_w       : NATURAL := 32;     -- the g_data_w is the width of the data, re, im values or of the combined im&re value
+    g_buf_nof_data : NATURAL := 1024;   -- nof words per data buffer
+    g_buf_use_sync : BOOLEAN := FALSE;  -- when TRUE start filling the buffer at the in_sync, else after the last word was read
+    -- Rx_seq
+    g_use_steps    : BOOLEAN := FALSE;
+    g_nof_steps    : NATURAL := c_diag_seq_rx_reg_nof_steps;
+    g_seq_dat_w    : NATURAL := 32  -- >= 1, test sequence data width. Choose g_seq_dat_w <= g_data_w
+  );
+  PORT (
+    -- System
+    mm_rst            : IN  STD_LOGIC;
+    mm_clk            : IN  STD_LOGIC;
+    dp_rst            : IN  STD_LOGIC;
+    dp_clk            : IN  STD_LOGIC;
+    -- MM interface
+    reg_data_buf_mosi : IN  t_mem_mosi := c_mem_mosi_rst;  -- DB control register (one per stream)
+    reg_data_buf_miso : OUT t_mem_miso;
+
+    ram_data_buf_mosi : IN  t_mem_mosi := c_mem_mosi_rst;  -- DB buffer RAM (one per streams)
+    ram_data_buf_miso : OUT t_mem_miso;
+
+    reg_rx_seq_mosi   : IN  t_mem_mosi := c_mem_mosi_rst;  -- Rx seq control register (one per streams)
+    reg_rx_seq_miso   : OUT t_mem_miso;
+    
+    -- ST interface
+    in_sync           : IN  STD_LOGIC := '0';  -- input sync pulse in ST dp_clk domain that starts data buffer when g_use_in_sync = TRUE
+    in_sosi_arr       : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0)
+  );
+END mms_diag_data_buffer_dev;
+
+ARCHITECTURE str OF mms_diag_data_buffer_dev IS
+
+  CONSTANT c_buf_mm_factor   : NATURAL := ceil_div(g_data_w, c_word_w);
+  CONSTANT c_buf_nof_data_mm : NATURAL := g_buf_nof_data*c_buf_mm_factor;
+
+  CONSTANT c_buf_adr_w : NATURAL := ceil_log2(c_buf_nof_data_mm);
+  CONSTANT c_reg_adr_w : NATURAL := c_diag_db_dev_reg_adr_w;
+
+  TYPE t_data_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
+  
+  SIGNAL in_data_arr           : t_data_arr(g_nof_streams-1 DOWNTO 0);
+  
+  SIGNAL ram_data_buf_mosi_arr : t_mem_mosi_arr(g_nof_streams-1 DOWNTO 0);
+  SIGNAL ram_data_buf_miso_arr : t_mem_miso_arr(g_nof_streams-1 DOWNTO 0); 
+
+  SIGNAL reg_data_buf_mosi_arr : t_mem_mosi_arr(g_nof_streams-1 DOWNTO 0);
+  SIGNAL reg_data_buf_miso_arr : t_mem_miso_arr(g_nof_streams-1 DOWNTO 0); 
+  
+BEGIN
+
+  no_db : IF g_use_db=FALSE GENERATE
+    ram_data_buf_miso <= c_mem_miso_rst;
+    reg_data_buf_miso <= c_mem_miso_rst;
+  END GENERATE;
+  
+  gen_db : IF g_use_db=TRUE GENERATE
+    -- Combine the internal array of mm interfaces for the data_buf to one array that is connected to the port of the MM bus
+    u_mem_mux_data_buf : ENTITY common_lib.common_mem_mux
+    GENERIC MAP (    
+      g_nof_mosi    => g_nof_streams,
+      g_mult_addr_w => c_buf_adr_w
+    )
+    PORT MAP (
+      mosi     => ram_data_buf_mosi,
+      miso     => ram_data_buf_miso,
+      mosi_arr => ram_data_buf_mosi_arr,
+      miso_arr => ram_data_buf_miso_arr
+    );
+  
+    u_mem_mux_reg : ENTITY common_lib.common_mem_mux
+    GENERIC MAP (    
+      g_nof_mosi    => g_nof_streams,
+      g_mult_addr_w => c_reg_adr_w
+    )
+    PORT MAP (
+      mosi     => reg_data_buf_mosi,
+      miso     => reg_data_buf_miso,
+      mosi_arr => reg_data_buf_mosi_arr,
+      miso_arr => reg_data_buf_miso_arr
+    );
+    
+    gen_stream : FOR I IN 0 TO g_nof_streams-1 GENERATE
+      in_data_arr(I) <= in_sosi_arr(I).im(g_data_w/2-1 DOWNTO 0) & in_sosi_arr(I).re(g_data_w/2-1 DOWNTO 0) WHEN g_data_type=e_complex ELSE
+                        in_sosi_arr(I).re(g_data_w-1 DOWNTO 0)                                              WHEN g_data_type=e_real ELSE
+                        in_sosi_arr(I).im(g_data_w-1 DOWNTO 0)                                              WHEN g_data_type=e_imag ELSE
+                        in_sosi_arr(I).data(g_data_w-1 DOWNTO 0);                                             -- g_data_type=e_data is default
+    
+      u_diag_data_buffer : ENTITY work.diag_data_buffer_dev
+      GENERIC MAP (
+        g_technology  => g_technology,
+        g_data_w      => g_data_w, 
+        g_nof_data    => g_buf_nof_data,
+        g_use_in_sync => g_buf_use_sync   -- when TRUE start filling the buffer at the in_sync, else after the last word was read
+      )
+      PORT MAP (
+        -- Memory-mapped clock domain
+        mm_rst      => mm_rst,
+        mm_clk      => mm_clk,
+    
+        ram_mm_mosi => ram_data_buf_mosi_arr(I),
+        ram_mm_miso => ram_data_buf_miso_arr(I),
+  
+        reg_mm_mosi => reg_data_buf_mosi_arr(I),
+        reg_mm_miso => reg_data_buf_miso_arr(I),
+        
+        -- Streaming clock domain
+        st_rst      => dp_rst,
+        st_clk      => dp_clk,
+    
+        in_data     => in_data_arr(I),
+        in_sync     => in_sync,
+        in_val      => in_sosi_arr(I).valid
+      );
+    END GENERATE;
+  END GENERATE;
+
+  no_rx_seq : IF g_use_rx_seq=FALSE GENERATE
+    reg_rx_seq_miso <= c_mem_miso_rst;
+  END GENERATE;
+  
+  gen_rx_seq : IF g_use_rx_seq=TRUE GENERATE
+    u_mms_diag_rx_seq : ENTITY work.mms_diag_rx_seq
+    GENERIC MAP (
+      g_nof_streams => g_nof_streams,
+      g_use_steps   => g_use_steps,
+      g_nof_steps   => g_nof_steps,
+      g_seq_dat_w   => g_seq_dat_w,  -- >= 1, test sequence data width
+      g_data_w      => g_data_w      -- >= g_seq_dat_w, user data width
+    )
+    PORT MAP (
+      -- Clocks and reset
+      mm_rst         => mm_rst,
+      mm_clk         => mm_clk,
+      dp_rst         => dp_rst,
+      dp_clk         => dp_clk,
+  
+      -- Memory Mapped Slave
+      reg_mosi       => reg_rx_seq_mosi,   -- multiplexed port for g_nof_streams MM control/status registers
+      reg_miso       => reg_rx_seq_miso,
+  
+      -- Streaming interface
+      rx_snk_in_arr  => in_sosi_arr
+    );
+  END GENERATE;
+  
+END str;