-- =============================================================================
--                           COPYRIGHT NOTICE
-- Copyright 2003 (c) Lattice Semiconductor Corporation
-- ALL RIGHTS RESERVED
-- This confidential and proprietary software may be used only as authorised by
-- a licensing agreement from Lattice Semiconductor Corporation.
-- The entire notice above must be reproduced on all authorized copies and
-- copies may only be made to the extent permitted by a licensing agreement from
-- Lattice Semiconductor Corporation.
--
-- Lattice Semiconductor Corporation        TEL : 1-800-Lattice (USA and Canada)
-- 5555 NE Moore Court                            408-826-6000 (other locations)
-- Hillsboro, OR 97124                     web  : http://www.latticesemi.com/
-- U.S.A                                   email: techsupport@latticesemi.com
-- =============================================================================
--                         FILE DETAILS
-- Project          : Memory Controller
-- File             : ddr_sdram_mem_top.vhd
-- Title            : Top level file with the I/O, PLL and DLL for the
--                    Memory controller
-- Dependencies     : ddr_sdram_mem_params.vhd
-- =============================================================================
--                        REVISION HISTORY
-- Version          : 1.0
-- Mod. Date        : Sep 08, 2004
-- Changes Made     : Initial Creation
--
-- =============================================================================

library ieee;
  use ieee.std_logic_1164.all;
  use ieee.std_logic_arith.all;

library work;
  use work.ddrct_gen_e2_1_001_params.all;

library EC;
  use EC.all;


entity ddr_sdram_mem_top is
port(
	-- Clock and Reset
	clk_in 		: in  std_logic;
	pll_clk		: out std_logic;
	rst_n		: in  std_logic;

	-- Input Signals from the user interface
	cmd		: in std_logic_vector(3 downto 0);
	addr		: in std_logic_vector(ADDR_WIDTH-1 downto 0);
	cmd_valid	: in std_logic;
	init_start	: in std_logic;
	burst_count	: in std_logic_vector(4 downto 0);
	write_data	: in std_logic_vector(DSIZE-1 downto 0);
	data_mask	: in std_logic_vector(USER_DM-1 downto 0);

	-- User Interface Output Signals
	cmd_rdy		: out std_logic;
	init_done	: out std_logic;
	data_rdy	: out std_logic;
	read_data	: out std_logic_vector(DSIZE-1 downto 0);
	read_data_valid	: out std_logic;

	-- Databus and related signals to external memory
	em_ddr_data	: inout std_logic_vector(DATA_WIDTH-1 downto 0);
	em_ddr_dqs	: inout std_logic_vector(DATA_WIDTH/8-1 downto 0);
	em_ddr_dm	: out std_logic_vector(DATA_WIDTH/8-1 downto 0);

	-- Output to External Memory
	-- SDRAM Address, controls and clock

	em_ddr_clk	: out std_logic;
	em_ddr_clk_n	: out std_logic;
	em_ddr_clk1	: out std_logic;
	em_ddr_clk1_n	: out std_logic;
	em_ddr_cke0	: out std_logic;
	em_ddr_cke1	: out std_logic;
	em_ddr_ras_n	: out std_logic;
	em_ddr_cas_n	: out std_logic;
	em_ddr_we_n	: out std_logic;
	em_ddr_cs_n	: out std_logic_vector(CS_WIDTH-1 downto 0);
	em_ddr_cs_n1	: out std_logic;

	burst_term	: in std_logic;
	em_ddr_addr	: out std_logic_vector(ROW_WIDTH-1 downto 0);
	em_ddr_ba	: out std_logic_vector(1 downto 0));
end ddr_sdram_mem_top;

architecture ddr_sdram_top_a of ddr_sdram_mem_top is

component kbar_clk_pll
	port( in_clk 	: in std_logic;
	      out_clk_p	: out std_logic;
	      out_clk   : out std_logic);
end component;

