//*****************************************************************************
// (c) Copyright 2008 - 2010 Xilinx, Inc. All rights reserved.
//
// This file contains confidential and proprietary information
// of Xilinx, Inc. and is protected under U.S. and
// international copyright and other intellectual property
// laws.
//
// DISCLAIMER
// This disclaimer is not a license and does not grant any
// rights to the materials distributed herewith. Except as
// otherwise provided in a valid license issued to you by
// Xilinx, and to the maximum extent permitted by applicable
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
// (2) Xilinx shall not be liable (whether in contract or tort,
// including negligence, or under any other theory of
// liability) for any loss or damage of any kind or nature
// related to, arising under or in connection with these
// materials, including for any direct, or any indirect,
// special, incidental, or consequential loss or damage
// (including loss of data, profits, goodwill, or any type of
// loss or damage suffered as a result of any action brought
// by a third party) even if such damage or loss was
// reasonably foreseeable or Xilinx had been advised of the
// possibility of the same.
//
// CRITICAL APPLICATIONS
// Xilinx products are not designed or intended to be fail-
// safe, or for use in any application requiring fail-safe
// performance, such as life-support or safety devices or
// systems, Class III medical devices, nuclear facilities,
// applications related to the deployment of airbags, or any
// other applications that could lead to death, personal
// injury, or severe property or environmental damage
// (individually and collectively, "Critical
// Applications"). Customer assumes the sole risk and
// liability of any use of Xilinx products in Critical
// Applications, subject only to applicable laws and
// regulations governing limitations on product liability.
//
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
// PART OF THIS FILE AT ALL TIMES.
//
//*****************************************************************************
//   ____  ____
//  /   /\/   /
// /___/  \  /    Vendor                : Xilinx
// \   \   \/     Version               : %version
//  \   \         Application           : MIG
//  /   /         Filename              : mem_intfc.v
// /___/   /\     Date Last Modified    : $date$
// \   \  /  \    Date Created          : Aug 03 2009
//  \___\/\___\
//
//Device            : 7-Series
//Design Name       : DDR3 SDRAM
//Purpose           : Top level memory interface block. Instantiates a clock 
//                    and reset generator, the memory controller, the phy and 
//                    the user interface blocks.
//Reference         :
//Revision History  :
//*****************************************************************************

