diff --git a/libraries/io/ddr/src/vhdl/io_ddr.vhd b/libraries/io/ddr/src/vhdl/io_ddr.vhd
index 5605fad0fa041a7b1d77164f878951edd8cb71ff..2c909f513954e986a03eeaf36bfbbf320147ab2e 100644
--- a/libraries/io/ddr/src/vhdl/io_ddr.vhd
+++ b/libraries/io/ddr/src/vhdl/io_ddr.vhd
@@ -32,11 +32,11 @@ ENTITY io_ddr IS
   GENERIC(
     g_technology              : NATURAL := c_tech_select_default;
     g_tech_ddr                : t_c_tech_ddr;
-    g_wr_data_w               : NATURAL := c_tech_ddr_ctlr.data_w;  
+    g_wr_data_w               : NATURAL := 32;  
     g_wr_use_ctrl             : BOOLEAN := FALSE;              -- TRUE to allow filling the WR FIFO (by disabling flush) after an EOP
-    g_wr_fifo_depth           : NATURAL := 128;                -- >=16 AND >c_tech_ddr_ctlr.maxburstsize                              , defined at read  side of write FIFO.
-    g_rd_fifo_depth           : NATURAL := 256;                -- >=16 AND >c_tech_ddr_ctlr.maxburstsize > c_ddr_ctrl_nof_latent_reads, defined at write side of read  FIFO. 
-    g_rd_data_w               : NATURAL := c_tech_ddr_ctlr.data_w;
+    g_wr_fifo_depth           : NATURAL := 128;                -- >=16 AND >g_tech_ddr.maxburstsize                              , defined at read  side of write FIFO.
+    g_rd_fifo_depth           : NATURAL := 256;                -- >=16 AND >g_tech_ddr.maxburstsize > c_ddr_ctrl_nof_latent_reads, defined at write side of read  FIFO. 
+    g_rd_data_w               : NATURAL := 32;
     g_flush_wr_fifo           : BOOLEAN := FALSE;              -- TRUE instantiates a dp_flush + controller to flush the write fifo when the driver is not ready to write
     g_flush_sop               : BOOLEAN := FALSE;
     g_flush_sop_channel       : BOOLEAN := FALSE;
@@ -47,11 +47,6 @@ ENTITY io_ddr IS
     ctlr_ref_clk       : IN    STD_LOGIC;
     ctlr_ref_rst       : IN    STD_LOGIC;
 
-    ctlr_gen_clk       : OUT   STD_LOGIC; -- Controller generated clock
-    ctlr_gen_rst       : OUT   STD_LOGIC;    
-    ctlr_gen_clk_2x    : OUT   STD_LOGIC; -- Controller generated double frequency clock
-    ctlr_gen_rst_2x    : OUT   STD_LOGIC; -- ctlr_gen_rst synchronized to ctlr_gen_clk_2x
-
     ctlr_init_done     : OUT   STD_LOGIC;
     ctlr_rdy           : OUT   STD_LOGIC;
 
@@ -74,7 +69,7 @@ ENTITY io_ddr IS
     rd_clk             : IN    STD_LOGIC;
     rd_rst             : IN    STD_LOGIC;
 
-    rd_fifo_usedw      : OUT   STD_LOGIC_VECTOR(ceil_log2(g_rd_fifo_depth * (g_tech_ddr.data_w/g_rd_data_w) )-1 DOWNTO 0);
+    rd_fifo_usedw      : OUT   STD_LOGIC_VECTOR(ceil_log2(g_rd_fifo_depth * (func_tech_ddr_ctrl_data_w(g_tech_ddr)/g_rd_data_w) )-1 DOWNTO 0);
     
     phy_in             : IN    t_tech_ddr_phy_in;
     phy_io             : INOUT t_tech_ddr_phy_io;
@@ -85,26 +80,25 @@ END io_ddr;
 
 ARCHITECTURE str OF io_ddr IS  
  
-  CONSTANT c_wr_fifo_depth : NATURAL := g_wr_fifo_depth * (g_tech_ddr.data_w/g_wr_data_w); -- Multiply fifo depth by the fifo's rd/wr width ratio to get write side depth
+  CONSTANT c_ctrl_address_w   : NATURAL := func_tech_ddr_ctrl_address_w(g_tech_ddr);
+  CONSTANT c_ctlr_data_w      : NATURAL := func_tech_ddr_ctrl_data_w(   g_tech_ddr);
+  
+  CONSTANT c_wr_fifo_depth    : NATURAL := g_wr_fifo_depth * (c_ctlr_data_w/g_wr_data_w); -- Multiply fifo depth by the fifo's rd/wr width ratio to get write side depth
 
+  CONSTANT c_ddr_ctrl_nof_latent_reads : NATURAL := 100;  -- Due to having a command cue, even after de-asserting read requests, the PHY keeps processing the cued read requests.
+                                                          -- This makes sure 100 words are still available in the read FIFO after it de-asserted its siso.ready signal towards the ddr3 read side.
+                                                          
   CONSTANT c_latency       : NATURAL := 1;
-
-  SIGNAL ctlr_burst        : STD_LOGIC; 
-  SIGNAL ctlr_burst_size   : STD_LOGIC_VECTOR(g_tech_ddr.maxburstsize_w-1 DOWNTO 0);
-  SIGNAL ctlr_address      : STD_LOGIC_VECTOR(ceil_log2(g_tech_ddr.cs_w-1) + g_tech_ddr.ba_w + g_tech_ddr.a_w + g_tech_ddr.a_col_w - g_tech_ddr.rsl_w-1 DOWNTO 0); -- ceil_log2(..-1) because the chip select lines are converted to a logical address
-  SIGNAL ctlr_rd_req       : STD_LOGIC;
-  SIGNAL ctlr_wr_req       : STD_LOGIC;
-
-  SIGNAL ctlr_ref_rst_n    : STD_LOGIC;
-  SIGNAL ctlr_gen_rst_n    : STD_LOGIC;
-
-  SIGNAL i_ctlr_gen_clk    : STD_LOGIC;
-  SIGNAL i_ctlr_gen_rst    : STD_LOGIC;
-  SIGNAL i_ctlr_gen_clk_2x : STD_LOGIC;
+  
   SIGNAL i_ctlr_init_done  : STD_LOGIC;
-  SIGNAL i_ctlr_rdy        : STD_LOGIC;
   SIGNAL i_dvr_done        : STD_LOGIC;
 
+  SIGNAL ctlr_gen_clk      : STD_LOGIC;
+  SIGNAL ctlr_gen_rst      : STD_LOGIC;
+  
+  SIGNAL ctlr_mosi         : t_tech_ddr_mosi;
+  SIGNAL ctlr_miso         : t_tech_ddr_miso;
+
   SIGNAL dvr_cur_addr      : t_tech_ddr_addr;
   SIGNAL dvr_flush         : STD_LOGIC := '0';
  
@@ -121,21 +115,14 @@ ARCHITECTURE str OF io_ddr IS
   
 BEGIN 
 
+  ctlr_init_done <= i_ctlr_init_done;
+  ctlr_rdy <= ctlr_miso.waitrequest_n;
   dvr_done <= i_dvr_done;
-
-  ctlr_ref_rst_n  <= NOT(ctlr_ref_rst);  
-  i_ctlr_gen_rst  <= NOT(ctlr_gen_rst_n);
-
-  ctlr_gen_clk    <= i_ctlr_gen_clk;
-  ctlr_gen_rst    <= i_ctlr_gen_rst;
-  ctlr_gen_clk_2x <= i_ctlr_gen_clk_2x;   
-  ctlr_rdy        <= i_ctlr_rdy;  
-  ctlr_init_done  <= i_ctlr_init_done;
-
+  
   u_wr_fifo : ENTITY dp_lib.dp_fifo_dc_mixed_widths
   GENERIC MAP (
     g_wr_data_w         => g_wr_data_w,
-    g_rd_data_w         => g_tech_ddr.data_w,
+    g_rd_data_w         => c_ctlr_data_w,
     g_use_ctrl          => g_wr_use_ctrl,
     g_wr_fifo_size      => c_wr_fifo_depth,
     g_wr_fifo_af_margin => 4 + c_latency, --default (4) + c_latency to compensate for latency introduced by registering wr_siso.ready
@@ -144,8 +131,8 @@ BEGIN
   PORT MAP (
     wr_rst         => wr_rst,
     wr_clk         => wr_clk,
-    rd_rst         => i_ctlr_gen_rst,
-    rd_clk         => i_ctlr_gen_clk,
+    rd_rst         => ctlr_gen_rst,
+    rd_clk         => ctlr_gen_clk,
 
     snk_out        => wr_siso,
     snk_in         => wr_sosi,
@@ -165,20 +152,20 @@ BEGIN
     g_framed_xoff   => FALSE           -- immediately start flushing when dvr_flush goes high
   )
   PORT MAP (
-    rst      => i_ctlr_gen_rst,
-    clk      => i_ctlr_gen_clk,
+    rst      => ctlr_gen_rst,
+    clk      => ctlr_gen_clk,
    
     snk_in   => flush_wr_sosi,
     snk_out  => flush_wr_siso,
 
     src_out  => ctlr_wr_sosi,
-    src_in   => ctlr_wr_siso,  -- fixed streaming xon='1'
+    src_in   => ctlr_wr_siso,
 
-    flush_en => dvr_flush      -- memory mapped xon/xoff control
+    flush_en => dvr_flush
   );
 
-  gen_flush : IF g_flush_wr_fifo = TRUE GENERATE  
-    u_flush_ctrl : ENTITY work.ddr_flush_ctrl
+  gen_io_ddr_driver_flush_ctrl : IF g_flush_wr_fifo = TRUE GENERATE  
+    u_io_ddr_driver_flush_ctrl : ENTITY work.io_ddr_driver_flush_ctrl
     GENERIC MAP (
       g_sop               => g_flush_sop,
       g_sop_channel       => g_flush_sop_channel,
@@ -201,7 +188,7 @@ BEGIN
 
   u_rd_fifo : ENTITY dp_lib.dp_fifo_dc_mixed_widths
   GENERIC MAP (
-    g_wr_data_w         => g_tech_ddr.data_w,
+    g_wr_data_w         => c_ctlr_data_w,
     g_rd_data_w         => g_rd_data_w,
     g_use_ctrl          => FALSE,
     g_wr_fifo_size      => g_rd_fifo_depth,
@@ -209,8 +196,8 @@ BEGIN
     g_rd_fifo_rl        => 1
   )
   PORT MAP (
-    wr_rst   => i_ctlr_gen_rst,
-    wr_clk   => i_ctlr_gen_clk,
+    wr_rst   => ctlr_gen_rst,
+    wr_clk   => ctlr_gen_clk,
     rd_rst   => rd_rst,
     rd_clk   => rd_clk,
 
@@ -231,15 +218,15 @@ BEGIN
     g_wr_fifo_depth => g_wr_fifo_depth
   )
   PORT MAP ( 
-    rst             => i_ctlr_gen_rst,  
-    clk             => i_ctlr_gen_clk,        
+    rst             => ctlr_gen_rst,  
+    clk             => ctlr_gen_clk,        
 
-    ctlr_rdy        => i_ctlr_rdy,
+    ctlr_rdy        => ctlr_miso.waitrequest_n,
     ctlr_init_done  => i_ctlr_init_done,
-    ctlr_wr_req     => ctlr_wr_req,      
-    ctlr_rd_req     => ctlr_rd_req,
-    ctlr_burst      => ctlr_burst,
-    ctlr_burst_size => ctlr_burst_size,
+    ctlr_wr_req     => ctlr_mosi.wr,
+    ctlr_rd_req     => ctlr_mosi.rd,
+    ctlr_burst      => ctlr_mosi.burstbegin,
+    ctlr_burst_size => ctlr_mosi.burstsize,
 
     wr_val          => ctlr_wr_sosi.valid, 
     wr_rdy          => ctlr_wr_siso.ready,
@@ -256,62 +243,42 @@ BEGIN
     wr_fifo_usedw   => wr_fifo_usedw
   );
 
-  ctlr_address <= dvr_cur_addr.chip &
-                  dvr_cur_addr.bank &
-                  dvr_cur_addr.row(g_tech_ddr.a_w-1 DOWNTO 0) &
-                  dvr_cur_addr.column(g_tech_ddr.a_col_w-1 DOWNTO g_tech_ddr.rsl_w);
+  ctlr_mosi.address(c_ctrl_address_w-1 DOWNTO 0) <= dvr_cur_addr.chip &
+                                                    dvr_cur_addr.bank &
+                                                    dvr_cur_addr.row(g_tech_ddr.a_w-1 DOWNTO 0) &
+                                                    dvr_cur_addr.column(g_tech_ddr.a_col_w-1 DOWNTO g_tech_ddr.rsl_w);
+                                                    
+  ctlr_mosi.wrdata(c_ctlr_data_w-1 DOWNTO 0) <= ctlr_wr_sosi.data(c_ctlr_data_w-1 DOWNTO 0);
+    
+  ctlr_rd_sosi.valid                          <= ctlr_miso.rdval;
+  ctlr_rd_sosi.data(c_ctlr_data_w-1 DOWNTO 0) <= ctlr_miso.rddata(c_ctlr_data_w-1 DOWNTO 0);
   
-  gen_uphy_4g_800_master : IF func_tech_ddr_module_size(c_tech_ddr)=4 AND g_tech_ddr.mts=800 GENERATE
-    u_uphy_4g_800_master : COMPONENT uphy_4g_800_master 
-	   PORT MAP (
-	  	pll_ref_clk                => ctlr_ref_clk,                         
-	  	global_reset_n             => ctlr_ref_rst_n,                           
-	  	soft_reset_n               => '1',                                  
-	  	afi_clk                    => i_ctlr_gen_clk,                       
-	  	afi_half_clk               => OPEN,                                 
-	  	afi_reset_n                => ctlr_gen_rst_n,                       
-	  	mem_a                      => phy_ou.a(g_tech_ddr.a_w-1 DOWNTO 0),       
-	  	mem_ba                     => phy_ou.ba(g_tech_ddr.ba_w-1 DOWNTO 0),     
-	  	mem_ck                     => phy_io.clk(g_tech_ddr.clk_w-1 DOWNTO 0),   
-	  	mem_ck_n                   => phy_io.clk_n(g_tech_ddr.clk_w-1 DOWNTO 0), 
-	  	mem_cke                    => phy_ou.cke(g_tech_ddr.clk_w-1 DOWNTO 0),   
-	  	mem_cs_n                   => phy_ou.cs_n(g_tech_ddr.cs_w-1 DOWNTO 0),   
-	  	mem_dm                     => phy_ou.dm(g_tech_ddr.dm_w-1 DOWNTO 0),     
-	  	mem_ras_n                  => phy_ou.ras_n,                         
-	  	mem_cas_n                  => phy_ou.cas_n,                         
-	  	mem_we_n                   => phy_ou.we_n,                          
-	  	mem_reset_n                => phy_ou.reset_n,                       
-	  	mem_dq                     => phy_io.dq(g_tech_ddr.dq_w-1 DOWNTO 0),     
-	  	mem_dqs                    => phy_io.dqs(g_tech_ddr.dqs_w-1 DOWNTO 0),   
-	  	mem_dqs_n                  => phy_io.dqs_n(g_tech_ddr.dqs_w-1 DOWNTO 0), 
-	  	mem_odt                    => phy_ou.odt(g_tech_ddr.cs_w-1 DOWNTO 0),    
-	  	avl_ready                  => i_ctlr_rdy,                           
-	  	avl_burstbegin             => ctlr_burst,                           
-	  	avl_addr                   => ctlr_address,                         
-	  	avl_rdata_valid            => ctlr_rd_sosi.valid,                   
-	  	avl_rdata                  => ctlr_rd_sosi.data(g_tech_ddr.data_w-1 DOWNTO 0),                    
-	  	avl_wdata                  => ctlr_wr_sosi.data(g_tech_ddr.data_w-1 DOWNTO 0),                    
-	  	avl_be                     => (OTHERS => '1'),                      
-	  	avl_read_req               => ctlr_rd_req,                          
-	  	avl_write_req              => ctlr_wr_req,                          
-	  	avl_size                   => ctlr_burst_size,          
-	  	local_init_done            => i_ctlr_init_done,                     
-	  	local_cal_success          => OPEN,                                 
-	  	local_cal_fail             => OPEN,                                 
-	  	oct_rdn                    => phy_in.oct_rdn,                       
-	  	oct_rup                    => phy_in.oct_rup,                       
-  		seriesterminationcontrol   => OPEN,
-	  	parallelterminationcontrol => OPEN,
-	  	pll_mem_clk                => i_ctlr_gen_clk_2x,
-      pll_write_clk              => OPEN,
-      pll_write_clk_pre_phy_clk  => OPEN,
-      pll_addr_cmd_clk           => OPEN,
-      pll_locked                 => OPEN,
-      pll_avl_clk                => OPEN,
-      pll_config_clk             => OPEN,
-      dll_delayctrl              => OPEN
-	  );    
-  END GENERATE;  
+  u_tech_ddr : ENTITY tech_ddr_lib.tech_ddr
+  GENERIC MAP (
+    g_technology => g_technology,
+    g_tech_ddr   => g_tech_ddr
+  )
+  PORT MAP (
+    -- PLL reference clock
+    ctlr_ref_clk      => ctlr_ref_clk,
+    ctlr_ref_rst      => ctlr_ref_rst,
+
+    -- Controller user interface
+    ctlr_gen_clk      => ctlr_gen_clk,
+    ctlr_gen_rst      => ctlr_gen_rst,
+    ctlr_gen_clk_2x   => OPEN,
+    ctlr_gen_rst_2x   => OPEN,
+
+    ctlr_init_done    => i_ctlr_init_done,
+
+    ctrl_mosi         => ctlr_mosi,
+    ctrl_miso         => ctlr_miso,
+
+    -- PHY interface
+    phy_in            => phy_in,
+    phy_io            => phy_io,
+    phy_ou            => phy_ou
+  );
 
 END str;