component ODDRXB
    port(
          DA		:	in	STD_LOGIC;
          DB		:	in	STD_LOGIC;
          CLK	        :	in	STD_LOGIC;
          LSR	        :	in	STD_LOGIC;
          Q		:	out	STD_LOGIC
        );
end component;

component inv
PORT(
        a: IN std_logic;
        z: OUT std_logic
  );
END component;

component DQSDLL
    port(
          CLK		:	in	STD_LOGIC;
          RST	        :	in	STD_LOGIC;
          UDDCNTL       :	in	STD_LOGIC;
          LOCK		:	out	STD_LOGIC;
          DQSDEL	:	out	STD_LOGIC
        );
end component;

component ddr_data32_io
    port( inddr_clk	: in std_logic_vector(3 downto 0);
	  outddr_clk	: in std_logic;
	  rst		: in std_logic;
	  ddrclkpol	: in std_logic_vector(3 downto 0);
	  ddr_write_data: in std_logic_vector(63 downto 0);
	  ddr_write_en	: in std_logic;
	  ddr_read_data : out std_logic_vector(63 downto 0);
	  bidi		: inout std_logic_vector(31 downto 0)	  	
	);
end component;

component ddr_dm32_io
    port( clk		: in std_logic;
	  rst		: in std_logic;
	  data_in	: in std_logic_vector(7 downto 0);
	  ddr_dataout	: out std_logic_vector(3 downto 0)
	);
end component;

component ddr_dqs32_io
    port( rst		: in std_logic;
	  dqs_clk	: in std_logic;
	  core_clk	: in std_logic;
	  pio_read	: in std_logic_vector(3 downto 0);
	  tri_en	: in std_logic;
	  dqsdel	: in std_logic;
	  ddr_dqs_out	: in std_logic_vector(1 downto 0);
	  dqsout_pio	: out std_logic_vector(3 downto 0);
	  dqsout_core  	: out std_logic_vector(3 downto 0);
	  prmbdet	: out std_logic_vector(3 downto 0);
	  ddrclkpol	: out std_logic_vector(3 downto 0);
	  dqsi		: out std_logic_vector(3 downto 0);
	  bidi		: inout std_logic_vector(3 downto 0)
	);
end component;

component ddr_pior32
    port( k_clk		: in std_logic;
	  kbar_clk	: in std_logic;
	  rst_n		: in std_logic;
	  pio_read_dly  : in std_logic;
	  pio_read_early: in std_logic;
	  sel_phase_0	: in std_logic_vector(3 downto 0);
	  sel_phase_1	: in std_logic_vector(3 downto 0);
	  sel_phase_2	: in std_logic_vector(3 downto 0);
	  sel_phase_3	: in std_logic_vector(3 downto 0);
	  pio_read_out	: out std_logic_vector(3 downto 0)
	);
end component;

component albuf
    port( clk		: in std_logic;
	  rst_n		: in std_logic;
	  read_command	: in std_logic;
	  cas_latency	: in std_logic_vector(2 downto 0);
	  data_valid_tap : in std_logic_vector(1 downto 0);
	  datavalid_in  : in std_logic;
	  datain	: in std_logic_vector(DSIZE-1 downto 0);
	  dataout	: out std_logic_vector(DSIZE-1 downto 0);
	  datavalid_out	: out std_logic;
	  pio_read_dly	: out std_logic;
	  pio_read_early : out std_logic
	);
end component;