`timescale 1 ps / 1 ps

module mem_intfc #
  (
   parameter TCQ = 100,
   parameter PAYLOAD_WIDTH   = 64,
   parameter ADDR_CMD_MODE   = "1T",
   parameter AL              = "0",     // Additive Latency option
   parameter BANK_WIDTH      = 3,       // # of bank bits
   parameter BM_CNT_WIDTH    = 2,       // Bank machine counter width
   parameter BURST_MODE      = "8",     // Burst length
   parameter BURST_TYPE      = "SEQ",   // Burst type
   parameter CK_WIDTH        = 1,       // # of CK/CK# outputs to memory
   // five fields, one per possible I/O bank, 4 bits in each field, 1 per lane
   // data=1/ctl=0
   parameter DATA_CTL_B0     = 4'hc,
   parameter DATA_CTL_B1     = 4'hf,
   parameter DATA_CTL_B2     = 4'hf,
   parameter DATA_CTL_B3     = 4'hf,
   parameter DATA_CTL_B4     = 4'hf,
   // defines the byte lanes in I/O banks being used in the interface
   // 1- Used, 0- Unused
   parameter BYTE_LANES_B0   = 4'b1111,
   parameter BYTE_LANES_B1   = 4'b0000,
   parameter BYTE_LANES_B2   = 4'b0000,
   parameter BYTE_LANES_B3   = 4'b0000,
   parameter BYTE_LANES_B4   = 4'b0000,
   // defines the bit lanes in I/O banks being used in the interface. Each 
   // parameter = 1 I/O bank = 4 byte lanes = 48 bit lanes. 1-Used, 0-Unused
   parameter PHY_0_BITLANES  = 48'h0000_0000_0000,
   parameter PHY_1_BITLANES  = 48'h0000_0000_0000,
   parameter PHY_2_BITLANES  = 48'h0000_0000_0000,

   // control/address/data pin mapping parameters
   parameter CK_BYTE_MAP
     = 144'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00,
   parameter ADDR_MAP    
     = 192'h000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000,
   parameter BANK_MAP   = 36'h000_000_000,
   parameter CAS_MAP    = 12'h000,
   parameter CKE_ODT_BYTE_MAP = 8'h00,
   parameter CS_MAP     = 120'h000_000_000_000_000_000_000_000_000_000,
   parameter PARITY_MAP = 12'h000,
   parameter RAS_MAP    = 12'h000,
   parameter WE_MAP     = 12'h000,
   parameter DQS_BYTE_MAP         
     = 144'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00,
   parameter DATA0_MAP  = 96'h000_000_000_000_000_000_000_000,
   parameter DATA1_MAP  = 96'h000_000_000_000_000_000_000_000,
   parameter DATA2_MAP  = 96'h000_000_000_000_000_000_000_000,
   parameter DATA3_MAP  = 96'h000_000_000_000_000_000_000_000,
   parameter DATA4_MAP  = 96'h000_000_000_000_000_000_000_000,
   parameter DATA5_MAP  = 96'h000_000_000_000_000_000_000_000,
   parameter DATA6_MAP  = 96'h000_000_000_000_000_000_000_000,
   parameter DATA7_MAP  = 96'h000_000_000_000_000_000_000_000,
   parameter DATA8_MAP  = 96'h000_000_000_000_000_000_000_000,
   parameter DATA9_MAP  = 96'h000_000_000_000_000_000_000_000,
   parameter DATA10_MAP = 96'h000_000_000_000_000_000_000_000,
   parameter DATA11_MAP = 96'h000_000_000_000_000_000_000_000,
   parameter DATA12_MAP = 96'h000_000_000_000_000_000_000_000,
   parameter DATA13_MAP = 96'h000_000_000_000_000_000_000_000,
   parameter DATA14_MAP = 96'h000_000_000_000_000_000_000_000,
   parameter DATA15_MAP = 96'h000_000_000_000_000_000_000_000,
   parameter DATA16_MAP = 96'h000_000_000_000_000_000_000_000,
   parameter DATA17_MAP = 96'h000_000_000_000_000_000_000_000,
   parameter MASK0_MAP  = 108'h000_000_000_000_000_000_000_000_000,
   parameter MASK1_MAP  = 108'h000_000_000_000_000_000_000_000_000,

   // calibration Address. The address given below will be used for calibration
   // read and write operations. 
   parameter CALIB_ROW_ADD   = 16'h0000,// Calibration row address
   parameter CALIB_COL_ADD   = 12'h000, // Calibration column address
   parameter CALIB_BA_ADD    = 3'h0,    // Calibration bank address
   parameter CL              = 5,       
   parameter COL_WIDTH       = 12,      // column address width
   parameter CMD_PIPE_PLUS1  = "ON",    // add pipeline stage between MC and PHY
   parameter CS_WIDTH        = 1,       // # of unique CS outputs
   parameter CKE_WIDTH       = 1,       // # of cke outputs 
   parameter CWL             = 5,
   parameter DATA_WIDTH      = 64,
   parameter DATA_BUF_ADDR_WIDTH = 8,
   parameter DATA_BUF_OFFSET_WIDTH = 1,
   parameter DDR2_DQSN_ENABLE = "YES",  // Enable differential DQS for DDR2
   parameter DM_WIDTH        = 8,       // # of DM (data mask)
   parameter DQ_CNT_WIDTH    = 6,       // = ceil(log2(DQ_WIDTH))
   parameter DQ_WIDTH        = 64,      // # of DQ (data)
   parameter DQS_CNT_WIDTH   = 3,       // = ceil(log2(DQS_WIDTH))
   parameter DQS_WIDTH       = 8,       // # of DQS (strobe)
   parameter DRAM_TYPE       = "DDR3",
   parameter DRAM_WIDTH      = 8,       // # of DQ per DQS
   parameter ECC             = "OFF",
   parameter ECC_WIDTH       = 8,
   parameter MC_ERR_ADDR_WIDTH = 31,
   parameter nAL             = 0,       // Additive latency (in clk cyc)
   parameter nBANK_MACHS     = 4,
   parameter nCK_PER_CLK     = 4,       // # of memory CKs per fabric CLK
   parameter nCS_PER_RANK    = 1,       // # of unique CS outputs per rank
   // Hard PHY parameters
   parameter PHYCTL_CMD_FIFO = "FALSE",
   parameter ORDERING        = "NORM",
   parameter PHASE_DETECT    = "OFF"  ,  // to phy_top
   parameter IBUF_LPWR_MODE  = "OFF",    // to phy_top
   parameter IODELAY_HP_MODE = "ON",     // to phy_top
   parameter IODELAY_GRP     = "IODELAY_MIG", //to phy_top
   parameter OUTPUT_DRV      = "HIGH" ,  // to phy_top
   parameter REG_CTRL        = "OFF"  ,  // to phy_top
   parameter RTT_NOM         = "60"   ,  // to phy_top
   parameter RTT_WR          = "120"   , // to phy_top
   parameter STARVE_LIMIT    = 2,
   parameter tCK             = 2500,         // pS
   parameter tFAW            = 40000,        // pS
   parameter tPRDI           = 1_000_000,    // pS
   parameter tRAS            = 37500,        // pS
   parameter tRCD            = 12500,        // pS
   parameter tREFI           = 7800000,      // pS
   parameter tRFC            = 110000,       // pS
   parameter tRP             = 12500,        // pS
   parameter tRRD            = 10000,        // pS
   parameter tRTP            = 7500,         // pS
   parameter tWTR            = 7500,         // pS
   parameter tZQI            = 128_000_000,  // nS
   parameter tZQCS           = 64,           // CKs
   parameter WRLVL           = "OFF"  ,  // to phy_top
   parameter DEBUG_PORT      = "OFF"  ,  // to phy_top
   parameter CAL_WIDTH       = "HALF" ,  // to phy_top
   parameter RANK_WIDTH      = 1,
   parameter RANKS           = 4,
   parameter ROW_WIDTH       = 16,       // DRAM address bus width
   parameter [7:0] SLOT_0_CONFIG = 8'b0000_0001,
   parameter [7:0] SLOT_1_CONFIG = 8'b0000_0000,
   parameter SIM_BYPASS_INIT_CAL = "OFF",
   parameter REFCLK_FREQ     = 300.0,
   parameter nDQS_COL0       = DQS_WIDTH,
   parameter nDQS_COL1       = 0,
   parameter nDQS_COL2       = 0,
   parameter nDQS_COL3       = 0,
   parameter DQS_LOC_COL0    = 144'h11100F0E0D0C0B0A09080706050403020100,
   parameter DQS_LOC_COL1    = 0,
   parameter DQS_LOC_COL2    = 0,
   parameter DQS_LOC_COL3    = 0,
   parameter USE_CS_PORT     = 1,     // Support chip select output
   parameter USE_DM_PORT     = 1,     // Support data mask output
   parameter USE_ODT_PORT    = 1      // Support ODT output
  )
  (
   input                  clk_ref,
   input                  freq_refclk,
   input                  mem_refclk,
   input                  pll_lock,
   input                  sync_pulse,

   input [BANK_WIDTH-1:0] bank,                   // To mc0 of mc.v
   input                  clk ,
   input [2:0]            cmd,                    // To mc0 of mc.v
   input [COL_WIDTH-1:0]  col,                    // To mc0 of mc.v
   input                  correct_en,
   input [DATA_BUF_ADDR_WIDTH-1:0] data_buf_addr, // To mc0 of mc.v
 
   input                     dbg_idel_down_all,
   input                     dbg_idel_down_cpt,
   input                     dbg_idel_up_all,
   input                     dbg_idel_up_cpt,
   input                     dbg_sel_all_idel_cpt,
   input [DQS_CNT_WIDTH-1:0] dbg_sel_idel_cpt,
   input                     hi_priority,            // To mc0 of mc.v
   input [RANK_WIDTH-1:0]    rank,                   // To mc0 of mc.v
   input [2*nCK_PER_CLK-1:0]               raw_not_ecc,
   input [ROW_WIDTH-1:0]     row,                    // To mc0 of mc.v
   input                     rst,                    // To mc0 of mc.v, ...
   input                     size,                   // To mc0 of mc.v
   input [7:0]               slot_0_present,         // To mc0 of mc.v
   input [7:0]               slot_1_present,         // To mc0 of mc.v
   input                     use_addr,               // To mc0 of mc.v
   input [2*nCK_PER_CLK*PAYLOAD_WIDTH-1:0] wr_data,
   input [2*nCK_PER_CLK*DATA_WIDTH/8-1:0]  wr_data_mask,
  
   output                   accept,             // From mc0 of mc.v
   output                   accept_ns,          // From mc0 of mc.v
   output [BM_CNT_WIDTH-1:0] bank_mach_next,     // From mc0 of mc.v
   
   output [255:0]            dbg_calib_top,
   output [5*DQS_WIDTH-1:0]  dbg_cpt_first_edge_cnt,
   output [5*DQS_WIDTH-1:0]  dbg_cpt_second_edge_cnt,
   output [255:0]            dbg_phy_rdlvl,
   output [99:0]             dbg_phy_wrcal,  
   output [DQS_WIDTH-1:0]    dbg_rd_data_edge_detect,
   output [4*DQ_WIDTH-1:0]   dbg_rddata,  
   output [1:0]              dbg_rdlvl_done,
   output [1:0]              dbg_rdlvl_err,
   output [1:0]              dbg_rdlvl_start,  
   output [4:0]              dbg_tap_cnt_during_wrlvl,  
   output                    dbg_wl_edge_detect_valid,  
   output                    dbg_wrlvl_done,  
   output                    dbg_wrlvl_err,
   output                    dbg_wrlvl_start,

   output [ROW_WIDTH-1:0]    ddr_addr,           // From phy_top0 of phy_top.v
   output [BANK_WIDTH-1:0]   ddr_ba,             // From phy_top0 of phy_top.v
   output                    ddr_cas_n,          // From phy_top0 of phy_top.v
   output [CK_WIDTH-1:0]     ddr_ck_n,           // From phy_top0 of phy_top.v
   output [CK_WIDTH-1:0]     ddr_ck  ,           // From phy_top0 of phy_top.v
   output [CKE_WIDTH-1:0]    ddr_cke,            // From phy_top0 of phy_top.v
   output [CS_WIDTH*nCS_PER_RANK-1:0] ddr_cs_n,  // From phy_top0 of phy_top.v
   output [DM_WIDTH-1:0]     ddr_dm,             // From phy_top0 of phy_top.v
   output [RANKS-1:0]        ddr_odt,            // From phy_top0 of phy_top.v
   output                    ddr_ras_n,          // From phy_top0 of phy_top.v
   output                    ddr_reset_n,        // From phy_top0 of phy_top.v
   output                    ddr_parity,
   output                    ddr_we_n,           // From phy_top0 of phy_top.v
   output                         init_calib_complete,
   output [MC_ERR_ADDR_WIDTH-1:0] ecc_err_addr,
   output [2*nCK_PER_CLK-1:0]                   ecc_multiple,
   output [2*nCK_PER_CLK-1:0]                   ecc_single,

   output wire [2*nCK_PER_CLK*PAYLOAD_WIDTH-1:0] rd_data,
   output [DATA_BUF_ADDR_WIDTH-1:0]              rd_data_addr,
                                                      // From mc0 of mc.v  
   output                             rd_data_en,     // From mc0 of mc.v
   output                             rd_data_end,    // From mc0 of mc.v
   output [DATA_BUF_OFFSET_WIDTH-1:0] rd_data_offset, // From mc0 of mc.v
   output [DATA_BUF_ADDR_WIDTH-1:0]   wr_data_addr,   // From mc0 of mc.v
   output                             wr_data_en,     // From mc0 of mc.v
   output [DATA_BUF_OFFSET_WIDTH-1:0] wr_data_offset, // From mc0 of mc.v

   inout [DQ_WIDTH-1:0]      ddr_dq,       // To/From phy_top0 of phy_top.v
   inout [DQS_WIDTH-1:0]     ddr_dqs_n,    // To/From phy_top0 of phy_top.v
   inout [DQS_WIDTH-1:0]     ddr_dqs       // To/From phy_top0 of phy_top.v
   );
  
  localparam nSLOTS  = 1 + (|SLOT_1_CONFIG ? 1 : 0);
  localparam SLOT_0_CONFIG_MC = (nSLOTS == 2)? 8'b0000_0101 : 8'b0000_1111;
  localparam SLOT_1_CONFIG_MC = (nSLOTS == 2)? 8'b0000_1010 : 8'b0000_0000; 

  reg [7:0]               slot_0_present_mc;
  reg [7:0]               slot_1_present_mc; 
   
  reg user_periodic_rd_req = 1'b0;
  reg user_ref_req = 1'b0;
  reg user_zq_req = 1'b0;

  // MC/PHY interface
  wire [nCK_PER_CLK-1:0]              mc_ras_n;
  wire [nCK_PER_CLK-1:0]              mc_cas_n;
  wire [nCK_PER_CLK-1:0]              mc_we_n;
  wire [nCK_PER_CLK*ROW_WIDTH-1:0]    mc_address;
  wire [nCK_PER_CLK*BANK_WIDTH-1:0]   mc_bank;
  wire [CS_WIDTH*nCS_PER_RANK*nCK_PER_CLK-1:0] mc_cs_n;
  wire                                mc_reset_n;
  wire [2*nCK_PER_CLK*DQ_WIDTH-1:0]   mc_wrdata;
  wire [2*nCK_PER_CLK*DQ_WIDTH/8-1:0] mc_wrdata_mask;
  wire                                mc_wrdata_en;
  
  wire                                mc_cmd_wren;
  wire                                mc_ctl_wren;
  wire  [2:0]                         mc_cmd;
  wire  [1:0]                         mc_cas_slot;
  wire  [5:0]                         mc_data_offset;
  wire  [3:0]                         mc_aux_out0;
  wire  [3:0]                         mc_aux_out1;
  wire  [1:0]                         mc_rank_cnt;

  wire                                phy_mc_ctl_full;
  wire                                phy_mc_cmd_full;
  wire                                phy_mc_data_full;
  wire  [2*nCK_PER_CLK*DQ_WIDTH-1:0]  phy_rd_data;
  wire                                phy_rddata_valid;
  
  wire  [6*RANKS-1:0]                 calib_rd_data_offset;
  
  // assigning CWL = CL -1 for DDR2. DDR2 customers will not know anything
  // about CWL. There is also nCWL parameter. Need to clean it up.
  localparam CWL_T = (DRAM_TYPE == "DDR3") ? CWL : CL-1;

  generate
    if (nSLOTS == 1) begin: gen_single_slot_odt
      always @ (slot_0_present[0] or slot_0_present[1]
                or slot_0_present[2] or slot_0_present[3]) begin
        slot_0_present_mc = slot_0_present;
        slot_1_present_mc = slot_1_present;
      end
    end else if (nSLOTS == 2) begin: gen_dual_slot_odt
        always @ (slot_0_present[0] or slot_0_present[1]
                or slot_1_present[0] or slot_1_present[1]) begin
        case ({slot_0_present[0],slot_0_present[1],  
               slot_1_present[0],slot_1_present[1]}) 
          //Two slot configuration, one slot present, single rank
          4'b1000: begin
             slot_0_present_mc = 8'b0000_0001;       
             slot_1_present_mc = 8'b0000_0000; 
          end
          4'b0010: begin
            slot_0_present_mc = 8'b0000_0000;        
            slot_1_present_mc = 8'b0000_0010;
          end
          // Two slot configuration, one slot present, dual rank
          4'b1100: begin
            slot_0_present_mc = 8'b0000_0101;        
            slot_1_present_mc = 8'b0000_0000;
          end
          4'b0011: begin
            slot_0_present_mc = 8'b0000_0000;        
            slot_1_present_mc = 8'b0000_1010;
          end
          // Two slot configuration, one rank per slot
          4'b1010: begin
            slot_0_present_mc = 8'b0000_0001;        
            slot_1_present_mc = 8'b0000_0010;
          end
          // Two Slots - One slot with dual rank and the other with single rank
          4'b1011: begin
            slot_0_present_mc = 8'b0000_0001;        
            slot_1_present_mc = 8'b0000_1010;
          end
          4'b1110: begin
            slot_0_present_mc = 8'b0000_0101;        
            slot_1_present_mc = 8'b0000_0010;
          end
          // Two Slots - two ranks per slot
          4'b1111: begin
            slot_0_present_mc = 8'b0000_0101;        
            slot_1_present_mc = 8'b0000_1010;
          end
        endcase
      end
    end
  endgenerate

  mc #
   (
    .TCQ                                (TCQ),
    .PAYLOAD_WIDTH                      (PAYLOAD_WIDTH),
    .MC_ERR_ADDR_WIDTH                  (MC_ERR_ADDR_WIDTH),
    .ADDR_CMD_MODE                      (ADDR_CMD_MODE),
    .BANK_WIDTH                         (BANK_WIDTH),
    .BM_CNT_WIDTH                       (BM_CNT_WIDTH),
    .BURST_MODE                         (BURST_MODE),
    .COL_WIDTH                          (COL_WIDTH),
    .CMD_PIPE_PLUS1                     (CMD_PIPE_PLUS1),
    .CS_WIDTH                           (CS_WIDTH),
    .DATA_WIDTH                         (DATA_WIDTH),
    .DATA_BUF_ADDR_WIDTH                (DATA_BUF_ADDR_WIDTH),
    .DATA_BUF_OFFSET_WIDTH              (DATA_BUF_OFFSET_WIDTH),
    .DRAM_TYPE                          (DRAM_TYPE),
    .DQS_WIDTH                          (DQS_WIDTH),
    .DQ_WIDTH                           (DQ_WIDTH),
    .ECC                                (ECC),
    .ECC_WIDTH                          (ECC_WIDTH),
    .nBANK_MACHS                        (nBANK_MACHS),
    .nCK_PER_CLK                        (nCK_PER_CLK),
    .nSLOTS                             (nSLOTS),
    .CL                                 (CL),
    .nCS_PER_RANK                       (nCS_PER_RANK),
    .CWL                                (CWL_T),
    .ORDERING                           (ORDERING),
    .RANK_WIDTH                         (RANK_WIDTH),
    .RANKS                              (RANKS),
    .REG_CTRL                           (REG_CTRL),
    .ROW_WIDTH                          (ROW_WIDTH),
    .RTT_NOM                            (RTT_NOM),
    .RTT_WR                             (RTT_WR),
    .STARVE_LIMIT                       (STARVE_LIMIT),
    .SLOT_0_CONFIG                      (SLOT_0_CONFIG_MC),
    .SLOT_1_CONFIG                      (SLOT_1_CONFIG_MC),
    .tCK                                (tCK),
    .tFAW                               (tFAW),
    .tRAS                               (tRAS),
    .tRCD                               (tRCD),
    .tREFI                              (tREFI),
    .tRFC                               (tRFC),
    .tRP                                (tRP),
    .tRRD                               (tRRD),
    .tRTP                               (tRTP),
    .tWTR                               (tWTR),
    .tZQI                               (tZQI),
    .tZQCS                              (tZQCS))
   mc0
     (.app_periodic_rd_req  (1'b0),
      .app_ref_req          (1'b0),
      .app_zq_req           (1'b0),
      .ecc_single           (ecc_single),
      .ecc_multiple         (ecc_multiple),
      .ecc_err_addr         (ecc_err_addr),
      .mc_address           (mc_address),
      .mc_aux_out0          (mc_aux_out0),
      .mc_aux_out1          (mc_aux_out1),
      .mc_bank              (mc_bank),
      .mc_cas_n             (mc_cas_n),
      .mc_cmd               (mc_cmd),
      .mc_cmd_wren          (mc_cmd_wren),
      .mc_cs_n              (mc_cs_n),
      .mc_ctl_wren          (mc_ctl_wren),
      .mc_data_offset       (mc_data_offset),
      .mc_cas_slot          (mc_cas_slot),
      .mc_rank_cnt          (mc_rank_cnt),
      .mc_ras_n             (mc_ras_n),
      .mc_reset_n           (mc_reset_n),
      .mc_we_n              (mc_we_n),
      .mc_wrdata            (mc_wrdata),
      .mc_wrdata_en         (mc_wrdata_en),
      .mc_wrdata_mask       (mc_wrdata_mask),
      // Outputs
      .accept               (accept),
      .accept_ns            (accept_ns),
      .bank_mach_next       (bank_mach_next[BM_CNT_WIDTH-1:0]),
      .rd_data_addr         (rd_data_addr[DATA_BUF_ADDR_WIDTH-1:0]),
      .rd_data_en           (rd_data_en),
      .rd_data_end          (rd_data_end),
      .rd_data_offset       (rd_data_offset),
      .wr_data_addr         (wr_data_addr[DATA_BUF_ADDR_WIDTH-1:0]),
      .wr_data_en           (wr_data_en),
      .wr_data_offset       (wr_data_offset),
      .rd_data              (rd_data),
      .wr_data              (wr_data),
      .wr_data_mask         (wr_data_mask),
      // Inputs
      .init_calib_complete  (init_calib_complete),
      .calib_rd_data_offset (calib_rd_data_offset),
      .phy_mc_ctl_full      (phy_mc_ctl_full),
      .phy_mc_cmd_full      (phy_mc_cmd_full),
      .phy_mc_data_full     (phy_mc_data_full),
      .phy_rd_data          (phy_rd_data),
      .phy_rddata_valid     (phy_rddata_valid),
      .correct_en           (correct_en),
      .bank                 (bank[BANK_WIDTH-1:0]),
      .clk                  (clk),
      .cmd                  (cmd[2:0]),
      .col                  (col[COL_WIDTH-1:0]),
      .data_buf_addr        (data_buf_addr[DATA_BUF_ADDR_WIDTH-1:0]),
      .hi_priority          (hi_priority),
      .rank                 (rank[RANK_WIDTH-1:0]),
      .raw_not_ecc          (raw_not_ecc[2*nCK_PER_CLK-1 :0]),
      .row                  (row[ROW_WIDTH-1:0]),
      .rst                  (rst),
      .size                 (size),
      .slot_0_present       (slot_0_present_mc[7:0]),
      .slot_1_present       (slot_1_present_mc[7:0]),
      .use_addr             (use_addr));

  // following calculations should be moved inside PHY
  // odt bus should  be added to PHY.
  localparam CLK_PERIOD = tCK * nCK_PER_CLK;
  localparam nCL  = CL;
  localparam nCWL = CWL_T;
`ifdef MC_SVA
  ddr2_improper_CL: assert property
     (@(posedge clk) (~((DRAM_TYPE == "DDR2") && ((CL > 6) || (CL < 3)))));
  // Not needed after the CWL fix for DDR2
  //  ddr2_improper_CWL: assert property
  //     (@(posedge clk) (~((DRAM_TYPE == "DDR2") && ((CL - CWL) != 1))));
