// =============================================================================
//                           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.v
// Title            : Top level file with the I/O, PLL and DLL for the
//                    Memory controller
// Dependencies     : ddr_sdram_mem_params.v
// =============================================================================
//                        REVISION HISTORY
// Version          : 1.0
// Mod. Date        : Sep 08, 2004
// Changes Made     : Initial Creation
//
// =============================================================================

`timescale 1ns/100ps
module ddr_sdram_mem_top (

   // Clock and reset
   clk_in,
   pll_clk,
   rst_n,

   // Inputs signals from the User Interface
   cmd,
   addr,
   cmd_valid,
   burst_count,
   init_start,
   write_data,
   data_mask,
 
   // These signals are brought out only during testing.  So that the core
   // can be verified with different settings.  In real designs, 
   // these signals will be driven by a  constant value within the module.

   // User Interface Output signals
   cmd_rdy,
   init_done,
   data_rdy,
   read_data,
   read_data_valid,

   // Bi-directional databus to external memory
   em_ddr_data,
   em_ddr_dqs,

   // Output to External memory
   // SDRAM Address, controls and clock
   em_ddr_clk,
   em_ddr_clk_n,
   em_ddr_clk1,
   em_ddr_clk1_n,
   em_ddr_cke0,
   em_ddr_cke1,
   em_ddr_ras_n,
   em_ddr_cas_n,
   em_ddr_we_n,
   em_ddr_cs_n,
   em_ddr_cs_n1,

   `ifdef DDR2_MODE
       em_ddr_odt,
   `else
       burst_term,
   `endif

   em_ddr_dm,
   em_ddr_ba,
   em_ddr_addr
);

//////////////////////////////////////////////////////////////////////////////
//clock and reset inputs
input                                 clk_in;
output                                pll_clk;
input                                 rst_n;

// Inputs signals from the User Interface
input   [3:0]                         cmd;
input   [`ADDR_WIDTH-1:0]             addr;
input                                 cmd_valid;
input                                 init_start;
input   [4:0]                         burst_count;
input   [`DSIZE-1:0]                  write_data;
input   [`USER_DM-1:0]                data_mask;

// User Interface Output signals
output                                cmd_rdy;
output                                init_done;
output                                data_rdy;
output  [`DSIZE -1:0]                 read_data;
output                                read_data_valid;

// databus and related signals to external memory
inout  [`DATA_WIDTH-1:0]              em_ddr_data;
inout  [`DATA_WIDTH/8-1:0]            em_ddr_dqs;
output [`DATA_WIDTH/8-1:0]            em_ddr_dm;

// Output to External memory
// SDRAM Address, controls and clock
output                                em_ddr_clk;
output                                em_ddr_clk_n;
output                                em_ddr_clk1;
output                                em_ddr_clk1_n;
output                                em_ddr_cke0;
output                                em_ddr_cke1;
output                                em_ddr_ras_n;
output                                em_ddr_cas_n;
output                                em_ddr_we_n;
output  [`CS_WIDTH-1:0]               em_ddr_cs_n;
output                                em_ddr_cs_n1;

`ifdef DDR2_MODE
    `ifdef CS_WIDTH_1
        output                        em_ddr_odt;
    `else
        output  [`CS_WIDTH -1 :0]     em_ddr_odt;
    `endif
`else
    input                             burst_term;
`endif

output  [`ROW_WIDTH-1:0]              em_ddr_addr;
output  [1:0]                         em_ddr_ba;

///////////////////////////////////////////////////////////////////////////
// Timing parameter registers.  They are initialized to
// constant values here.  The memory is mt46v8m16.  This device has 16 bits
// of data, 12 bits of row address and 9 bits of column address.

///////////////////////////////////////////////////////////////////////////
// Clock generation Logic.  Instantiate the PLL here.

// Clock outputs to the Memory controller
wire                                  k_clk;
wire                                  kbar_clk;
wire                                  act_high_rst;

kbar_clk_pll U1_kbar_clk_pll (

    .in_clk                 (clk_in),
    .out_clk_p              (kbar_clk),
    .out_clk                (k_clk)
);
assign pll_clk = k_clk;

// Instantiate an inverter to break the reset path
INV U1_INV (.A(rst_n), .Z(act_high_rst));

///////////////////////////////////////////////////////////////////////////
// Generate the clocks for the memory device

ODDRXB U1_ODDRXB (.DA(1'b0), .DB(1'b1), .LSR(~rst_n), .CLK(kbar_clk), 
                  .Q(em_ddr_clk));

