diff --git a/libraries/technology/ddr/tech_ddr_pkg.vhd b/libraries/technology/ddr/tech_ddr_pkg.vhd
index d0644d2302400808fd9563c61f9135ed7e55ac95..12338bd0e4a32bfe7572c2b45763fb84584dae4a 100644
--- a/libraries/technology/ddr/tech_ddr_pkg.vhd
+++ b/libraries/technology/ddr/tech_ddr_pkg.vhd
@@ -66,11 +66,14 @@ PACKAGE tech_ddr_pkg IS
   FUNCTION func_tech_ddr_ctlr_address_w(c_ddr : t_c_tech_ddr) RETURN NATURAL;  -- return DDR address width for the controller data at the by rsl=4 reduced rate
   FUNCTION func_tech_ddr_ctlr_data_w(   c_ddr : t_c_tech_ddr) RETURN NATURAL;  -- return DDR    data width for the controller data at the by rsl=4 reduced rate
   FUNCTION func_tech_ddr_module_size(   c_ddr : t_c_tech_ddr) RETURN NATURAL;  -- return DDR module size in GByte
+
+  FUNCTION func_tech_ddr_sim_size(c_ddr : t_c_tech_ddr; sim_ctrl_addr_w : NATURAL) RETURN t_c_tech_ddr; -- derive sim_ddr from c_ddr (or alternatively use predefined c_tech_ddr*_sim)
   
   --                                                                                                    a   a                               cs cs
   --                                                                 name    mts   master rank      a   row col ba dq  dqs dm dbi bg ck cke w  w_w  odt term rsl rsl_w cqd burst burst_w
   CONSTANT c_tech_ddr3_max                        : t_c_tech_ddr := ("none",  800,  TRUE, "DUAL  ", 16, 16, 11, 3, 64, 8,  8, 0,  0, 2, 2,  2, 1,   2,  14,  4,  2,    4,  64,   7);  -- maximum ranges for record field definitions
   
+  -- use predefined c_tech_ddr3_sim or derive it using func_tech_ddr_sim_size()
   CONSTANT c_tech_ddr3_sim_8k                     : t_c_tech_ddr := ("DDR3",  800,  TRUE, "DUAL  ", 10,  1, 10, 3, 64, 8,  8, 0,  0, 2, 2,  2, 1,   2,  14,  4,  2,    4,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col - rsl_w)
   CONSTANT c_tech_ddr3_sim_16k                    : t_c_tech_ddr := ("DDR3",  800,  TRUE, "DUAL  ", 10,  2, 10, 3, 64, 8,  8, 0,  0, 2, 2,  2, 1,   2,  14,  4,  2,    4,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col - rsl_w)
   CONSTANT c_tech_ddr3_sim_128k                   : t_c_tech_ddr := ("DDR3",  800,  TRUE, "DUAL  ", 10,  5, 10, 3, 64, 8,  8, 0,  0, 2, 2,  2, 1,   2,  14,  4,  2,    4,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col - rsl_w)
@@ -85,6 +88,7 @@ PACKAGE tech_ddr_pkg IS
 --CONSTANT c_tech_ddr4_max                        : t_c_tech_ddr := ("none", 1600,  TRUE, "DUAL  ", 17, 15, 10, 2, 72, 9,  0, 9,  2, 1, 1,  1, 0,   1,   0,  8,  3,    8,  64,   7);  -- maximum ranges for record field definitions
   CONSTANT c_tech_ddr4_max                        : t_c_tech_ddr := ("none", 1600,  TRUE, "DUAL  ", 17, 15, 10, 2, 72, 9,  0, 9,  2, 2, 2,  2, 1,   2,   0,  8,  3,    8,  64,   7);  -- maximum ranges for record field definitions
   
+  -- use predefined c_tech_ddr4_sim or derive it using func_tech_ddr_sim_size()
   CONSTANT c_tech_ddr4_sim_4k                     : t_c_tech_ddr := ("DDR4", 1600,  TRUE, "DUAL  ", 10,  1, 10, 2, 72, 9,  0, 9,  2, 1, 1,  1, 0,   1,   0,  8,  3,    8,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col + bg_w - rsl_w)
   CONSTANT c_tech_ddr4_sim_8k                     : t_c_tech_ddr := ("DDR4", 1600,  TRUE, "DUAL  ", 10,  2, 10, 2, 72, 9,  0, 9,  2, 1, 1,  1, 0,   1,   0,  8,  3,    8,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col + bg_w - rsl_w)
   CONSTANT c_tech_ddr4_sim_16k                    : t_c_tech_ddr := ("DDR4", 1600,  TRUE, "DUAL  ", 10,  3, 10, 2, 72, 9,  0, 9,  2, 1, 1,  1, 0,   1,   0,  8,  3,    8,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col + bg_w - rsl_w)
@@ -219,6 +223,19 @@ PACKAGE BODY tech_ddr_pkg IS
     RETURN c_ddr.dq_w*c_ddr.rsl;                                                -- CTLR data
   END;
   
+  FUNCTION func_tech_ddr_sim_size(c_ddr : t_c_tech_ddr; sim_ctrl_addr_w : NATURAL) RETURN t_c_tech_ddr IS
+    VARIABLE v_ddr         : t_c_tech_ddr := c_ddr;
+    VARIABLE v_ctrl_addr_w : NATURAL;
+  BEGIN
+    -- adapt a_row to set number of ctrl addr, use a_row_w = 1 to derive minimal size
+    v_ddr.a_row_w := 1;
+    v_ctrl_addr_w := func_tech_ddr_ctlr_address_w(v_ddr);
+    IF sim_ctrl_addr_w > v_ctrl_addr_w THEN
+      v_ddr.a_row_w := 1 + sim_ctrl_addr_w - v_ctrl_addr_w;
+    END IF;
+    RETURN v_ddr;
+  END;
+  
   FUNCTION func_tech_ddr_module_size(c_ddr : t_c_tech_ddr) RETURN NATURAL IS
     CONSTANT c_dq_address_w       : NATURAL := func_tech_ddr_dq_address_w(c_ddr);
     CONSTANT c_dq_nof_bytes       : NATURAL := 8;  -- both dw_q = 64 and 72 are regarded as having 8 bytes (either with 8 or 9 bits per byte)