diff --git a/libraries/technology/ddr/hdllib.cfg b/libraries/technology/ddr/hdllib.cfg
index dae97d24a3842626cfb5b34752e9c6d11c16357d..0f67ecdab8960b443af579ffc1f3211dcdad7f9c 100644
--- a/libraries/technology/ddr/hdllib.cfg
+++ b/libraries/technology/ddr/hdllib.cfg
@@ -14,6 +14,7 @@ hdl_lib_technology =
 
 synth_files =
     tech_ddr_pkg.vhd
+    sim_ddr.vhd
     tech_ddr_component_pkg.vhd
     tech_ddr_stratixiv.vhd
     tech_ddr_arria10.vhd
diff --git a/libraries/technology/ddr/sim_ddr.vhd b/libraries/technology/ddr/sim_ddr.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..f8ec34019ba1e27c1eb3a358e471ce5bb8ee53a2
--- /dev/null
+++ b/libraries/technology/ddr/sim_ddr.vhd
@@ -0,0 +1,159 @@
+--------------------------------------------------------------------------------
+--
+-- Copyright (C) 2015
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.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: Functional simulation model of both the DDR driver and the DDR memory.
+-- Description:
+--   The component also supports different types of DDR, so DDR3 and DDR4.
+-- Remark:
+-- . It is assumed that the user only performs burst reads/writes!
+-- . Modelsim raises warning 3391 when the DDR memory set by c_nof_addr is to big to fit in PC RAM.
+--   Use 'verror 3391' to display the help. This means that the computer becomes too slow due to
+--   page swapping to disk. Even loading the simulation becomes slow.
+
+LIBRARY IEEE, common_lib, technology_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE technology_lib.technology_select_pkg.ALL;
+USE work.tech_ddr_pkg.ALL;
+
+ENTITY sim_ddr IS
+  GENERIC (
+    g_tech_ddr        : t_c_tech_ddr
+  );
+  PORT (
+    -- PLL reference clock
+    ref_clk           : IN    STD_LOGIC;
+    ref_rst           : IN    STD_LOGIC;
+
+    -- Controller user interface
+    ctlr_gen_clk      : OUT   STD_LOGIC;
+    ctlr_gen_rst      : OUT   STD_LOGIC;
+    ctlr_gen_clk_2x   : OUT   STD_LOGIC;
+    ctlr_gen_rst_2x   : OUT   STD_LOGIC;
+
+    ctlr_mosi         : IN    t_mem_ctlr_mosi;
+    ctlr_miso         : OUT   t_mem_ctlr_miso
+  );
+END sim_ddr;
+
+
+ARCHITECTURE str OF sim_ddr IS
+
+  -- DDR size and controller data width
+  CONSTANT c_nof_addr : NATURAL := 2**func_tech_ddr_ctlr_address_w(g_tech_ddr);  --8192;
+  CONSTANT c_dat_w    : NATURAL := func_tech_ddr_ctlr_data_w(g_tech_ddr);  --256;
+
+  -- DDR memory
+  TYPE t_mem_arr IS ARRAY(0 TO c_nof_addr-1) OF STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0);
+
+  SIGNAL sim_clk       : STD_LOGIC;
+  SIGNAL sim_rst       : STD_LOGIC;
+  SIGNAL sim_ctlr_mosi : t_mem_ctlr_mosi;
+
+  SIGNAL address       : NATURAL;
+
+BEGIN
+
+  -- Prevent delta delay issues by using a re-assigned clk both internally (sim_clk) and externally (ctrl_gen_clk)
+  ctlr_gen_clk <= ref_clk;
+  ctlr_gen_rst <= ref_rst;
+  sim_clk      <= ref_clk;
+  sim_rst      <= ref_rst;
+
+  ctlr_miso.done     <= '0' , '1' AFTER 1 ns;
+  ctlr_miso.cal_ok   <= '0' , '1' AFTER 1 ns;
+  ctlr_miso.cal_fail <= '0';
+
+  -- Delay the control one cycle here so p_mem_access can update its outputs immediately
+  p_clk : PROCESS(sim_clk)
+  BEGIN
+    IF rising_edge(sim_clk) THEN
+      sim_ctlr_mosi <= ctlr_mosi;
+    END IF;
+  END PROCESS;
+
+  p_mem_access : PROCESS(sim_clk, sim_ctlr_mosi)
+    VARIABLE v_enable_model  : BOOLEAN := FALSE;
+    VARIABLE v_mem_arr       : t_mem_arr := (OTHERS=>(OTHERS=>'0'));
+    VARIABLE v_address       : NATURAL := 0;
+    VARIABLE v_wr_bursting   : BOOLEAN := FALSE;
+    VARIABLE v_rd_bursting   : BOOLEAN := FALSE;
+    VARIABLE v_burst_cnt     : NATURAL := 0;
+    VARIABLE v_burst_size    : NATURAL := 0;
+  BEGIN
+
+    -- Don't waste simulation time when user does not access the model anyway
+    IF v_enable_model = FALSE THEN
+      ctlr_miso.waitrequest_n <= '1'; 
+      IF sim_ctlr_mosi.burstbegin='1' THEN
+        v_enable_model := TRUE;
+      END IF;
+    END IF;
+
+    IF v_enable_model = TRUE THEN
+      IF rising_edge(sim_clk) THEN
+  
+        ctlr_miso.rdval <= '0'; 
+        ctlr_miso.waitrequest_n <= '1'; 
+  
+        -- Access: burst begin
+        IF sim_ctlr_mosi.burstbegin='1' THEN
+          IF sim_ctlr_mosi.wr='1' THEN
+            v_wr_bursting := TRUE;
+          ELSIF sim_ctlr_mosi.rd='1' THEN
+            v_rd_bursting := TRUE;
+          END IF;
+          v_address     := TO_UINT(sim_ctlr_mosi.address);
+          v_burst_size  := TO_UINT(sim_ctlr_mosi.burstsize);
+          v_burst_cnt   := 0;
+        END IF;
+    
+        IF v_wr_bursting=TRUE OR v_rd_bursting=TRUE THEN
+          IF sim_ctlr_mosi.wr='1' THEN -- Write
+            v_mem_arr(v_address) := sim_ctlr_mosi.wrdata(c_dat_w-1 DOWNTO 0);
+            v_address   := v_address+1;
+            v_burst_cnt := v_burst_cnt +1;
+          ELSIF v_rd_bursting=TRUE THEN -- Read
+            ctlr_miso.rddata(c_dat_w-1 DOWNTO 0) <= v_mem_arr(v_address);  
+            ctlr_miso.rdval <= '1';
+            ctlr_miso.waitrequest_n <= '0';
+            v_address   := v_address+1;
+            v_burst_cnt := v_burst_cnt +1;
+          END IF;
+    
+          IF v_burst_cnt = v_burst_size THEN
+            v_wr_bursting := FALSE;
+            v_rd_bursting := FALSE;
+          END IF;
+        END IF;
+    
+        address <= v_address;
+  
+      END IF;
+    END IF;
+
+  END PROCESS;
+ 
+END str;
+
diff --git a/libraries/technology/ddr/tech_ddr.vhd b/libraries/technology/ddr/tech_ddr.vhd
index 03961ea0085e885f76acecd6d7d76ecc2ea39c9c..b19e6f9ad1378168ca618ff8aa1ea89d1627eac9 100644
--- a/libraries/technology/ddr/tech_ddr.vhd
+++ b/libraries/technology/ddr/tech_ddr.vhd
@@ -35,7 +35,7 @@ USE work.tech_ddr_pkg.ALL;
 
 ENTITY tech_ddr IS
   GENERIC (
-    g_sim_model            : BOOLEAN := FALSE; -- TRUE: use fast behavioural model, requires no external memory (uses memory array).
+    g_sim_model            : BOOLEAN := FALSE;  -- TRUE: use fast behavioural model, requires no external memory (uses memory array).
     g_technology           : NATURAL := c_tech_select_default;
     g_tech_ddr             : t_c_tech_ddr
   );