`endif

  phy_top #
    (
     .TCQ                (TCQ),
     .REFCLK_FREQ        (REFCLK_FREQ),
     .BYTE_LANES_B0      (BYTE_LANES_B0),
     .BYTE_LANES_B1      (BYTE_LANES_B1),
     .BYTE_LANES_B2      (BYTE_LANES_B2),
     .BYTE_LANES_B3      (BYTE_LANES_B3),
     .BYTE_LANES_B4      (BYTE_LANES_B4),
     .PHY_0_BITLANES     (PHY_0_BITLANES),
     .PHY_1_BITLANES     (PHY_1_BITLANES),
     .PHY_2_BITLANES     (PHY_2_BITLANES),
     .CK_BYTE_MAP        (CK_BYTE_MAP),
     .ADDR_MAP           (ADDR_MAP),
     .BANK_MAP           (BANK_MAP),
     .CAS_MAP            (CAS_MAP),
     .CKE_ODT_BYTE_MAP   (CKE_ODT_BYTE_MAP),
     .CS_MAP             (CS_MAP),
     .PARITY_MAP         (PARITY_MAP),
     .RAS_MAP            (RAS_MAP),
     .WE_MAP             (WE_MAP),
     .DQS_BYTE_MAP       (DQS_BYTE_MAP),
     .DATA0_MAP          (DATA0_MAP),
     .DATA1_MAP          (DATA1_MAP),
     .DATA2_MAP          (DATA2_MAP),
     .DATA3_MAP          (DATA3_MAP),
     .DATA4_MAP          (DATA4_MAP),
     .DATA5_MAP          (DATA5_MAP),
     .DATA6_MAP          (DATA6_MAP),
     .DATA7_MAP          (DATA7_MAP),
     .DATA8_MAP          (DATA8_MAP),
     .DATA9_MAP          (DATA9_MAP),
     .DATA10_MAP         (DATA10_MAP),
     .DATA11_MAP         (DATA11_MAP),
     .DATA12_MAP         (DATA12_MAP),
     .DATA13_MAP         (DATA13_MAP),
     .DATA14_MAP         (DATA14_MAP),
     .DATA15_MAP         (DATA15_MAP),
     .DATA16_MAP         (DATA16_MAP),
     .DATA17_MAP         (DATA17_MAP),
     .MASK0_MAP          (MASK0_MAP),
     .MASK1_MAP          (MASK1_MAP),
     .CALIB_ROW_ADD      (CALIB_ROW_ADD),
     .CALIB_COL_ADD      (CALIB_COL_ADD),
     .CALIB_BA_ADD       (CALIB_BA_ADD),
     .nCS_PER_RANK       (nCS_PER_RANK),
     .CS_WIDTH           (CS_WIDTH),
     .nCK_PER_CLK        (nCK_PER_CLK),
     .CKE_WIDTH          (CKE_WIDTH),
     .DATA_CTL_B0        (DATA_CTL_B0),
     .DATA_CTL_B1        (DATA_CTL_B1),
     .DATA_CTL_B2        (DATA_CTL_B2),
     .DATA_CTL_B3        (DATA_CTL_B3),
     .DATA_CTL_B4        (DATA_CTL_B4),
     .DDR2_DQSN_ENABLE   (DDR2_DQSN_ENABLE),
     .DRAM_TYPE          (DRAM_TYPE),
     .BANK_WIDTH         (BANK_WIDTH),
     .CK_WIDTH           (CK_WIDTH),
     .COL_WIDTH          (COL_WIDTH),
     .DM_WIDTH           (DM_WIDTH),
     .DQ_WIDTH           (DQ_WIDTH),
     .DQS_CNT_WIDTH      (DQS_CNT_WIDTH),
     .DQS_WIDTH          (DQS_WIDTH),
     .DRAM_WIDTH         (DRAM_WIDTH),
     .PHYCTL_CMD_FIFO    (PHYCTL_CMD_FIFO),
     .ROW_WIDTH          (ROW_WIDTH),
     .AL                 (AL),
     .ADDR_CMD_MODE      (ADDR_CMD_MODE),
     .BURST_MODE         (BURST_MODE),
     .BURST_TYPE         (BURST_TYPE),
     .CL                 (nCL),
     .CWL                (nCWL),
     .tRFC               (tRFC),
     .tCK                (tCK),
     .OUTPUT_DRV         (OUTPUT_DRV),
     .RANKS              (RANKS),
     .REG_CTRL           (REG_CTRL),
     .RTT_NOM            (RTT_NOM),
     .RTT_WR             (RTT_WR),
     .SLOT_1_CONFIG      (SLOT_1_CONFIG),
     .WRLVL              (WRLVL),
     .IODELAY_HP_MODE    (IODELAY_HP_MODE),
     .IODELAY_GRP        (IODELAY_GRP),
     // Prevent the following simulation-related parameters from
     // being overridden for synthesis - for synthesis only the
     // default values of these parameters should be used
     // synthesis translate_off
     .SIM_BYPASS_INIT_CAL (SIM_BYPASS_INIT_CAL),
     // synthesis translate_on
     .USE_CS_PORT        (USE_CS_PORT),
     .USE_DM_PORT        (USE_DM_PORT),
     .USE_ODT_PORT       (USE_ODT_PORT),
     .DEBUG_PORT         (DEBUG_PORT)
     )
    phy_top0
      (
       // Outputs
       .calib_rd_data_offset      (calib_rd_data_offset),
       .ddr_ck                    (ddr_ck),
       .ddr_ck_n                  (ddr_ck_n),
       .ddr_addr                  (ddr_addr),
       .ddr_ba                    (ddr_ba),
       .ddr_ras_n                 (ddr_ras_n),
       .ddr_cas_n                 (ddr_cas_n),
       .ddr_we_n                  (ddr_we_n),
       .ddr_cs_n                  (ddr_cs_n),
       .ddr_cke                   (ddr_cke),
       .ddr_odt                   (ddr_odt),
       .ddr_reset_n               (ddr_reset_n),
       .ddr_parity                (ddr_parity),
       .ddr_dm                    (ddr_dm),
       .dbg_calib_top             (dbg_calib_top),
       .dbg_cpt_first_edge_cnt    (dbg_cpt_first_edge_cnt),
       .dbg_cpt_second_edge_cnt   (dbg_cpt_second_edge_cnt),
       .dbg_phy_rdlvl             (dbg_phy_rdlvl),       
       .dbg_phy_wrcal             (dbg_phy_wrcal),
       .dbg_rd_data_edge_detect   (dbg_rd_data_edge_detect),
       .dbg_rddata                (dbg_rddata),
       .dbg_rdlvl_done            (dbg_rdlvl_done),
       .dbg_rdlvl_err             (dbg_rdlvl_err),
       .dbg_rdlvl_start           (dbg_rdlvl_start),
       .dbg_tap_cnt_during_wrlvl  (dbg_tap_cnt_during_wrlvl),
       .dbg_wl_edge_detect_valid  (dbg_wl_edge_detect_valid),
       .dbg_wrlvl_done            (dbg_wrlvl_done),
       .dbg_wrlvl_err             (dbg_wrlvl_err),       
       .dbg_wrlvl_start           (dbg_wrlvl_start),
       .init_calib_complete       (init_calib_complete),
       .mc_address                (mc_address),
       .mc_aux_out0               (mc_aux_out0),
       .mc_aux_out1               (mc_aux_out1),
       .mc_bank                   (mc_bank),
       .mc_cas_n                  (mc_cas_n),
       .mc_cmd                    (mc_cmd),
       .mc_cmd_wren               (mc_cmd_wren),
       .mc_cas_slot               (mc_cas_slot),
       .mc_cs_n                   (mc_cs_n),
       .mc_ctl_wren               (mc_ctl_wren),
       .mc_data_offset            (mc_data_offset),
       .mc_rank_cnt               (mc_rank_cnt),
       .mc_ras_n                  (mc_ras_n),
       .mc_reset_n                (mc_reset_n),
       .mc_we_n                   (mc_we_n),
       .mc_wrdata                 (mc_wrdata),
       .mc_wrdata_en              (mc_wrdata_en),
       .mc_wrdata_mask            (mc_wrdata_mask),
       .mem_refclk                (mem_refclk),
       .phy_mc_ctl_full           (phy_mc_ctl_full),
       .phy_mc_cmd_full           (phy_mc_cmd_full),
       .phy_mc_data_full          (phy_mc_data_full),
       .phy_rd_data               (phy_rd_data),
       .phy_rddata_valid          (phy_rddata_valid),
       .pll_lock                  (pll_lock),
       .sync_pulse                (sync_pulse),
       // Inouts
       .ddr_dqs                   (ddr_dqs),
       .ddr_dqs_n                 (ddr_dqs_n),
       .ddr_dq                    (ddr_dq),
        // Inputs
       .clk_ref                   (clk_ref),
       .freq_refclk               (freq_refclk),
       .clk                       (clk),
       .rst                       (rst),
       .slot_0_present            (slot_0_present),
       .slot_1_present            (slot_1_present),
       .dbg_idel_up_all           (dbg_idel_up_all),       
       .dbg_idel_down_all         (dbg_idel_down_all),
       .dbg_idel_up_cpt           (dbg_idel_up_cpt),
       .dbg_idel_down_cpt         (dbg_idel_down_cpt),
       .dbg_sel_idel_cpt          (dbg_sel_idel_cpt),
       .dbg_sel_all_idel_cpt      (dbg_sel_all_idel_cpt)
      );

endmodule 
