diff --git a/applications/lofar2/libraries/ddrctrl/hdllib.cfg b/applications/lofar2/libraries/ddrctrl/hdllib.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..8f92d2ddd3f4d347fdfc32811cdbcefd07fe0288
--- /dev/null
+++ b/applications/lofar2/libraries/ddrctrl/hdllib.cfg
@@ -0,0 +1,25 @@
+hdl_lib_name = lofar2_ddrctrl
+hdl_library_clause_name = lofar2_ddrctrl_lib
+hdl_lib_uses_synth = technology common tech_ddr dp
+hdl_lib_uses_sim = 
+hdl_lib_technology = 
+
+synth_files = 
+    src/vhdl/ddrctrl_address_counter.vhd 
+    src/vhdl/ddrctrl_pack.vhd
+    src/vhdl/ddrctrl_repack.vhd
+    src/vhdl/ddrctrl.vhd
+
+test_bench_files =
+    tb/vhdl/tb_ddrctrl_address_counter.vhd
+    tb/vhdl/tb_ddrctrl_pack.vhd
+    tb/vhdl/tb_ddrctrl_repack.vhd
+    tb/vhdl/tb_ddrctrl.vhd
+
+regression_test_vhdl = 
+
+[modelsim_project_file]
+
+
+[quartus_project_file]
+
diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..838e8f5c89576d1b3a336d91e8d2ab180e863269
--- /dev/null
+++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd
@@ -0,0 +1,119 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2022
+-- 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: Job van Wee
+-- Purpose: Folding a stream of data into a mm data configuration so it can be
+-- stored in a DDR RAM-stick.
+--
+-- Description:
+--  First the data from the sosi array gets collected into one data vector.
+--  After that this data vector gets resized to the right size data vector in 
+--  order to make it storable in a DDR RAM-stick.
+--  After that a address gets assigned to the data so the data can be found back.
+--
+-- Remark:
+--  Use VHDL coding template from:
+--  https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding
+--  The maximum value of the address is determend by g_tech_ddr.
+
+LIBRARY IEEE, technology_lib, tech_ddr_lib, common_lib, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE tech_ddr_lib.tech_ddr_pkg.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+
+
+ENTITY ddrctrl IS
+  GENERIC (
+    g_tech_ddr        : t_c_tech_ddr;                                   -- type of memory
+    g_sim_model       : BOOLEAN       := TRUE;                          -- determens if this is a simulation
+    g_nof_streams     : NATURAL       := 12;                            -- number of input streams
+    g_data_w          : NATURAL       := 14                             -- data with of input data vectors
+  );
+  PORT (
+    clk               : IN  STD_LOGIC := '0';
+    rst               : IN  STD_LOGIC;
+    in_sosi_arr       : IN  t_dp_sosi_arr;                              -- input data
+    out_of            : OUT NATURAL;                                    -- amount of internal overflow this output
+    out_mosi          : OUT t_mem_ctlr_mosi                             -- output data
+  );
+END ddrctrl;
+
+
+ARCHITECTURE str OF ddrctrl IS
+
+  -- constant for readability
+  CONSTANT  c_out_data_w : NATURAL    := g_nof_streams*g_data_w;        -- the input data with for ddrctrl_repack
+
+
+  -- signals for connecting the components
+  SIGNAL    data         : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0);
+  SIGNAL    sosi         : t_dp_sosi  := c_dp_sosi_init;
+  SIGNAL    a_of           : NATURAL    := 0;
+
+BEGIN
+
+  -- makes one data vector out of all the data from the t_dp_sosi_arr
+  u_pack : ENTITY work.ddrctrl_pack
+  GENERIC MAP(
+
+    g_nof_streams     => g_nof_streams,                                 -- number of input streams
+    g_data_w          => g_data_w                                       -- data with of input data vectors
+
+  )
+  PORT MAP(
+
+    in_sosi_arr       => in_sosi_arr,                                   -- input data
+    out_data          => data                                           -- output data
+
+  );
+
+  -- resizes the input data vector so that the output data vector can be stored into the ddr memory
+  u_repack : ENTITY work.ddrctrl_repack
+  GENERIC MAP(
+    g_tech_ddr        => g_tech_ddr,                                    -- type of memory
+    g_in_data_w       => c_out_data_w                                   -- the input data with
+  )
+  PORT MAP(
+    clk               => clk,
+    rst               => rst,
+    in_data           => data,                                          -- input data
+    out_of            => a_of,                                          -- amount of internal overflow
+    out_sosi          => sosi                                           -- output data
+  );
+
+  -- creates address by counting input valids
+  u_address_counter : ENTITY work.ddrctrl_address_counter
+  GENERIC MAP(
+    g_tech_ddr        => g_tech_ddr,                                    -- type of memory
+    g_sim_model       => g_sim_model                                    -- determens if this is a simulation
+  )
+  PORT MAP(
+    clk               => clk,
+    rst               => rst,
+    in_sosi           => sosi,                                          -- input data
+    in_of             => a_of,
+    out_mosi          => out_mosi,                                      -- output data
+    out_of            => out_of
+  );
+
+END str;
diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..25d43e825ad5bd8bd5babdb72071004b391f9945
--- /dev/null
+++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd
@@ -0,0 +1,133 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2022
+-- 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: Job van Wee
+-- Purpose: Creates address by counting input valids
+--
+-- Description:
+--  The counter starts on the first valid = '1' clockcylce, the counter stops 
+--  when valid = '0'.
+--
+-- Remark:
+--  Use VHDL coding template from:
+--  https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding
+--  The maximum value of the address is determend by g_tech_ddr.
+
+LIBRARY IEEE, technology_lib, tech_ddr_lib, common_lib, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE tech_ddr_lib.tech_ddr_pkg.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+
+
+ENTITY ddrctrl_address_counter IS
+  GENERIC (
+    g_tech_ddr            : t_c_tech_ddr;                                                                                                 -- type of memory
+    g_sim_model           : BOOLEAN                               := TRUE                                                                 -- determens if this is a simulation
+  );
+  PORT (
+    clk                   : IN  STD_LOGIC;
+    rst                   : IN  STD_LOGIC;
+    in_sosi               : IN  t_dp_sosi;                                                                                                -- input data
+    in_of                 : IN  NATURAL;
+    out_mosi              : OUT t_mem_ctlr_mosi                   := c_mem_ctlr_mosi_rst;                                                 -- output data
+    out_of                : OUT NATURAL
+  );
+END ddrctrl_address_counter;
+
+
+ARCHITECTURE rtl OF ddrctrl_address_counter IS
+
+  -- constants for readability
+  CONSTANT c_data_w       : NATURAL                               := func_tech_ddr_ctlr_data_w( g_tech_ddr );                             -- the with of the input data and output data, 576
+  CONSTANT c_adr_w        : NATURAL                               := sel_a_b(g_sim_model, 4, func_tech_ddr_ctlr_address_w( g_tech_ddr )); -- the lengt of the address vector, for simulation this is smaller, otherwise the simulation would take to long, 27
+  CONSTANT c_max_adr      : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0)  := STD_LOGIC_VECTOR(TO_UVEC(2**(c_adr_w)-1, c_adr_w));                  -- the maximal address that is possible within the vector length of the address
+
+  -- type for statemachine
+  TYPE t_state IS (RESET, COUNTING, MAX, IDLE);
+
+  -- record for readability
+  TYPE t_reg IS RECORD
+  state                   : t_state;
+  out_mosi                : t_mem_ctlr_mosi;
+  out_of                  : NATURAL;
+  s_in_sosi               : t_dp_sosi;
+  s_in_of                 : NATURAL;
+  END RECORD;
+
+  CONSTANT  c_t_reg_init  : t_reg                                 := (RESET, c_mem_ctlr_mosi_rst, 0, c_dp_sosi_init, 0);
+
+
+  -- signals for readability
+  SIGNAL d_reg            : t_reg                                 := c_t_reg_init;
+  SIGNAL q_reg            : t_reg                                 := c_t_reg_init;
+
+BEGIN
+
+  q_reg <= d_reg WHEN rising_edge(clk);
+
+  -- Increments the address each time in_sosi.valid = '1', if address = c_max_adr the address is reset to 0.
+  p_adr : PROCESS(rst, in_sosi, in_of, q_reg)
+
+  VARIABLE v              : t_reg;
+
+  BEGIN
+    v                                                             := q_reg;
+    v.out_mosi.wrdata(c_data_w-1 DOWNTO 0)                        := q_reg.s_in_sosi.data(c_data_w - 1 DOWNTO 0);
+    v.out_mosi.wr                                                 := q_reg.s_in_sosi.valid;
+    v.out_of                                                      := q_reg.s_in_of;
+    v.s_in_sosi                                                   := in_sosi;
+    v.s_in_of                                                     := in_of;
+
+
+    CASE q_reg.state IS
+    WHEN RESET =>
+      v.out_mosi.address(c_adr_w-1 DOWNTO 0) := (OTHERS => '0');
+
+    WHEN COUNTING =>
+      v.out_mosi.address(c_adr_w-1 DOWNTO 0) := STD_LOGIC_VECTOR(TO_UVEC(TO_UINT(q_reg.out_mosi.address)+1, c_adr_w));
+
+    WHEN MAX =>
+      v.out_mosi.address(c_adr_w-1 DOWNTO 0) := (OTHERS => '0');
+
+    WHEN IDLE =>
+
+    END CASE;
+
+    IF rst = '1' THEN
+      v.state := RESET;
+    ELSIF q_reg.out_mosi.address(c_adr_w-1 DOWNTO 0) = c_max_adr(c_adr_w-1 DOWNTO 0) AND in_sosi.valid = '1' THEN
+      v.state := MAX;
+    ELSIF in_sosi.valid = '1' THEN
+      v.state := COUNTING;
+    ELSE
+      v.state := IDLE;
+    END IF;
+
+    d_reg <= v;
+  END PROCESS;
+
+  -- fill outputs
+  out_mosi <= q_reg.out_mosi;
+  out_of   <= q_reg.out_of;
+
+END rtl;
diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_pack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_pack.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..5d7630a29b8c8e4b870f74ca713a0ad3622cd1a1
--- /dev/null
+++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_pack.vhd
@@ -0,0 +1,58 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2022
+-- 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: Job van Wee
+-- Purpose: Make one data vector out of all the data from the t_dp_sosi_arr.
+--
+-- Description:
+--  The data from the t_dp_sosi_arr gets put into one data vector.
+--
+-- Remark:
+--  Use VHDL coding template from:
+--  https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding
+
+LIBRARY IEEE, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+
+ENTITY ddrctrl_pack IS
+  GENERIC (
+
+    g_nof_streams : POSITIVE := 12;                                           -- number of input streams
+    g_data_w      : NATURAL  := 14                                            -- data with of input data vectors
+
+  );
+  PORT (
+
+    in_sosi_arr   : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);               -- input data
+    out_data      : OUT STD_LOGIC_VECTOR((g_nof_streams*g_data_w)-1 DOWNTO 0) -- output data
+
+  );
+END ddrctrl_pack;
+
+ARCHITECTURE rtl OF ddrctrl_pack IS
+
+BEGIN
+
+  -- Putting all the data from the different streams into one data vector.
+  gen_extract_and_pack_data : FOR I IN 0 TO g_nof_streams-1 GENERATE
+    out_data(g_data_w*(I+1)-1 DOWNTO g_data_w*I) <= in_sosi_arr(I).data(g_data_w-1 DOWNTO 0);
+  END GENERATE;
+
+END rtl;
diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_repack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_repack.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..e650494588ca35744b3d979d72ea214368350fe3
--- /dev/null
+++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_repack.vhd
@@ -0,0 +1,137 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2022
+-- 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: Job van Wee
+-- Purpose: Resize the input data vector so that the output data vector can be
+--  stored into the ddr memory.
+--
+-- Description:
+--  The input data gets resized and put into the output data vector.
+--
+-- Remark:
+--  Use VHDL coding template from:
+--  https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding
+--  The output vector must be larger than the input vector.
+
+LIBRARY IEEE, dp_lib, tech_ddr_lib;
+USE IEEE.std_logic_1164.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE tech_ddr_lib.tech_ddr_pkg.ALL;
+
+ENTITY ddrctrl_repack IS
+  GENERIC (
+    g_tech_ddr              : t_c_tech_ddr;                                                                                                   -- type of memory
+    g_in_data_w             : NATURAL       := 168                                                                                            -- the input data with
+  );
+  PORT (
+    clk                     : IN  STD_LOGIC;
+    rst                     : IN  STD_LOGIC;
+    in_data                 : IN  STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0);                                                                   -- input data
+    out_of                  : OUT NATURAL   := 0;                                                                                             -- amount of internal overflow this output
+    out_sosi                : OUT t_dp_sosi := c_dp_sosi_init                                                                                 -- output data
+  );
+END ddrctrl_repack;
+
+
+ARCHITECTURE rtl OF ddrctrl_repack IS
+
+  -- constant for readability
+  CONSTANT c_out_data_w     : NATURAL       := func_tech_ddr_ctlr_data_w( g_tech_ddr );                                                       -- the output data with, 576
+  CONSTANT k_c_v_w          : NATURAL       := c_out_data_w*2;                                                                                -- the c_v data with, 2*576=1152
+
+  -- type for statemachine
+  TYPE t_state IS (OVERFLOW_OUTPUT, FILL_VECTOR, FIRST_OUTPUT, RESET);
+
+  -- record for readability
+  TYPE t_reg IS RECORD
+  state                     : t_state;                                                                                                        -- the state the process is currently in;
+  a_of                      : NATURAL;                                                                                                        -- amount of overflow
+  c_v                       : STD_LOGIC_VECTOR(k_c_v_w-1 DOWNTO 0);                                                                           -- the vector that stores the input data until the data is put into the output data vector
+  c_v_count                 : NATURAL;                                                                                                        -- the amount of times the c_v vector received data from the input since the last time it was filled completely
+  out_data_count            : NATURAL;                                                                                                        -- the amount of times the output data vector has been filled since the last time c_v was filled completely
+  out_of                    : NATURAL;
+  out_sosi                  : t_dp_sosi;
+  END RECORD;
+
+  CONSTANT c_t_reg_init     : t_reg         := (RESET, 0, (OTHERS => '0'), 0, 0, 0, c_dp_sosi_init);
+
+  -- signals for readability
+  SIGNAL d_reg              : t_reg         := c_t_reg_init;
+  SIGNAL q_reg              : t_reg         := c_t_reg_init;
+
+BEGIN
+
+  q_reg <= d_reg WHEN rising_edge(clk);
+
+  -- put the input data into c_v and fill the output vector from c_v
+  p_state : PROCESS(q_reg, rst)
+
+    VARIABLE v                : t_reg;
+
+  BEGIN
+
+    v := q_reg;
+
+    CASE q_reg.state IS
+    WHEN FILL_VECTOR =>                                                                                                                       -- if the input data doesn't exceeds the output data vector width
+      v.c_v(g_in_data_w*(q_reg.c_v_count+1)+q_reg.a_of-1 DOWNTO g_in_data_w*q_reg.c_v_count+q_reg.a_of) := in_data(g_in_data_w-1 DOWNTO 0);   -- fill c_v
+      v.c_v_count := q_reg.c_v_count+1;                                                                                                       -- increase the counter of c_v with 1
+      v.out_sosi.valid := '0';                                                                                                                -- out_sosi.valid 0
+
+    WHEN FIRST_OUTPUT =>                                                                                                                      -- if the input data exceeds output data vector width but not the c_v width
+       v.c_v(g_in_data_w*(q_reg.c_v_count+1)+q_reg.a_of-1 DOWNTO g_in_data_w*q_reg.c_v_count+q_reg.a_of) := in_data(g_in_data_w-1 DOWNTO 0);  -- fill c_v
+       v.c_v_count := q_reg.c_v_count + 1;                                                                                                    -- increase the counter of c_v with 1
+       v.out_sosi.data(c_out_data_w - 1 DOWNTO 0) := v.c_v(c_out_data_w - 1 DOWNTO 0);                                                        -- fill out_sosi.data with 1st part of c_v
+       v.out_sosi.valid := '1';                                                                                                               -- out_sosi.valid 1
+       v.out_data_count := q_reg.out_data_count+1;                                                                                            -- increase the counter of out_sosi.data with 1
+
+    WHEN OVERFLOW_OUTPUT =>                                                                                                                   -- if the input data exceeds the output data vector width and the c_v width
+      v.a_of := q_reg.a_of + (g_in_data_w*(q_reg.c_v_count+1)) - (c_out_data_w*(q_reg.out_data_count+1));                                     -- check how much overflow there is and safe it in a_of
+      v.out_of := v.a_of;                                                                                                                     -- set the output overflow to the overflow that maches the out_sosi.data vector
+      v.c_v(k_c_v_w-1 DOWNTO k_c_v_w-(g_in_data_w-v.a_of)) := in_data(g_in_data_w-v.a_of-1 DOWNTO 0);                                         -- fill the rest of c_v untill the end
+      v.c_v(v.a_of-1 DOWNTO 0) := in_data(g_in_data_w-1 DOWNTO g_in_data_w-v.a_of);                                                           -- fill the start of c_v untill the a_of
+      v.out_sosi.data(c_out_data_w-1 DOWNTO 0) := v.c_v(k_c_v_w-1 DOWNTO c_out_data_w);                                                       -- fill out_sosi.data with 2nd part of c_v
+      v.out_sosi.valid := '1';                                                                                                                -- out_sosi.valid 1
+      v.c_v_count := 0;                                                                                                                       -- reset counter
+      v.out_data_count := 0;                                                                                                                  -- reset counter
+
+    WHEN RESET =>
+      v := c_t_reg_init;
+
+    END CASE;
+
+
+    IF rst = '1' THEN
+      v.state := RESET;
+    ELSIF ((g_in_data_w*(v.c_v_count+1))+v.a_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 0) THEN
+      v.state := FIRST_OUTPUT;
+    ELSIF ((g_in_data_w*(v.c_v_count+1))+v.a_of >= c_out_data_w*(v.out_data_count+1)) AND (v.out_data_count = 1) THEN
+      v.state := OVERFLOW_OUTPUT;
+    ELSE
+      v.state := FILL_VECTOR;
+    END IF;
+
+    d_reg <= v;
+  END PROCESS;
+
+  -- fill outputs
+  out_of    <= q_reg.out_of;
+  out_sosi  <= q_reg.out_sosi;
+
+END rtl;
diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..8b56c9ddcf22d7455e0099fbc19f4179ba6e526c
--- /dev/null
+++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd
@@ -0,0 +1,209 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2022
+-- 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: Job van Wee
+-- Purpose: Self checking and self-stopping tb for ddrctrl.vhd
+-- Usage:
+-- > run -a
+
+LIBRARY IEEE, common_lib, technology_lib, tech_ddr_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE IEEE.MATH_REAL.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE tech_ddr_lib.tech_ddr_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_pkg.ALL;
+
+ENTITY tb_ddrctrl IS
+  GENERIC (
+
+    g_tech_ddr                : t_c_tech_ddr                                          := c_tech_ddr4_8g_1600m;                    -- type of memory
+    g_sim_model               : BOOLEAN                                               := TRUE;                                    -- determens if this is a simulation
+    g_nof_streams             : POSITIVE                                              := 12;                                      -- number of input streams
+    g_data_w                  : NATURAL                                               := 14;                                      -- data with of input data vectors
+    g_sim_length              : NATURAL                                               := 52
+
+  );
+END tb_ddrctrl;
+
+ARCHITECTURE tb OF tb_ddrctrl IS
+
+  -- constants for testbench
+  CONSTANT  c_clk_freq        : NATURAL                                               := 200;                                     -- clock frequency in MHz
+  CONSTANT  c_clk_period      : TIME                                                  := (10**6 / c_clk_freq) * 1 ps;             -- clock priod, 5 ns
+
+  -- constants for readability
+  CONSTANT  c_in_data_w       : NATURAL                                               := g_nof_streams * g_data_w;                -- output data with, 168
+  CONSTANT  c_out_data_w      : NATURAL                                               := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- output data vector with, 576
+  CONSTANT  c_adr_w           : NATURAL                                               := 4;                                       -- address with in simulation
+  CONSTANT  c_adr_size        : NATURAL                                               := 2**c_adr_w;                              -- address size in simulation
+
+  -- function for making total data vector
+  FUNCTION  c_total_vector_init RETURN STD_LOGIC_VECTOR IS
+    VARIABLE temp             : STD_LOGIC_VECTOR(c_in_data_w*g_sim_length-1 DOWNTO 0);
+  BEGIN
+    FOR I IN 0 TO g_sim_length*g_nof_streams-1 LOOP
+      temp(g_data_w*(I+1)-1 DOWNTO g_data_w*I) := TO_UVEC(I, g_data_w);
+    END LOOP;
+    RETURN temp;
+  END FUNCTION c_total_vector_init;
+
+  -- constant for running the test
+  CONSTANT  c_total_vector    : STD_LOGIC_VECTOR(c_in_data_w*g_sim_length-1 DOWNTO 0) := c_total_vector_init;                     -- vector which contains all input data vectors to make it easy to fill ctr_vector
+
+
+  -- input signals for ddrctrl.vhd
+  SIGNAL    clk               : STD_LOGIC                                             := '1';
+  SIGNAL    rst               : STD_LOGIC                                             := '0';
+  SIGNAL    q_rst             : STD_LOGIC                                             := '0';
+  SIGNAL    q_q_rst           : STD_LOGIC                                             := '0';
+  SIGNAL    in_sosi_arr       : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0)               := (OTHERS => c_dp_sosi_init);              -- input data signal for ddrctrl_pack.vhd 
+
+  -- output singals from ddrctrl.vhd
+  SIGNAL    out_of            : NATURAL                                               := 0;                                       -- output signal from ddrctrl_repack to determen how high the overflow is
+  SIGNAL    out_mosi          : t_mem_ctlr_mosi                                       := c_mem_ctlr_mosi_rst;                     -- output signal from ddrctrl_pack.vhd
+
+  -- testbench signal
+  SIGNAL    tb_end            : STD_LOGIC                                             := '0';                                     -- signal to turn the testbench off
+
+  -- signals for running test
+  SIGNAL    in_data_cnt       : NATURAL                                               := 0;                                       -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd
+  SIGNAL    q_in_data_cnt     : NATURAL                                               := 0;                                       -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd with a delay of 1 clockcycle
+  SIGNAL    q_q_in_data_cnt   : NATURAL                                               := 0;                                       -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd with a delay of 2 clockcycles
+  SIGNAL    test_running      : STD_LOGIC                                             := '0';                                     -- signal to tell wheter the testing has started
+  SIGNAL    q_test_running    : STD_LOGIC                                             := '0';                                     -- signal to tell wheter the testing has started with a delay of 1 clockcycle
+  SIGNAL    q_q_test_running  : STD_LOGIC                                             := '0';                                     -- signal to tell wheter the testing has started with a delay of 2 clockcycles
+  SIGNAL    lag_due_reset     : NATURAL                                               := 0;                                       -- signal to hold the address lag after a rest
+  SIGNAL    q_lag_due_reset   : NATURAL                                               := 0;                                       -- signal to hold the address lag after a rest with a delay of 1 clockcycle
+
+BEGIN
+
+  -- generating clock
+  clk               <= NOT clk OR tb_end AFTER c_clk_period/2;
+
+  -- excecuting test
+  p_test : PROCESS
+  BEGIN
+
+    -- start the test
+    tb_end          <= '0';
+    WAIT UNTIL rising_edge(clk);                                                                                                  -- align to rising edge
+    WAIT FOR c_clk_period*4;
+    rst <= '1';
+    WAIT FOR c_clk_period*1;
+    rst <= '0';
+    test_running <= '1';
+
+    -- filling the input data vectors with the corresponding numbers
+    make_data : FOR J IN 0 TO g_sim_length-1 LOOP
+      in_data_cnt     <= in_data_cnt+1;
+      fill_in_sosi_arr_rest : FOR I IN 0 TO g_nof_streams-1 LOOP
+        in_sosi_arr(I).data(g_data_w-1 DOWNTO 0)   <= c_total_vector(g_data_w*(I+1)+J*c_in_data_w-1 DOWNTO g_data_w*I+J*c_in_data_w);
+      END LOOP;
+      WAIT FOR c_clk_period*1;
+    END LOOP;
+    test_running      <= '0';
+
+    -- testing reset
+    FOR I IN 0 TO g_sim_length-1 LOOP
+      rst <= '1';
+      WAIT FOR c_clk_period*1;
+      rst <= '0';
+      WAIT FOR c_clk_period*((((c_out_data_w/c_in_data_w)+1)*c_adr_size)+4);
+    END LOOP;
+
+
+    -- stopping the testbench
+    WAIT FOR c_clk_period*4;
+    tb_end <= '1';
+    ASSERT FALSE                                                                                                                          REPORT "Test: OK"                                                                                                                             SEVERITY FAILURE;
+  END PROCESS;
+
+  -- generating compare data for out_mosi
+  p_out_mosi : PROCESS
+  BEGIN
+    WAIT UNTIL rising_edge(clk);
+    if rising_edge(clk) THEN
+      q_q_rst           <= q_rst;
+      q_lag_due_reset   <= lag_due_reset;
+      q_rst             <= rst;
+    END IF;
+    IF q_rst = '1' THEN
+      IF lag_due_reset + TO_UINT(out_mosi.address) >= c_adr_size THEN
+        lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address)-c_adr_size;
+      ELSE
+        lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address);
+      END IF;
+    END IF;
+  END PROCESS;
+
+  -- verifying if the address is correct by keeping track of the address
+  p_verify_address : PROCESS
+  BEGIN
+    FOR I IN 0 TO c_adr_size-1 LOOP
+      IF I >= q_lag_due_reset THEN
+        ASSERT I-q_lag_due_reset   = TO_UINT(out_mosi.address)                                                                            REPORT "Wrong address, 1, I = " & NATURAL'image(I-q_lag_due_reset) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address))                SEVERITY ERROR;
+      ELSE
+        ASSERT (I-q_lag_due_reset)+c_adr_size = TO_UINT(out_mosi.address)                                                                 REPORT "Wrong address, 2, I = " & NATURAL'image((I-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address))   SEVERITY ERROR;
+      END IF;
+      WAIT UNTIL out_mosi.wr = '1';
+      IF q_q_rst = '1' THEN
+        WAIT UNTIL out_mosi.wr = '1';
+      END IF;
+    END LOOP;
+  END PROCESS;
+
+  -- verification by checking if the input vectors are correctly put into the output vector and the amount of overflow is as expected
+  p_verify : PROCESS
+
+  VARIABLE  ctr_of            : NATURAL                                                := 0;
+  VARIABLE  out_data_cnt      : NATURAL                                                := 0;
+
+  BEGIN
+  WAIT UNTIL rising_edge(clk);
+  IF q_q_test_running = '1' AND out_mosi.wr = '1' THEN
+    out_data_cnt      := out_data_cnt+1;
+    IF out_data_cnt mod 2 = 0 THEN
+      ctr_of := c_in_data_w*(q_q_in_data_cnt)-c_out_data_w*out_data_cnt;
+      ASSERT ctr_of                               = out_of                                                                                REPORT "The amount of overflow does not match, ctr_of = " & NATURAL'image(ctr_of) & ", out_of = " & NATURAL'image(out_of)                     SEVERITY ERROR;
+    END IF;
+    ASSERT out_mosi.wrdata(c_out_data_w-1 DOWNTO 0) = c_total_vector(c_out_data_w*out_data_cnt-1 DOWNTO c_out_data_w*(out_data_cnt-1))    REPORT "Data does not match, out_data_cnt = " & NATURAL'image(out_data_cnt)                                                                   SEVERITY ERROR;
+  END IF;
+  END PROCESS;
+
+
+  -- DUT
+  u_ddrctrl : ENTITY work.ddrctrl
+  GENERIC MAP (
+    g_tech_ddr        => g_tech_ddr,
+    g_sim_model       => g_sim_model,
+    g_nof_streams     => g_nof_streams,
+    g_data_w          => g_data_w
+  )
+  PORT MAP (
+    clk               => clk,
+    rst               => rst,
+    in_sosi_arr       => in_sosi_arr,
+    out_of            => out_of,
+    out_mosi          => out_mosi
+  );
+
+END tb;
diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_address_counter.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_address_counter.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a17f098b594c673887acdc59f982a8dd87d515f2
--- /dev/null
+++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_address_counter.vhd
@@ -0,0 +1,193 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2022
+-- 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: Job van Wee
+-- Purpose: Self checking and self-stopping tb for ddrctrl_address_counter.vhd
+-- Usage:
+-- > run -a
+
+LIBRARY IEEE, common_lib, technology_lib, tech_ddr_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE tech_ddr_lib.tech_ddr_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_pkg.ALL;
+
+ENTITY tb_ddrctrl_address_counter IS
+  GENERIC (
+    
+    g_tech_ddr                : t_c_tech_ddr    := c_tech_ddr4_8g_1600m;                    -- type of memory
+    g_sim_model               : BOOLEAN         := TRUE;                                    -- determens if this is a simulation
+    g_sim_length              : NATURAL         := 52                                       -- determens the length of the duration of the test
+
+  );
+END tb_ddrctrl_address_counter;
+
+ARCHITECTURE tb OF tb_ddrctrl_address_counter IS
+
+  -- constants for running the testbench
+  CONSTANT  c_clk_freq        : NATURAL         := 200;                                     -- clock frequency in MHz
+  CONSTANT  c_clk_period      : TIME            := (10**6/c_clk_freq)*1 ps;                 -- clock period, 5 ns
+
+  -- constants for running the test
+  CONSTANT  c_data_w          : NATURAL         := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- in and output data vector with, 576
+  CONSTANT  c_adr_w           : NATURAL         := 4;                                       -- address with in simulation
+  CONSTANT  c_adr_size        : NATURAL         := 2**c_adr_w;                              -- address size in simulation
+
+
+  -- input signals for ddrctrl_address_counter.vhd
+  SIGNAL    clk               : STD_LOGIC       := '1';
+  SIGNAL    rst               : STD_LOGIC       := '0';
+  SIGNAL    q_rst             : STD_LOGIC       := '0';
+  SIGNAL    q_q_rst           : STD_LOGIC       := '0';
+  SIGNAL    in_sosi           : t_dp_sosi       := c_dp_sosi_init;                          -- signal which is the input for ddrctrl_address_counter.vhd
+  SIGNAL    in_of             : NATURAL         := 0;                                       -- signal which contains the amount of overflow
+
+  -- output signal from ddrctrl_address_counter.vhd
+  SIGNAL    out_mosi          : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst;                     -- signal which is the output from ddrctrl_address_counter.vhd
+  SIGNAL    out_of            : NATURAL         := 0;                                       -- signal which is the output from ddrctrl_address_counter.vhd
+
+  -- testbench signals
+  SIGNAL    tb_end            : STD_LOGIC       := '0';                                     -- signal to turn the testbench off
+  SIGNAL    in_data           : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0) := (OTHERS => '0');   -- signal which contains the data that is set as input
+  SIGNAL    q_in_data         : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0) := (OTHERS => '0');   -- signal which contains the data that is set as input with a delay of 1 clockcycle
+  SIGNAL    q_q_in_data       : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0) := (OTHERS => '0');   -- signal which contains the data that is set as input with a delay of 2 clockcycles
+  SIGNAL    in_data_enable    : STD_LOGIC       := '0';                                     -- signal to determen if in_data is ready for reading
+  SIGNAL    q_in_data_enable  : STD_LOGIC       := '0';                                     -- signal to determen if in_data is ready for reading with a delay of 1 clockcycle
+  SIGNAL    q_q_in_data_enable: STD_LOGIC       := '0';                                     -- signal to determen if in_data is ready for reading with a delay of 2 clockcycles
+  SIGNAL    q_in_of           : NATURAL         := 0;                                       -- signal which contains the amount of overflow with a delay of 1 clockcycle
+  SIGNAL    q_q_in_of         : NATURAL         := 0;                                       -- signal which contains the amount of overflow with a delay of 2 clockcycles
+  SIGNAL    lag_due_reset     : NATURAL         := 0;                                       -- signal to hold the address lag after a reset
+  SIGNAL    q_lag_due_reset   : NATURAL         := 0;                                       -- signal to hold the address lag after a reset with a delay of 1 clockcycle
+
+BEGIN
+
+  -- wiring the input signals to the inputs of the testbench
+  in_sosi.data(c_data_w-1 DOWNTO 0) <= in_data(c_data_w-1 DOWNTO 0);
+  in_sosi.valid                     <= in_data_enable;
+
+  -- generating clock
+  clk <= NOT clk OR tb_end AFTER c_clk_period/2;
+
+  -- excecuting the test
+  p_test : PROCESS
+  BEGIN
+
+    -- initialize inputs
+    tb_end            <= '0';
+    in_data           <= (OTHERS => '0');
+    in_data_enable    <= '0';
+    WAIT UNTIL rising_edge(clk);
+
+    -- changing inputs to start the address counting
+    FOR I IN 0 TO g_sim_length-1 LOOP
+      in_data_enable  <= '1';
+      in_data         <= NOT in_data;
+      in_of           <= in_of + 1;
+      WAIT FOR c_clk_period*1;
+      in_data_enable  <= '0';
+      WAIT FOR c_clk_period*2;
+    END LOOP;
+
+    -- stopping the test
+    WAIT FOR c_clk_period*4;
+    tb_end            <= '1';
+    ASSERT FALSE                                                                      REPORT "Test: OK"                                                                                                                           SEVERITY FAILURE;
+  END PROCESS;
+
+  -- generating compare data for out_mosi
+  p_out_mosi : PROCESS
+  BEGIN
+    WAIT UNTIL rising_edge(clk);
+    if rising_edge(clk) THEN
+      q_q_in_data_enable <= q_in_data_enable;
+      q_q_in_data        <= q_in_data;
+      q_q_in_of          <= q_in_of;
+      q_q_rst            <= q_rst;
+      q_in_data_enable   <= in_data_enable;
+      q_in_data          <= in_data;
+      q_in_of            <= in_of;
+      q_lag_due_reset    <= lag_due_reset;
+      q_rst              <= rst;
+    END IF;
+    IF q_rst = '1' THEN
+      IF lag_due_reset + TO_UINT(out_mosi.address) >= c_adr_size THEN
+        lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address)-c_adr_size;
+      ELSE
+        lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address);
+      END IF;
+    END IF;
+  END PROCESS;
+      
+
+  -- verifying if the data is correct and if valid is correct
+  p_verify_data_valid : PROCESS
+  BEGIN
+    WAIT UNTIL rising_edge(clk);
+    IF rising_edge(clk) THEN
+      ASSERT q_q_in_data(c_data_w-1 DOWNTO 0) = out_mosi.wrdata(c_data_w-1 DOWNTO 0)  REPORT "in_sosi.data does not match out_mosi.wrdata"                                                                                        SEVERITY ERROR;
+      ASSERT q_q_in_data_enable               = out_mosi.wr                           REPORT "in_sosi.valid does not match out_mosi.wr"                                                                                           SEVERITY ERROR;
+      ASSERT q_q_in_of                        = out_of                                REPORT "in_of does not match out_of"                                                                                                        SEVERITY ERROR;
+    END IF;
+  END PROCESS;
+
+  -- excecuting the reset test
+  p_test_reset : PROCESS
+  BEGIN
+    rst <= '0';
+    WAIT FOR c_clk_period*((c_adr_size*4)+3);
+    rst <= '1';
+    WAIT FOR c_clk_period*1;
+  END PROCESS;
+
+  -- verifying if the address is correct by keeping track of the address
+  p_verify_address : PROCESS
+  BEGIN
+    FOR I IN 0 TO c_adr_size-1 LOOP
+      IF I >= q_lag_due_reset THEN
+        ASSERT I-q_lag_due_reset              = TO_UINT(out_mosi.address)             REPORT "Wrong address, 1, I = " & NATURAL'image(I-q_lag_due_reset) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address))              SEVERITY ERROR;
+      ELSE
+        ASSERT (I-q_lag_due_reset)+c_adr_size = TO_UINT(out_mosi.address)             REPORT "Wrong address, 2, I = " & NATURAL'image((I-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address)) SEVERITY ERROR;
+      END IF;
+      WAIT UNTIL out_mosi.wr = '1';     
+      IF q_q_rst = '1' THEN
+        WAIT UNTIL out_mosi.wr = '1';
+      END IF;
+    END LOOP;
+  END PROCESS;
+
+
+  -- DUT
+  u_ddrctrl_address_counter : ENTITY work.ddrctrl_address_counter
+  GENERIC MAP (
+    g_tech_ddr        => g_tech_ddr,
+    g_sim_model       => g_sim_model
+  )
+  PORT MAP (
+    clk               => clk,
+    rst               => rst,
+    in_sosi           => in_sosi,
+    in_of             => in_of,
+
+    out_mosi          => out_mosi,
+    out_of            => out_of
+  );
+
+END tb;
diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_pack.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_pack.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..6f81b6cb22c88159a2153680f467c39799fa06fe
--- /dev/null
+++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_pack.vhd
@@ -0,0 +1,142 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2022
+-- 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: Job van Wee
+-- Purpose: Self checking and self-stopping tb for ddrctrl_pack.vhd
+-- Usage:
+-- > run -a
+
+LIBRARY IEEE, common_lib, technology_lib, tech_ddr_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE IEEE.MATH_REAL.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE tech_ddr_lib.tech_ddr_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_pkg.ALL;
+
+ENTITY tb_ddrctrl_pack IS
+  GENERIC (
+
+    g_nof_streams             : POSITIVE                                    := 12;                                -- number of input streams
+    g_data_w                  : NATURAL                                     := 14;                                -- data with of input data vectors
+    g_sim_length              : NATURAL                                     := 52                                 -- determens the lengt of the duration of the test
+
+ );
+END tb_ddrctrl_pack;
+
+ARCHITECTURE tb OF tb_ddrctrl_pack IS
+
+  -- constants for running the testbench
+  CONSTANT  c_clk_freq        : NATURAL                                     := 200;                               -- clock frequency in MHz
+  CONSTANT  c_clk_period      : TIME                                        := (10**6/c_clk_freq)*1 ps;           -- clock priod, 5 ns
+
+  -- constant for readability
+  CONSTANT  c_out_data_w      : NATURAL                                     := g_nof_streams*g_data_w;            -- output data with, 168
+
+  -- function for making test vector
+  FUNCTION c_testv_init RETURN STD_LOGIC_VECTOR IS
+    VARIABLE temp             : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0);
+  BEGIN
+    FOR I IN 0 TO g_nof_streams-1 LOOP
+      temp(g_data_w*(I+1)-1 DOWNTO g_data_w*I) := TO_UVEC(I, g_data_w);
+    END LOOP;
+    RETURN temp;
+  END FUNCTION c_testv_init;
+
+  -- constants for running the test
+  CONSTANT  c_testv           : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0)   := c_testv_init;                      -- testvector which contains a number for each stream, so the data of stream 6 will look like ...00110
+
+
+  -- input signals for ddrctrl_pack.vhd
+  SIGNAL    clk               : STD_LOGIC                                   := '1';                               -- clock signal
+  SIGNAL    in_sosi_arr       : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0)     := (OTHERS => c_dp_sosi_init);        -- input signal for ddrctrl_pack.vhd 
+
+  -- output singal from ddrctrl_pack.vhd
+  SIGNAL    out_data          : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0);                                        -- output signal from ddrctrl_pack.vhd
+
+  -- testbench signal
+  SIGNAL    tb_end            : STD_LOGIC                                   := '0';                               -- signal to turn the testbench off
+
+BEGIN
+
+  -- generating clock
+  clk               <= NOT clk OR tb_end AFTER c_clk_period/2;
+
+  -- excecuting the test
+  p_test : PROCESS
+  BEGIN
+
+    -- starting the test
+    tb_end            <= '0';
+    WAIT UNTIL rising_edge(clk);
+    WAIT FOR c_clk_period*2;
+
+
+    -- the input data vectors get filled with the corresponding number
+    fill_in_sosi_arr : FOR I IN 0 TO g_nof_streams-1 LOOP
+      in_sosi_arr(I).data(g_data_w - 1 DOWNTO 0)   <= c_testv(g_data_w * (I + 1) - 1 DOWNTO g_data_w * I);
+    END LOOP;
+
+
+    -- the numbers get cycled trough the input vectors
+    change_in_sosi_arr : FOR J IN 0 TO g_sim_length-1 LOOP
+      WAIT FOR c_clk_period*1;
+      in_sosi_arr(0).data(g_data_w - 1 DOWNTO 0)   <= in_sosi_arr(g_nof_streams-1).data(g_data_w - 1 DOWNTO 0);
+      loop_switch_data : FOR I IN 1 TO g_nof_streams-1 LOOP
+        in_sosi_arr(I).data(g_data_w - 1 DOWNTO 0) <= in_sosi_arr(I-1).data(g_data_w - 1 DOWNTO 0);
+      END LOOP;
+    END LOOP;  
+
+    -- stopping the testbench
+    WAIT FOR c_clk_period*4;
+    tb_end <= '1';
+    ASSERT FALSE                                                                                               REPORT "Test: OK"                                     SEVERITY FAILURE;
+  END PROCESS;
+
+  -- verification by checking if the input vectors equel the corresponding index of the output vector
+  p_verify : PROCESS
+  BEGIN
+    WAIT UNTIL rising_edge(clk);
+    IF rising_edge(clk) THEN
+      check_data : FOR I IN 0 TO g_nof_streams - 1 LOOP
+        ASSERT out_data(g_data_w * (I + 1) - 1 DOWNTO g_data_w * I) = in_sosi_arr(I).data(g_data_w-1 DOWNTO 0) REPORT "Data does not match, I = " & NATURAL'image(I) SEVERITY ERROR;
+      END LOOP;
+    END IF;
+  END PROCESS;
+
+  -- DUT
+  u_ddrctrl_pack : ENTITY work.ddrctrl_pack
+  GENERIC MAP (
+    g_nof_streams     => g_nof_streams,
+    g_data_w          => g_data_w
+  )
+  PORT MAP (
+    in_sosi_arr       => in_sosi_arr,
+
+    out_data          => out_data
+  );
+
+END tb;
+
+
+
+
+
diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_repack.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_repack.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..395cb8896128ab33aa01da54733982f8a855e143
--- /dev/null
+++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_repack.vhd
@@ -0,0 +1,152 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2022
+-- 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: Job van Wee
+-- Purpose: Self checking and self-stopping tb for ddrctrl_repack.vhd
+-- Usage:
+-- > run -a
+
+LIBRARY IEEE, common_lib, technology_lib, tech_ddr_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE IEEE.MATH_REAL.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE tech_ddr_lib.tech_ddr_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_pkg.ALL;
+
+ENTITY tb_ddrctrl_repack IS
+  GENERIC (
+
+    g_tech_ddr                : t_c_tech_ddr                                           := c_tech_ddr4_8g_1600m;                    -- type of memory
+    g_in_data_w               : NATURAL                                                := 168;                                     -- input data vector with
+    g_sim_lengt               : NATURAL                                                := 52                                       -- amount of times there wil be input data for ddrctrl_repack in this testbench
+
+  );
+END tb_ddrctrl_repack;
+
+ARCHITECTURE tb OF tb_ddrctrl_repack IS
+
+  -- constants for running testbench
+  CONSTANT  c_clk_freq        : NATURAL                                                := 200;                                     -- clock freqency in MHz
+  CONSTANT  c_clk_period      : TIME                                                   := (10**6 / c_clk_freq) * 1 ps;             -- clock period, 5 ns
+
+  -- constant for readability
+  CONSTANT  c_out_data_w      : NATURAL                                                := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- output data vector with, 576
+
+  -- function for making total data vector
+  FUNCTION  c_total_vector_init RETURN STD_LOGIC_VECTOR IS
+    VARIABLE temp             : STD_LOGIC_VECTOR(g_in_data_w*g_sim_lengt-1 DOWNTO 0);
+  BEGIN
+    FOR I IN 0 TO g_sim_lengt-1 LOOP
+      temp(g_in_data_w*(I+1)-1 DOWNTO g_in_data_w*I) := TO_UVEC(I, g_in_data_w);
+    END LOOP;
+    RETURN temp;
+  END FUNCTION c_total_vector_init;
+
+  -- constant for running the test
+  CONSTANT  c_total_vector    : STD_LOGIC_VECTOR(g_in_data_w*g_sim_lengt-1 DOWNTO 0)   := c_total_vector_init;                     -- vector which contains all input data vectors to make it easy to fill ctr_vector
+
+
+  -- input signals for ddrctrl_repack.vhd
+  SIGNAL    clk               : STD_LOGIC                                              := '1';                                     -- clock signal
+  SIGNAL    rst               : STD_LOGIC                                              := '0';                                     -- reset signal
+  SIGNAL    in_data           : STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0)               := (OTHERS => '0');                         -- input data signal for ddrctrl_repack
+
+  -- output signals from ddrctrl_repack.vhd
+  SIGNAL    out_of            : NATURAL                                                := 0;                                       -- output signal from ddrctrl_repack to determen how high the overflow is
+  SIGNAL    out_sosi          : t_dp_sosi                                              := c_dp_sosi_init;                          -- output data signal form ddrctrl_repack
+
+  -- testbench signal
+  SIGNAL    tb_end            : STD_LOGIC                                              := '0';                                     -- signal to turn the testbench off
+
+  -- singals for running the test
+  SIGNAL    in_data_cnt       : NATURAL                                                := 0;                                       -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd
+  SIGNAL    test_running      : STD_LOGIC                                              := '0';                                     -- signal to tell wheter the testing has started
+
+BEGIN
+
+  -- Generating clock
+  clk                 <= NOT clk OR tb_end AFTER c_clk_period/2;
+
+  -- Excecuting the test
+  p_test : PROCESS
+  BEGIN
+
+    -- start the test
+    tb_end            <= '0';
+    WAIT UNTIL rising_edge(clk);                                                                                                   -- align to rising edge
+    WAIT FOR c_clk_period*5;
+    rst <= '1';
+    WAIT FOR c_clk_period*1;
+    rst <= '0';
+    WAIT FOR c_clk_period*1;
+    test_running      <= '1';                                                                                                      -- start of test
+
+    -- filling the input vector g_sim_lengt amount of times
+    make_in_data : FOR I IN 0 TO g_sim_lengt-1 LOOP
+      in_data(g_in_data_w-1 DOWNTO 0) <= TO_UVEC(I, g_in_data_w);
+      WAIT FOR c_clk_period*1;
+      in_data_cnt     <= in_data_cnt + 1;
+    END LOOP;
+    test_running      <= '0';
+
+    -- stopping the testbench
+    WAIT FOR c_clk_period*5;
+    tb_end            <= '1';
+    ASSERT FALSE                                                                                                                      REPORT "Test: OK"                                                                                                           SEVERITY FAILURE;
+  END PROCESS;
+
+  -- verification by checking if the input vectors are correctly put into the output vector and the amount of overflow is as expected
+  p_verify : PROCESS
+
+  VARIABLE  ctr_of            : NATURAL                                                := 0;
+  VARIABLE  out_data_cnt      : NATURAL                                                := 0;
+
+  BEGIN
+  WAIT UNTIL rising_edge(clk);
+  IF test_running = '1' AND out_sosi.valid = '1' THEN
+    out_data_cnt      := out_data_cnt+1;
+    IF out_data_cnt mod 2 = 0 THEN
+      ctr_of := g_in_data_w*in_data_cnt-c_out_data_w*out_data_cnt;
+      ASSERT ctr_of                               = out_of                                                                              REPORT "The amount of overflow does not match, ctr_of = " & NATURAL'image(ctr_of) & ", out_of = " & NATURAL'image(out_of) SEVERITY ERROR;
+    END IF;
+    ASSERT out_sosi.data(c_out_data_w-1 DOWNTO 0) = c_total_vector(c_out_data_w*out_data_cnt-1 DOWNTO c_out_data_w*(out_data_cnt-1))    REPORT "Data does not match, out_data_cnt = " & NATURAL'image(out_data_cnt)                                               SEVERITY ERROR;
+  END IF;
+  END PROCESS;
+
+
+  -- DUT
+  u_ddrctrl_repack : ENTITY work.ddrctrl_repack
+  GENERIC MAP (
+    g_tech_ddr        => g_tech_ddr,
+    g_in_data_w       => g_in_data_w
+  )
+  PORT MAP (
+    clk               => clk,
+    rst               => rst,
+    in_data           => in_data,
+
+    out_of            => out_of,
+    out_sosi          => out_sosi
+  );
+
+END tb;
+