ODDRXB U2_ODDRXB (.DA(1'b1), .DB(1'b0), .LSR(~rst_n), .CLK(kbar_clk), 
                  .Q(em_ddr_clk_n));

ODDRXB U3_ODDRXB (.DA(1'b0), .DB(1'b1), .LSR(~rst_n), .CLK(kbar_clk), 
                  .Q(em_ddr_clk1));

ODDRXB U4_ODDRXB (.DA(1'b1), .DB(1'b0), .LSR(~rst_n), .CLK(kbar_clk), 
                  .Q(em_ddr_clk1_n));

///////////////////////////////////////////////////////////////////////////
// Instantiate the Memory controller Core

// Internal wires

// Output signals from the FPGA I/O 
wire    [`DSIZE-1:0]                  ddr_read_data;
wire    [`DSIZE -1:0]                 read_data;
wire                                  read_data_valid;

// Output signals from the memory controller core
wire   [`USER_DM-1:0]                 ddr_dm_tmp;
reg    [`USER_DM-1:0]                 ddr_dm_tmp_d;
reg    [`USER_DM-1:0]                 ddr_dm;
wire   [`DSIZE-1:0]                   em_write_data_tmp;
reg    [`DSIZE-1:0]                   em_write_data_tmp_d;
reg    [`DSIZE-1:0]                   em_write_data;

`ifdef DDR2_MODE
    `ifdef CS_WIDTH_1
        wire                          em_ddr_odt;
    `else
        wire    [`CS_WIDTH -1 :0]     em_ddr_odt;
    `endif
`endif

wire                                  pio_read;
wire                                  pio_read_dly;
wire                                  pio_read_early;
wire                                  read_command;

`ifdef DATA_SIZE_8
    wire                              ddrclkpol;
    wire                              prmbdet;
    wire                              dqsi;
    wire                              pio_read_out;
`else
    wire   [(`DATA_WIDTH/8)-1:0]      ddrclkpol;
    wire   [(`DATA_WIDTH/8)-1:0]      prmbdet;
    wire   [(`DATA_WIDTH/8)-1:0]      dqsi;
    wire   [(`DATA_WIDTH/8)-1:0]      pio_read_out;
`endif

reg                                   update_cntl;
reg                                   open_latch;
reg    [3:0]                          latch_ctrl_count;

`ifdef ECP
   `ifdef DATA_SIZE_8
      wire                            al_data_valid;     // True Data valid 
                                                         // signal for AL logic
      wire                            pio_dv_pulse;
   `else
      wire    [(`DATA_WIDTH/8) -1:0]  al_data_valid;     // True Data valid 
                                                         // signal for AL logic
      wire    [(`DATA_WIDTH/8) -1:0]  pio_dv_pulse;     
   `endif
`endif

wire                                  dv_cs_csm_is_rd;   // cs is read 
wire                                  rd_cmd_pulse;      // RD cmd pulse 
wire    [2:0]                         dv_bl_cycles;      // BL Cycle Count
wire    [2:0]                         cas_latency;
wire                                  data_valid_tmp;    // data valid aligned 
                                                         // to the rd command 
                                                         // at the Memory I/F.

////////////////////////////////////////////////////////////////////////////
// Signals to generate the command, Addr, data, dqs, and mask signals 
// at the memory interface

wire    [`ROW_WIDTH-1:0]              ddr_addr_kpos;
reg     [`ROW_WIDTH-1:0]              ddr_addr_kbar_neg;
wire    [`ROW_WIDTH-1:0]              em_ddr_addr;

wire    [1:0]                         ddr_ba_kpos;
reg     [1:0]                         ddr_ba_kbar_neg;
wire    [1:0]                         em_ddr_ba;

wire                                  ddr_cke_kpos;
reg                                   ddr_cke_kbar_neg;
wire                                  em_ddr_cke0;
wire                                  em_ddr_cke1;

wire                                  ddr_ras_n_kpos;
reg                                   ddr_ras_n_kbar_neg;
wire                                  em_ddr_ras_n;

wire                                  ddr_we_n_kpos;
reg                                   ddr_we_n_kbar_neg;
wire                                  em_ddr_we_n;

wire                                  ddr_cas_n_kpos;
reg                                   ddr_cas_n_kbar_neg;
wire                                  em_ddr_cas_n;

wire    [`CS_WIDTH-1:0]               ddr_cs_n_kpos;
reg     [`CS_WIDTH-1:0]               ddr_cs_n_kbar_neg;
wire    [`CS_WIDTH-1:0]               em_ddr_cs_n;
wire                                  em_ddr_cs_n1;