component ddrct_gen_e2_1_001
    port ( clk			: in std_logic;
	   rst_n		: in std_logic;
	   fb_cmd		: in std_logic_vector(3 downto 0);
	   fb_addr		: in std_logic_vector(ADDR_WIDTH-1 downto 0);
	   fb_cmd_valid		: in std_logic;
	   fb_init_start	: in std_logic;
	   fb_burst_length 	: in std_logic_vector(4 downto 0);
	   fb_write_data	: in std_logic_vector(DSIZE-1 downto 0);
	   fb_data_mask		: in std_logic_vector(USER_DM-1 downto 0);
	   data_valid_tap	: in std_logic_vector(1 downto 0);
	   tras			: in std_logic_vector(4 downto 0);
	   trc			: in std_logic_vector(4 downto 0);
	   trcd			: in std_logic_vector(2 downto 0);
	   trrd			: in std_logic_vector(2 downto 0);
	   trfc			: in std_logic_vector(4 downto 0);
	   trp			: in std_logic_vector(2 downto 0);
	   tmrd			: in std_logic_vector(2 downto 0);
	   twr			: in std_logic_vector(2 downto 0);
	   trefi		: in std_logic_vector(15 downto 0);
	   ar_burst_en		: in std_logic_vector(2 downto 0);
	   ext_reg_en		: in std_logic;
	   fb_burst_term	: in std_logic;
	   fb_cmd_rdy		: out std_logic;
	   init_done		: out std_logic;
	   fb_data_rdy		: out std_logic;
	   data_valid_tmp	: out std_logic;
	   cas_latency		: out std_logic_vector(2 downto 0);
	   ddr_cke		: out std_logic;
	   ddr_ras_n		: out std_logic;
	   ddr_cas_n		: out std_logic;
	   ddr_we_n		: out std_logic;
	   ddr_cs_n		: out std_logic_vector(CS_WIDTH-1 downto 0);
	   pio_read		: out std_logic;
	   dv_cs_csm_is_rd	: out std_logic;
	   rd_cmd_pulse		: out std_logic;
	   dv_bl_cycles		: out std_logic_vector(2 downto 0);
	   read_command		: out std_logic;
	   ddr_addr		: out std_logic_vector(ROW_WIDTH-1 downto 0);
	   ddr_ba		: out std_logic_vector(1 downto 0);
	   ddr_dqs_out		: out std_logic_vector(1 downto 0);
	   ddr_write_data	: out std_logic_vector(DATA_WIDTH*2-1 downto 0);
	   ddr_DM		: out std_logic_Vector(USER_DM-1 downto 0);
	   ddr_write_valid	: out std_logic;
	   ddr_write_valid_early: out std_logic);
end component;

signal k_clk		: std_logic;
signal kbar_clk		: std_logic;
signal act_high_rst	: std_logic;


-- internal wire
signal ddr_addr_kpos		: std_logic_vector(ROW_WIDTH-1 downto 0);
signal ddr_addr_kbar_neg	: std_logic_vector(ROW_WIDTH-1 downto 0);
--signal em_ddr_addr		: std_logic_vector(ROW_WIDTH-1 downto 0);

signal ddr_ba_kpos		: std_logic_vector(1 downto 0);
signal ddr_ba_kbar_neg		: std_logic_vector(1 downto 0);
--signal em_ddr_ba		: std_logic_vector(1 downto 0);

signal ddr_cke_kpos		: std_logic;
signal ddr_cke_kbar_neg		: std_logic;
--signal em_ddr_cke		: std_logic;

signal ddr_ras_n_kpos		: std_logic;
signal ddr_ras_n_kbar_neg	: std_logic;
--signal em_ddr_ras_n		: std_logic;

signal ddr_we_n_kpos		: std_logic;
signal ddr_we_n_kbar_neg	: std_logic;
--signal em_ddr_we_n		: std_logic;

signal ddr_cas_n_kpos		: std_logic;
signal ddr_cas_n_kbar_neg	: std_logic;
--signal em_ddr_cas_n		: std_logic;

signal ddr_cs_n_kpos		: std_logic_vector(CS_WIDTH-1 downto 0);
signal ddr_cs_n_kbar_neg	: std_logic_vector(CS_WIDTH-1 downto 0);
--signal em_ddr_cs_n		: std_logic_vector(CS_WIDTH-1 downto 0);

signal ddr_dqs_out		: std_logic_vector(1 downto 0);
signal ddr_dqs_out_kbar_neg	: std_logic_vector(1 downto 0);
signal int_ddr_dqs_out_kbar_neg	: std_logic_vector(1 downto 0);