@@ -71,8 +71,8 @@ END tech_ddr;
 
 ARCHITECTURE str OF tech_ddr IS
 
-  CONSTANT c_nof_addr : NATURAL := 8192;
-  CONSTANT c_dat_w    : NATURAL := 256;
+  CONSTANT c_nof_addr : NATURAL := 2**func_tech_ddr_ctlr_address_w(g_tech_ddr);  --8192;
+  CONSTANT c_dat_w    : NATURAL := func_tech_ddr_ctlr_data_w(g_tech_ddr);  --256;
 
   TYPE t_mem_arr IS ARRAY(0 TO c_nof_addr-1) OF STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0);
 
@@ -108,91 +108,28 @@ BEGIN
   END GENERATE;
  
   -----------------------------------------------------------------------------
-  -- Functional simulation model
-  -- . Note: is it assumed that the user only performs burst reads/writes!
+  -- Functional simulation model of both the DDR controller and the DDR memory
   -----------------------------------------------------------------------------
   gen_sim_model : IF g_sim_model=TRUE GENERATE
-    -- Prevent delta delay issues by using a re-assigned clk both internally 
-    -- (sim_clk) and externally (ctrl_gen_clk)
-    ctlr_gen_clk <= ref_clk;
-    ctlr_gen_rst <= ref_rst;
-    sim_clk      <= ref_clk;
-    sim_rst      <= ref_rst;
-  
-    ctlr_miso.done   <= '0' , '1' AFTER 1000 ps;
-    ctlr_miso.cal_ok <= '0' , '1' AFTER 1000 ps;
-  
-    -- Delay the control one cycle here so p_mem_access can update its outputs
-    -- immediately
-    p_clk : PROCESS(sim_clk)
-    BEGIN
-      IF rising_edge(sim_clk) THEN
-        sim_ctlr_mosi <= ctlr_mosi;
-      END IF;
-    END PROCESS;
-  
-    p_mem_access : PROCESS(sim_clk, sim_ctlr_mosi)
-      VARIABLE v_enable_model  : BOOLEAN := FALSE;
-      VARIABLE v_mem_arr       : t_mem_arr := (OTHERS=>(OTHERS=>'0'));
-      VARIABLE v_address       : NATURAL := 0;
-      VARIABLE v_wr_bursting   : BOOLEAN := FALSE;
-      VARIABLE v_rd_bursting   : BOOLEAN := FALSE;
-      VARIABLE v_burst_cnt     : NATURAL := 0;
-      VARIABLE v_burst_size    : NATURAL := 0;
-    BEGIN
-  
-      -- Don't waste simulation time when user does not use the model anyway
-      IF v_enable_model = FALSE THEN
-        ctlr_miso.waitrequest_n <= '1'; 
-        IF sim_ctlr_mosi.burstbegin='1' THEN
-          v_enable_model := TRUE;
-        END IF;
-      END IF;
-  
-      IF v_enable_model = TRUE THEN
-        IF rising_edge(sim_clk) THEN
+    u0 : ENTITY work.sim_ddr
+    GENERIC MAP (
+      g_tech_ddr        => g_tech_ddr
+    )
+    PORT MAP (
+      -- PLL reference clock
+      ref_clk           => ref_clk,
+      ref_rst           => ref_rst,
     
-          ctlr_miso.rdval <= '0'; 
-          ctlr_miso.waitrequest_n <= '1'; 
+      -- Controller user interface
+      ctlr_gen_clk      => ctlr_gen_clk,
+      ctlr_gen_rst      => ctlr_gen_rst,
+      ctlr_gen_clk_2x   => ctlr_gen_clk_2x,
+      ctlr_gen_rst_2x   => ctlr_gen_rst_2x,
     
-          -- Access: burst begin
-          IF sim_ctlr_mosi.burstbegin='1' THEN
-            IF sim_ctlr_mosi.wr='1' THEN
-              v_wr_bursting := TRUE;
-            ELSIF sim_ctlr_mosi.rd='1' THEN
-              v_rd_bursting := TRUE;
-            END IF;
-            v_address     := TO_UINT(sim_ctlr_mosi.address);
-            v_burst_size  := TO_UINT(sim_ctlr_mosi.burstsize);
-            v_burst_cnt   := 0;
-          END IF;
-      
-          IF v_wr_bursting=TRUE OR v_rd_bursting=TRUE THEN
-            IF sim_ctlr_mosi.wr='1' THEN -- Write
-              v_mem_arr(v_address) := sim_ctlr_mosi.wrdata(c_dat_w-1 DOWNTO 0);
-              v_address   := v_address+1;
-              v_burst_cnt := v_burst_cnt +1;
-            ELSIF v_rd_bursting=TRUE THEN -- Read
-              ctlr_miso.rddata(c_dat_w-1 DOWNTO 0) <= v_mem_arr(v_address);  
-              ctlr_miso.rdval <= '1';
-              ctlr_miso.waitrequest_n <= '0';
-              v_address   := v_address+1;
-              v_burst_cnt := v_burst_cnt +1;
-            END IF;
-      
-            IF v_burst_cnt = v_burst_size THEN
-              v_wr_bursting := FALSE;
-              v_rd_bursting := FALSE;
-            END IF;
-          END IF;
-      
-          address <= v_address;
-    
-        END IF;
-      END IF;
-  
-    END PROCESS;
+      ctlr_mosi         => ctlr_mosi,
+      ctlr_miso         => ctlr_miso
+    );
   END GENERATE;
- 
+  
 END str;