wire    [1:0]                         ddr_dqs_out;
reg     [1:0]                         ddr_dqs_out_kbar_neg;
reg     [1:0]                         int_ddr_dqs_out_kbar_neg;

wire                                  ddr_write_enable_kpos;
wire                                  ddr_write_enable_early_kpos;
reg                                   ddr_write_enable_kbar_neg;
reg                                   ddr_write_enable;
////////////////////////////////////////////////////////////////////////////
// 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

reg                                   ddr_write_enable_kneg;
reg                                   ddr_write_enable_kneg_d;

always @ (negedge k_clk or negedge rst_n) begin
    if (!rst_n) begin
	ddr_write_enable_kneg       <= 1'b1;
	ddr_write_enable_kneg_d     <= 1'b1;
    end
    else begin
	ddr_write_enable_kneg       <= ddr_write_enable_early_kpos;
	ddr_write_enable_kneg_d     <= ddr_write_enable_kneg;
    end
end

always @ (negedge kbar_clk or negedge rst_n) begin
    if (!rst_n) begin
	ddr_addr_kbar_neg           <= {`ROW_WIDTH{1'b0}};
	ddr_ba_kbar_neg             <= 2'b00;
	ddr_cke_kbar_neg            <= 1'b0;
	ddr_ras_n_kbar_neg          <= 1'b1;
	ddr_cas_n_kbar_neg          <= 1'b1;
	ddr_we_n_kbar_neg           <= 1'b1;
	ddr_cs_n_kbar_neg           <= {`CS_WIDTH{1'b1}};

	ddr_dqs_out_kbar_neg        <= 2'b00;
	int_ddr_dqs_out_kbar_neg    <= 2'b00;

	ddr_write_enable_kbar_neg   <= 1'b1;
    end
    else begin

        // 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
end

// Use ODDRXB to drive the address and control signals

ODDRXB U_ODDR_CKE0 (.DA(ddr_cke_kbar_neg), .DB(ddr_cke_kbar_neg), .LSR(~rst_n), 
                  .CLK(kbar_clk), .Q(em_ddr_cke0));

ODDRXB U_ODDR_CKE1 (.DA(ddr_cke_kbar_neg), .DB(ddr_cke_kbar_neg), .LSR(~rst_n), 
                  .CLK(kbar_clk), .Q(em_ddr_cke1));

ODDRXB U_ODDR_RAS (.DA(ddr_ras_n_kbar_neg), .DB(ddr_ras_n_kbar_neg), .LSR(~rst_n), 
                  .CLK(kbar_clk), .Q(em_ddr_ras_n));

ODDRXB U_ODDR_CAS (.DA(ddr_cas_n_kbar_neg), .DB(ddr_cas_n_kbar_neg), .LSR(~rst_n), 
                  .CLK(kbar_clk), .Q(em_ddr_cas_n));

ODDRXB U_ODDR_WE (.DA(ddr_we_n_kbar_neg), .DB(ddr_we_n_kbar_neg), .LSR(~rst_n), 
                  .CLK(kbar_clk), .Q(em_ddr_we_n));

ODDRXB U_ODDR_CS[`CS_WIDTH-1:0] (.DA(ddr_cs_n_kbar_neg), .DB(ddr_cs_n_kbar_neg), .LSR(~rst_n), 
                  .CLK(kbar_clk), .Q(em_ddr_cs_n));

ODDRXB U_ODDR_CS1 (.DA(ddr_cs_n_kbar_neg), .DB(ddr_cs_n_kbar_neg), .LSR(~rst_n), 
                  .CLK(kbar_clk), .Q(em_ddr_cs_n1));

ODDRXB U_ODDR_BA0 (.DA(ddr_ba_kbar_neg[0]), .DB(ddr_ba_kbar_neg[0]), .LSR(~rst_n), 
                  .CLK(kbar_clk), .Q(em_ddr_ba[0]));

ODDRXB U_ODDR_BA1 (.DA(ddr_ba_kbar_neg[1]), .DB(ddr_ba_kbar_neg[1]), .LSR(~rst_n), 
                  .CLK(kbar_clk), .Q(em_ddr_ba[1]));

ODDRXB U_ODDR_ADDR[`ROW_WIDTH-1:0] (.DA(ddr_addr_kbar_neg), .DB(ddr_addr_kbar_neg),
                  .LSR(~rst_n), .CLK(kbar_clk), .Q(em_ddr_addr));

always @ (posedge kbar_clk or negedge rst_n) begin
    if (!rst_n) begin
	ddr_write_enable            <= 1'b1;
    end
    else begin
        // This is a 1/2 clock cycle transfer
	ddr_write_enable            <= ddr_write_enable_kbar_neg;
    end
end

////////////////////////////////////////////////////////////////////////////
// Get the write data from the core and 
// flop it on the falling k_clk before feeding it to the ddr_io block.
always @ (negedge rst_n or  posedge k_clk) begin
   if (!rst_n) begin 
      em_write_data_tmp_d <= {`DSIZE{1'b0}};
      ddr_dm_tmp_d  <= {`USER_DM{1'b0}};
   end
   else begin
      em_write_data_tmp_d <= em_write_data_tmp;  
      ddr_dm_tmp_d  <= ddr_dm_tmp;
   end
end

always @ (negedge rst_n or  negedge k_clk) begin
   if (!rst_n) begin 
      em_write_data <= {`DSIZE{1'b0}};
      ddr_dm        <= {`USER_DM{1'b0}};
   end
   else begin
      em_write_data <= em_write_data_tmp_d;  
      ddr_dm        <= ddr_dm_tmp_d;
   end
end
////////////////////////////////////////////////////////////////////////////
ddrct_gen_e2_1_001 U1_ddrct_gen_e2_1_001 (

    .clk                 (k_clk),
    .rst_n               (rst_n),

    // User Interface control and data Input signals
    .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      (`DATA_VALID_TAP),
    //.dataout_valid       (read_data_valid),
    .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),

    `ifdef DDR2_MODE
	.trtp            (`TRTP),
	.twtr            (`TWTR),
        .tckp            (`TCKP),
    `else
        .ext_reg_en      (`EXT_REG_EN),
        .fb_burst_term   (burst_term),
    `endif

    // User Interface Output signals
    .fb_cmd_rdy          (cmd_rdy),
    .fb_data_rdy         (data_rdy),
    .init_done           (init_done),

    // Pio read signal
    .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),

    `ifdef DDR2_MODE
        .ddr_odt         (em_ddr_odt),
    `endif

    .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

albuf U1_albuf (
   .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       (`DATA_VALID_TAP),
   .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.
always @ (posedge k_clk or negedge rst_n) begin
    if (!rst_n) begin
        update_cntl                <= 1'b1;
        latch_ctrl_count           <= 4'd15;
        open_latch                 <= 1'b1;
    end
    else begin
        if (read_command) begin
            update_cntl            <= 1'b0;
            latch_ctrl_count       <= 4'd15;
            open_latch             <= 1'b0;
        end
        else begin
            if (latch_ctrl_count != 4'd0)
                latch_ctrl_count   <= latch_ctrl_count-1;

            if (latch_ctrl_count == 4'd0)
                open_latch         <= 1'b1;

            if (open_latch)
                update_cntl        <= 1'b1;
        end
    end
end



///////////////////////////////////////////////////////////////////////////
// Instantiate the FPGA I/O and DLL

wire    [`DATA_WIDTH/8-1:0]            ddr_dqs_in;
wire                                   dqsdel;

DQSDLL U1_DQSDLL (.CLK(k_clk), .RST(~rst_n), .UDDCNTL(update_cntl), 
                  .DQSDEL(dqsdel), .LOCK());
    
`ifdef DATA_SIZE_72
    ddr_data72_io U1_ddr_data72_io (
        .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)
    );

    ddr_dm72_io U1_ddr_dm72_io (
        .clk                    (~k_clk),
        .rst                    (~rst_n),
        .data_in                (ddr_dm),
        .ddr_dataout            (em_ddr_dm)
    );

    ddr_dqs72_io U1_ddr_dqs72_io (
	.rst                    (~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            (),
	.prmbdet                (prmbdet),
	.ddrclkpol              (ddrclkpol),
	.ddr_dqs_out            (ddr_dqs_out_kbar_neg),
	.dqsi                   (dqsi),
        .bidi                   (em_ddr_dqs)
    );

    ddr_pior72 U1_ddr_pior72 (
        .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),
        .sel_phase_4            (`PIO_RD_DQS4),
        .sel_phase_5            (`PIO_RD_DQS5),
        .sel_phase_6            (`PIO_RD_DQS6),
        .sel_phase_7            (`PIO_RD_DQS7),
        .sel_phase_7            (`PIO_RD_DQS8),
        .pio_read_dly           (pio_read_dly),
        .pio_read_early         (pio_read_early),
        .pio_read_out           (pio_read_out)
    );

`endif

`ifdef DATA_SIZE_64
    ddr_data64_io U1_ddr_data64_io (
        .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)
    );

    ddr_dm64_io U1_ddr_dm64_io (
        .clk                    (~k_clk),
        .rst                    (~rst_n),
        .data_in                (ddr_dm),
        .ddr_dataout            (em_ddr_dm)
    );

    ddr_dqs64_io U1_ddr_dqs64_io (
	.rst                    (~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            (),
	.prmbdet                (prmbdet),
	.ddrclkpol              (ddrclkpol),
	.ddr_dqs_out            (ddr_dqs_out_kbar_neg),
	.dqsi                   (dqsi),
        .bidi                   (em_ddr_dqs)
    );

    ddr_pior64 U1_ddr_pior64 (
        .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),
        .sel_phase_4            (`PIO_RD_DQS4),
        .sel_phase_5            (`PIO_RD_DQS5),
        .sel_phase_6            (`PIO_RD_DQS6),
        .sel_phase_7            (`PIO_RD_DQS7),
        .pio_read_dly           (pio_read_dly),
        .pio_read_early         (pio_read_early),
        .pio_read_out           (pio_read_out)
    );

`endif

`ifdef DATA_SIZE_32
    ddr_data32_io U1_ddr_data32_io (
        .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)
    );

    ddr_dm32_io U1_ddr_dm32_io (
        .clk                    (~k_clk),
        .rst                    (~rst_n),
        .data_in                (ddr_dm),
        .ddr_dataout            (em_ddr_dm)
    );

    ddr_dqs32_io U1_ddr_dqs32_io (
	.rst                    (~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            (),
	.prmbdet                (prmbdet),
	.ddrclkpol              (ddrclkpol),
	.ddr_dqs_out            (ddr_dqs_out_kbar_neg),
	.dqsi                   (dqsi),
        .bidi                   (em_ddr_dqs)
    );

    ddr_pior32 U1_ddr_pior32 (
	.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)
    );
`endif

`ifdef DATA_SIZE_16
    ddr_data16_io U1_ddr_data16_io (
        .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)
    );

    ddr_dm16_io U1_ddr_dm16_io (
        .clk                    (~k_clk),
        .rst                    (~rst_n),
        .data_in                (ddr_dm),
        .ddr_dataout            (em_ddr_dm)
    );

    ddr_dqs16_io U1_ddr_dqs16_io (
	.rst                    (~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            (),
	.prmbdet                (prmbdet),
	.ddrclkpol              (ddrclkpol),
	.ddr_dqs_out            (ddr_dqs_out_kbar_neg),
	.dqsi                   (dqsi),
        .bidi                   (em_ddr_dqs)
    );

    ddr_pior16 U1_ddr_pior16 (
        .rst_n                  (rst_n),
        .k_clk                  (k_clk),
        .kbar_clk               (kbar_clk),
        .sel_phase_0            (`PIO_RD_DQS0),
        .sel_phase_1            (`PIO_RD_DQS1),
        .pio_read_dly           (pio_read_dly),
        .pio_read_early         (pio_read_early),
        .pio_read_out           (pio_read_out)
    );

`endif

`ifdef DATA_SIZE_8
    ddr_data8_io U1_ddr_data8_io (
        .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)
    );

    ddr_dm8_io U1_ddr_dm8_io (
        .clk                    (~k_clk),
        .rst                    (~rst_n),
        .data_in                (ddr_dm),
        .ddr_dataout            (em_ddr_dm)
    );

    ddr_dqs8_io U1_ddr_dqs8_io (
	.rst                    (~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            (),
	.prmbdet                (prmbdet),
	.ddrclkpol              (ddrclkpol),
	.ddr_dqs_out            (ddr_dqs_out_kbar_neg),
	.dqsi                   (dqsi),
        .bidi                   (em_ddr_dqs)
    );

    ddr_pior8 U1_ddr_pior8 (
        .rst_n                  (rst_n),
        .k_clk                  (k_clk),
        .kbar_clk               (kbar_clk),
        .sel_phase_0            (`PIO_RD_DQS0),
        .pio_read_dly           (pio_read_dly),
        .pio_read_early         (pio_read_early),
        .pio_read_out           (pio_read_out)
    );

`endif

//////////////////////////////////////////////////////////////
endmodule