signal ddr_write_enable_kpos	: std_logic;
signal ddr_write_enable_early_kpos: std_logic;
signal ddr_write_enable_kbar_neg: std_logic;
signal ddr_write_enable		: std_logic;

signal ddr_write_enable_kneg	: std_logic;
signal ddr_write_enable_kneg_d	: std_logic;

signal ddr_dqs_in 		: std_logic_vector(DATA_WIDTH/8-1 downto 0);
signal dqsdel	  		: std_logic;
signal em_write_data	: std_logic_vector(DSIZE-1 downto 0);
signal em_write_data_tmp : std_logic_vector(DSIZE-1 downto 0);
signal em_write_data_tmp_d : std_logic_vector(DSIZE-1 downto 0);
signal ddr_dm			: std_logic_vector(USER_DM-1 downto 0);
signal ddr_dm_tmp		: std_logic_vector(USER_DM-1 downto 0);
signal ddr_dm_tmp_d 	: std_logic_vector(USER_DM-1 downto 0);

signal data_valid_tmp 	: std_logic;
signal cas_latency		: std_logic_vector(2 downto 0);
signal dv_bl_cycles		: std_logic_vector(2 downto 0);
signal pio_read			: std_logic;
signal read_command		: std_logic;
signal dv_cs_csm_is_rd 	: std_logic;
signal rd_cmd_pulse		: std_logic;
signal ddr_read_data	: std_logic_vector(DSIZE-1 downto 0);
signal pio_read_dly		: std_logic;
signal pio_read_early	: std_logic;

signal update_cntl		: std_logic;
signal open_latch		: std_logic;
signal latch_ctrl_count	: unsigned(3 downto 0);

signal ddrclkpol		: std_logic_vector(DATA_WIDTH/8-1 downto 0);
signal prmbdet			: std_logic_vector(DATA_WIDTH/8-1 downto 0);
signal dqsi				: std_logic_vector(DATA_WIDTH/8-1 downto 0);
signal pio_read_out		: std_logic_vector(DATA_WIDTH/8-1 downto 0);
	
signal not_rst_n		: std_logic;
signal not_k_clk		: std_logic;


begin

-- Clock outputs to the Memory controller

not_rst_n	<= not rst_n;
not_k_clk	<= not k_clk;
pll_clk         <= k_clk;

U1_kbar_clk_pll : kbar_clk_pll
	port map(
		in_clk => clk_in,
		out_clk_p => kbar_clk,
		out_clk	=> k_clk
	);


-- Instantiate an inverter to break the reset path

U1_INV : INV
	port map(
		A => rst_n,
		Z => act_high_rst
	);
	
-- Generate the clocks for the memory device

U1_ODDRXB : ODDRXB
	port map(
		DA => '0',
		DB => '1',
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_clk		
	);

U2_ODDRXB : ODDRXB
	port map(
		DA => '1',
		DB => '0',
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_clk_n		
	);

U3_ODDRXB : ODDRXB
	port map(
		DA => '0',
		DB => '1',
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_clk1		
	);

U4_ODDRXB : ODDRXB
	port map(
		DA => '1',
		DB => '0',
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_clk1_n		
	);

-- instantiate the memory controller core



------------------------------------------------------------------------------
-- This logic implemennts the logic to transfer the addr and command
-- signals from the core clock domain to the DDR memory interface clock domain
-- kclk -> kbar_clk

-- Generate the wite enable for the data and mask bus using the 
-- ddr_write_enable_early_kpos signal.  Reduce the width by 2 clock cycles

process(k_clk, rst_n)
begin
	if (rst_n = '0') then
		ddr_write_enable_kneg 	<= '1';
		ddr_write_enable_kneg_d <= '1';

	elsif k_clk'event and k_clk = '0' then

		ddr_write_enable_kneg 	<= ddr_write_enable_early_kpos;
		ddr_write_enable_kneg_d <= ddr_write_enable_kneg;
	end if;
end process; 

process(kbar_clk, rst_n)
begin
	if (rst_n = '0') then 

		ddr_addr_kbar_neg 	<= (others => '0');
		ddr_ba_kbar_neg 	<= "00";
		ddr_cke_kbar_neg 	<= '0';
		ddr_ras_n_kbar_neg 	<= '1';
		ddr_cas_n_kbar_neg 	<= '1';
		ddr_we_n_kbar_neg 	<= '1';
		ddr_cs_n_kbar_neg	<= (others => '1');
		ddr_dqs_out_kbar_neg	<= "00";
		int_ddr_dqs_out_kbar_neg <= "00";
		ddr_write_enable_kbar_neg <= '1';

	elsif kbar_clk'event and kbar_clk='0' then 
		
		-- This is a 3/4 clock cycle transfer
		ddr_addr_kbar_neg           <= ddr_addr_kpos;
		ddr_ba_kbar_neg             <= ddr_ba_kpos;
		ddr_cke_kbar_neg            <= ddr_cke_kpos;
		ddr_ras_n_kbar_neg          <= ddr_ras_n_kpos;
		ddr_cas_n_kbar_neg          <= ddr_cas_n_kpos;
		ddr_we_n_kbar_neg           <= ddr_we_n_kpos;
		ddr_cs_n_kbar_neg           <= ddr_cs_n_kpos;
		int_ddr_dqs_out_kbar_neg    <= ddr_dqs_out;
		ddr_dqs_out_kbar_neg        <= int_ddr_dqs_out_kbar_neg;
		ddr_write_enable_kbar_neg   <= ddr_write_enable_kpos;

	end if;			
end process;

-- Use ODDRXB to drive the address and control signals

U_ODDR_CKE0 : ODDRXB
	port map(
		DA => ddr_cke_kbar_neg,
		DB => ddr_cke_kbar_neg,
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_cke0		
	);

U_ODDR_CKE1 : ODDRXB
	port map(
		DA => ddr_cke_kbar_neg,
		DB => ddr_cke_kbar_neg,
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_cke1		
	);

U_ODDR_RAS : ODDRXB
	port map(
		DA => ddr_ras_n_kbar_neg,
		DB => ddr_ras_n_kbar_neg,
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_ras_n		
	);

U_ODDR_CAS : ODDRXB
	port map(
		DA => ddr_cas_n_kbar_neg,
		DB => ddr_cas_n_kbar_neg,
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_cas_n		
	);

U_ODDR_WE : ODDRXB
	port map(
		DA => ddr_we_n_kbar_neg,
		DB => ddr_we_n_kbar_neg,
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_we_n		
	);

u_cs0_inst : for cs_index in 0 to CS_WIDTH-1 generate
     begin
         U_ODDR_CS_n : component ODDRXB
	   port map(
		DA => ddr_cs_n_kbar_neg(cs_index),
		DB => ddr_cs_n_kbar_neg(cs_index),
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_cs_n(cs_index)		
	);
      end generate u_cs0_inst;

u_cs1_inst : component ODDRXB
	port map(
		DA => ddr_cs_n_kbar_neg(0),
		DB => ddr_cs_n_kbar_neg(0),
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_cs_n1		
	);
 
U_ODDR_BA0 : ODDRXB
	port map(
		DA => ddr_ba_kbar_neg(0),
		DB => ddr_ba_kbar_neg(0),
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_ba(0)		
	);


U_ODDR_BA1 : ODDRXB
	port map(
		DA => ddr_ba_kbar_neg(1),
		DB => ddr_ba_kbar_neg(1),
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_ba(1)		
	);


U_ODDR_ADDR : for ad_index in 0 to ROW_WIDTH-1 generate
  begin
	oddr_addr_n: component ODDRXB
	port map(
		DA => ddr_addr_kbar_neg(ad_index),
		DB => ddr_addr_kbar_neg(ad_index),
		LSR => not_rst_n,
		CLK => kbar_clk,
		Q => em_ddr_addr(ad_index)		
	);
  end generate U_ODDR_ADDR;


process(kbar_clk, rst_n)
begin
	if (rst_n = '0') then
		ddr_write_enable 	<= '1';
	elsif rising_edge(kbar_clk) then
		ddr_write_enable 	<= ddr_write_enable_kbar_neg;
	end if;
end process;

-- Get the write data from the core and 
-- flop it on the falling k_clk before feeding it to the ddr_io block.

process(k_clk, rst_n)
begin
	if (rst_n = '0') then
		em_write_data_tmp_d <= (others => '0');
		ddr_dm_tmp_d	  	<= (others => '0');

	elsif rising_edge(k_clk) then
		em_write_data_tmp_d	<= em_write_data_tmp;
		ddr_dm_tmp_d		<= ddr_dm_tmp;
	end if;
	
end process;

process(k_clk, rst_n)
begin
	if (rst_n = '0') then
		em_write_data 	<= (others => '0');
		ddr_dm		<= (others => '0');

	elsif k_clk'event and k_clk = '0' then
		em_write_data 	<= em_write_data_tmp_d;
		ddr_dm		<= ddr_dm_tmp_d;
	end if;
end process;

U1_ddrct_gen_e2_1_001 : ddrct_gen_e2_1_001
	port map(
		clk		=> k_clk,
		rst_n		=> rst_n,
		fb_cmd		=> cmd,
		fb_addr		=> addr,
		fb_cmd_valid	=> cmd_valid,
		fb_burst_length => burst_count,
		fb_init_start	=> init_start,
		fb_write_data	=> write_data,
		fb_data_mask	=> data_mask,

		data_valid_tap	=> "00",
		data_valid_tmp	=> data_valid_tmp,
		cas_latency	=> cas_latency,
		
		-- User Interface timing parameter input signals
		tras		=> TRAS,
		trc		=> TRC,
		trcd		=> TRCD,
		trrd		=> TRRD,
		trfc		=> TRFC,
		trp		=> TRP,
		tmrd		=> TMRD,
		twr		=> TWR,
		trefi		=> TREFI,
		ar_burst_en	=> AR_BURST_EN,
		
		ext_reg_en	=> EXT_REG_EN,
		fb_burst_term	=> burst_term,
		
		fb_cmd_rdy	=> cmd_rdy,
		fb_data_rdy	=> data_rdy,
		init_done	=> init_done,
		
		pio_read	=> pio_read,
		read_command	=> read_command,
		dv_bl_cycles	=> dv_bl_cycles,
		dv_cs_csm_is_rd	=> dv_cs_csm_is_rd,
		rd_cmd_pulse	=> rd_cmd_pulse,

		-- Memory interface output signals
		ddr_cke		=> ddr_cke_kpos,
		ddr_ras_n	=> ddr_ras_n_kpos,
		ddr_cas_n	=> ddr_cas_n_kpos,
		ddr_we_n	=> ddr_we_n_kpos,
		ddr_cs_n	=> ddr_cs_n_kpos,

		ddr_DM		=> ddr_dm_tmp,
		ddr_ba		=> ddr_ba_kpos,
		ddr_dqs_out	=> ddr_dqs_out,
		ddr_addr	=> ddr_addr_kpos,
		ddr_write_valid	=> ddr_write_enable_kpos,
	        ddr_write_valid_early => ddr_write_enable_early_kpos,
		ddr_write_data	=> em_write_data_tmp	
	);


-----------------------------------------------------------------------------
-- Logic to generate the pio_read signal to the DQS buffer
-- Since the routing delays on the dqs signals are not known, the read 
-- signal to the dqs buffer needs to be selected from an array of 
-- available read signals.  This is done to position the read signal withn the 
-- preamble period.  The goal is to position the read 1/4 clock cycle 
-- into the pramble period to allow sufficient time for routing.

-----------------------------------------------------------------------------
-- ALBUF module - Logic to align data from different DQS groups

U1_albuf : albuf
	port map(
		clk		=> k_clk,
		rst_n		=> rst_n,
		datain		=> ddr_read_data,
		datavalid_in	=> data_valid_tmp,
		read_command	=> pio_read,
		cas_latency	=> cas_latency,
		data_valid_tap	=> "00",
		dataout		=> read_data,
		pio_read_dly	=> pio_read_dly,
		pio_read_early	=> pio_read_early,
		datavalid_out	=> read_data_valid
	);


---------------------------------------------------------------------------
-- The following logic controls the DLL latch that outputs the delay values.

-- When a read is detected, the latch is closed.  It is opened again once
-- read_latency+blength+4 clock cycles have passed since a read command
-- was presented.  The 4 additional clock cycles compensate for the
-- early read command, and other delays.  To simplify, this counter is
-- always set to 15.
---------------------------------------------------------------------------

process(k_clk, rst_n)
begin
	if (rst_n = '0') then
		update_cntl		<= '1';
		latch_ctrl_count	<= "1111";
		open_latch		<= '1';
	elsif rising_edge(k_clk) then
		if (read_command = '1') then
			update_cntl		<= '0';
			latch_ctrl_count	<= "1111";
			open_latch		<= '0';
		else
			if (latch_ctrl_count /= 0) then
				latch_ctrl_count <= latch_ctrl_count - "0001";
			end if;

			if (latch_ctrl_count = 0) then
				open_latch 	<= '1';
			end if;
			
			if (open_latch = '1') then
				update_cntl	<= '1';
			end if;
		end if;
	end if;

end process;



U1_DQSDLL : DQSDLL
	port map(
		CLK	=> k_clk,
		RST	=> not_rst_n,
		UDDCNTL	=> update_cntl,
		DQSDEL	=> dqsdel,
		LOCK	=> open
	);

U1_ddr_data32_io : ddr_data32_io
	port map( inddr_clk 	=> ddr_dqs_in,
	  	  outddr_clk	=> k_clk,
	 	  rst		=> act_high_rst,
	 	  ddrclkpol	=> ddrclkpol,
	 	  ddr_write_data => em_write_data,
	 	  ddr_write_en	=> ddr_write_enable_kneg_d,
	 	  ddr_read_data => ddr_read_data,
	 	  bidi		=> em_ddr_data	
	);

U1_ddr_dm32_io	: ddr_dm32_io
	port map(
		clk		=> not_k_clk,
		rst		=> not_rst_n,
		data_in		=> ddr_dm,
		ddr_dataout	=> em_ddr_dm
	);

U1_ddr_dqs32_io : ddr_dqs32_io
	port map(
		rst		=> not_rst_n,
		dqs_clk		=> kbar_clk,
		core_clk	=> k_clk,
		pio_read	=> pio_read_out,
		tri_en		=> ddr_write_enable,
		dqsdel		=> dqsdel,
		dqsout_pio	=> ddr_dqs_in,
		dqsout_core	=> open,
		prmbdet		=> prmbdet,
		ddrclkpol	=> ddrclkpol,
		ddr_dqs_out	=> ddr_dqs_out_kbar_neg,
		dqsi		=> dqsi,
		bidi		=> em_ddr_dqs
	);

U1_ddr_pior32 : ddr_pior32
	port map(
		rst_n		=> rst_n,
		k_clk		=> k_clk,
		kbar_clk	=> kbar_clk,
		sel_phase_0	=> PIO_RD_DQS0,
		sel_phase_1	=> PIO_RD_DQS1,
		sel_phase_2	=> PIO_RD_DQS2,
		sel_phase_3	=> PIO_RD_DQS3,
		pio_read_dly	=> pio_read_dly,
		pio_read_early	=> pio_read_early,
		pio_read_out	=> pio_read_out
	);

end ddr_sdram_top_a;