  //localparam  DRAM_TYPE = "DDR1";
  //`define DDR1
  //`define DDR2
  //`define DDR3
  //localparam  nCK_PER_CLK = 1 ;
  localparam  CWL = 1;
  localparam  nDq_pre_Dqs = DRAM_WIDTH == 16 ? 8 : DRAM_WIDTH;
  localparam  DQS_WIDTH = DQ_WIDTH/nDq_pre_Dqs;
  localparam  DM_WIDTH = DQS_WIDTH;
  localparam  CS_WIDTH = 1;
  localparam  nCS_PER_RANK = 1;
  localparam  APP_DATA_WIDTH = (ECC== "ON") ? nCK_PER_CLK*2*64 : nCK_PER_CLK*2*DQ_WIDTH;
  localparam  APP_MASK_WIDTH = APP_DATA_WIDTH/nDq_pre_Dqs;
  localparam  GWMC_PRESCALER_PERIOD  = 200000;       // maintenance period (ps)

  localparam  RANKS = 1;
  localparam  nSLOTS = 1;
  localparam  SLOT_0_CONFIG = 8'b00000001;
  localparam  SLOT_1_CONFIG = 8'b00000000;

  localparam  ADDR_WIDTH = RANK_WIDTH + BANK_WIDTH + ROW_WIDTH + COL_WIDTH;
  localparam  RAM_WIDTH  = ((nCK_PER_CLK==2) ? 2:4) * (APP_DATA_WIDTH + APP_MASK_WIDTH);



  localparam  OUT_CMD_WIDTH = RANK_WIDTH + BANK_WIDTH + ROW_WIDTH + 1 + 1 + 1;

  // BANK Contrl State Machine
  localparam  GWMCST_POWERON          = 34'b1<<0;
  localparam  GWMCST_IDLE             = 34'b1<<1;
  localparam  GWMCST_ACT_WR           = 34'b1<<2;
  localparam  GWMCST_ACT2WR           = 34'b1<<3;
  localparam  GWMCST_WRITE            = 34'b1<<4;
  localparam  GWMCST_WRITE_D0         = 34'b1<<5;
  localparam  GWMCST_WRITE_D1         = 34'b1<<6;
  localparam  GWMCST_WRITE_P          = 34'b1<<7;
  localparam  GWMCST_W2R              = 34'b1<<8;
  localparam  GWMCST_ACTED_WR         = 34'b1<<9;
  localparam  GWMCST_WP2AR            = 34'b1<<10;
  localparam  GWMCST_WP2AW            = 34'b1<<11;
  localparam  GWMCST_WP2REF           = 34'b1<<12;
  localparam  GWMCST_WP2SRE           = 34'b1<<13;
  localparam  GWMCST_ACT_RD           = 34'b1<<14;
  localparam  GWMCST_ACT2RD           = 34'b1<<15;
  localparam  GWMCST_READ             = 34'b1<<16;
  localparam  GWMCST_READ_D0          = 34'b1<<17;
  localparam  GWMCST_READ_D1          = 34'b1<<18;
  localparam  GWMCST_READ_P           = 34'b1<<19;
  localparam  GWMCST_R2W              = 34'b1<<20;
  localparam  GWMCST_ACTED_RD         = 34'b1<<21;
  localparam  GWMCST_RP2AR            = 34'b1<<22;
  localparam  GWMCST_RP2AW            = 34'b1<<23;
  localparam  GWMCST_RP2REF           = 34'b1<<24;
  localparam  GWMCST_RP2SRE           = 34'b1<<25;
  localparam  GWMCST_PD               = 34'b1<<26;
  localparam  GWMCST_REF              = 34'b1<<27;
  localparam  GWMCST_SREI             = 34'b1<<28;
  localparam  GWMCST_SRE              = 34'b1<<29;
  localparam  GWMCST_SREE             = 34'b1<<30;
  localparam  GWMCST_ZQ               = 34'b1<<31;

  //***************************************************************************
  // Convert timing parameters from time to clock cycles
  //***************************************************************************
`ifdef DDR1
  localparam  LAL                    = 0;
  localparam  LCL                    = CL == 1.5 ? 2 : 
                                       CL == 2.5 ? 3 :
                                       CL == 2   ? 2 :
                                                   3 ;
`elsif DDR2
  localparam  LAL                    = (AL == "0") ? 0 : 
                                       (AL == "1") ? 1 : 
                                       (AL == "2") ? 2 :
                                       (AL == "3") ? 3 :
                                       (AL == "4") ? 4 :
                                                     5 ;
  localparam  LCL                    = CL;
`elsif DDR3
  localparam  LAL                    = (AL == "0"   ) ? 0    : 
                                       (AL == "CL-1") ? CL-1 : 
                                                        CL-2 ;
  localparam  LCL                    = CL;
`endif

  localparam nCKE = cdiv(tCKE, tCK);
  localparam nRP  = cdiv(tRP, tCK)+1;
  localparam nRCD = cdiv(tRCD, tCK) - LAL;
  localparam nRAS = cdiv(tRAS, tCK);
  localparam nFAW = cdiv(tFAW, tCK);
  localparam nRFC = cdiv(tRFC, tCK);

  localparam nWR_CK  = cdiv(15000, tCK);
  localparam nRRD_CK = cdiv(tRRD, tCK);
  localparam nWTR_CK = cdiv(tWTR, tCK);
  localparam nRTP_CK = cdiv(tRTP, tCK);
  // Convert tWR. As per specification, write recover for autoprecharge
  // cycles doesn't support values of 9 and 11. Round up 9 to 10 and 11 to 12
  localparam nWR = (nWR_CK == 9) ? 10 : (nWR_CK == 11) ? 12 : nWR_CK;

  // tRRD, tWTR at tRTP have a 4 cycle floor in DDR3 and 2 cycle floor in DDR2
  localparam nRRD = (DRAM_TYPE == "DDR3") ? (nRRD_CK < nCK_PER_CLK*2) ? nCK_PER_CLK*2 : nRRD_CK
                                          : (nRRD_CK < nCK_PER_CLK*2) ? nCK_PER_CLK*2 : nRRD_CK;

  localparam nWTR = (DRAM_TYPE == "DDR3") ? (nWTR_CK < nCK_PER_CLK*2) ? nCK_PER_CLK*2 : nWTR_CK
                                          : (nWTR_CK < nCK_PER_CLK*2) ? nCK_PER_CLK*2 : nWTR_CK;

  localparam nRTP = (DRAM_TYPE == "DDR3") ? (nRTP_CK < nCK_PER_CLK*2) ? nCK_PER_CLK*2 : nRTP_CK
                                          : (nRTP_CK < nCK_PER_CLK*2) ? nCK_PER_CLK*2 : nRTP_CK;

  // Add a cycle to CL/CWL for the register in RDIMM devices
  localparam nCWL = (REG_CTRL == "ON") ? CWL + 1 : CWL;
  localparam nCL  = (REG_CTRL == "ON") ? LCL + 1 : LCL;
  
  localparam nWL  = (DRAM_TYPE == "DDR3") ? (nCWL + LAL      ): 
                    (DRAM_TYPE == "DDR2") ? (nCL  + LAL - 1  ):
                                             1                ;

  localparam nRL  = (DRAM_TYPE == "DDR3") ? (nCL  + LAL      ):
                    (DRAM_TYPE == "DDR2") ? (nCL  + LAL      ):
                                             nCL              ;

  // Add combination cycle
  localparam nWTP  = nWL  + nWR  + (BURST_MODE == "8" ? 4 : 2);
  localparam nCRTW = nRL  - nWL  + (BURST_MODE == "8" ? 4 : 2) + 2;
  localparam nCWTR = nWL  + nWTR + (BURST_MODE == "8" ? 4 : 2);

  localparam nCKESR = nCKE + 1;



  localparam nXSD_MCCLKS = (nCK_PER_CLK == 1) ?  tDLLK: 
                           (nCK_PER_CLK == 2) ? ((tDLLK/2) + (tDLLK%2)) : 
                                                ((tDLLK/4) + ((tDLLK%4) ? 1 : 0));

  localparam nCKESR_MCCLKS = (nCK_PER_CLK == 1) ? nCKESR : 
                             (nCK_PER_CLK == 2) ? ((nCKESR/2) + (nCKESR%2)) : 
                                                  ((nCKESR/4) + ((nCKESR%4) ? 1 : 0));


  localparam nRP_MCCLKS = (nCK_PER_CLK == 1) ? nRP : 
                          (nCK_PER_CLK == 2) ? ((nRP/2) + (nRP%2)) : 
                                               ((nRP/4) + ((nRP%4) ? 1 : 0));


  localparam nRCD_MCCLKS = nCK_PER_CLK == 1 ? nRCD :
                           nCK_PER_CLK == 2 ? nWL % 2 ? (nRCD/2)                        : (nRCD+2) / 2 :
                                              nWL % 2 ? (nRCD-2 ? (nRCD-2) / 4 + 1 : 1) : nRCD/4 + 1;


  localparam nRAS_MCCLKS = (nCK_PER_CLK == 1)  ? nRAS  : 
                           (nCK_PER_CLK == 2) ? ((nRAS/2) + (nRAS % 2)) : 
                                                ((nRAS/4) + ((nRAS%4) ? 1 : 0));

  localparam nWTP_MCCLKS = (nCK_PER_CLK == 1) ?  nWTP :
                           (nCK_PER_CLK == 2) ? (nWTP/2) + ((ADDR_CMD_MODE == "2T") ?  nWTP%2 : 1) :
                                                (nWTP/4) + ((ADDR_CMD_MODE == "2T") ? (nWTP%4 > 2 ? 2 : 1) : 2);


  localparam nRFC_MCCLKS =  (nCK_PER_CLK == 1) ? nRFC :
                            (nCK_PER_CLK == 2) ? ((nRFC/2) + (nRFC%2)) :
                                                 ((nRFC/4) + ((nRFC%4) ? 1 : 0));


  localparam nRRD_MCCLKS = (nCK_PER_CLK == 1) ?  nRRD                    :
                           (nCK_PER_CLK == 2) ?  ((nRRD/2)+(nRRD%2)) :
                                                 ((nRRD/4)+((nRRD%4) ? 1 : 0));


  localparam nRTP_MCCLKS1 = (nCK_PER_CLK == 1) ? nRTP :
                           (nCK_PER_CLK == 2) ? (nRTP/2) + ((ADDR_CMD_MODE == "2T") ? nRTP%2 : 1) :
                                                (nRTP/4) + ((ADDR_CMD_MODE == "2T") ? (nRTP%4 > 2 ? 2 : 1) : 2);

  localparam nRTP_MCCLKS = ((nRTP_MCCLKS1-1) <= 0) ? 0 : nRTP_MCCLKS1-1;


  localparam nRTW_MCCLKS = (nCK_PER_CLK == 1) ?  nCRTW                     :
                           (nCK_PER_CLK == 2) ?  ((nCRTW/2)+(nCRTW%2))     :
                                                 ((nCRTW/4)+((nCRTW%4) ? 1 : 0));

  localparam nWTR_MCCLKS = (nCK_PER_CLK == 1) ?  nCWTR                    :
                           (nCK_PER_CLK == 2) ?  ((nCWTR/2)+(nCWTR%2))     :
                                                 ((nCWTR/4)+((nCWTR%4) ? 1 : 0));



  localparam nFAW_MCCLKS = (nCK_PER_CLK == 1) ? nFAW : 
                           (nCK_PER_CLK == 2) ? ((nFAW/2) + (nFAW%2)) : 
                                                ((nFAW/4) + ((nFAW%4) ? 1 : 0));

  localparam RAS_CNT_WIDTH   = clogb2(nRAS_MCCLKS   + 1);
  localparam RCD_CNT_WIDTH   = clogb2(nRCD_MCCLKS   + 1);
  localparam RFC_CNT_WIDTH   = clogb2(nRFC_MCCLKS   + 1);
  localparam RP_CNT_WIDTH    = clogb2(nRP_MCCLKS    + 1);
  localparam RRD_CNT_WIDTH   = clogb2(nRRD_MCCLKS   + 1);
  localparam RTP_CNT_WIDTH   = clogb2(nRTP_MCCLKS   + 1);
  localparam WTP_CNT_WIDTH   = clogb2(nWTP_MCCLKS   + 1);
  localparam RTW_CNT_WIDTH   = clogb2(nRTW_MCCLKS   + 1);
  localparam WTR_CNT_WIDTH   = clogb2(nWTR_MCCLKS   + 1);
  localparam FAW_CNT_WIDTH   = clogb2(nFAW_MCCLKS   + 1);
  localparam XSD_CNT_WIDTH   = clogb2(nXSD_MCCLKS   + 1);
  localparam CKESR_CNT_WIDTH = clogb2(nCKESR_MCCLKS + 1);

  // CK clock divisor to generate maintenance prescaler period (round down)
  localparam PRESCALER_DIV = (GWMC_PRESCALER_PERIOD/(tCK*nCK_PER_CLK)) - 1;


  localparam REFRESH_TIMER_DIV = USER_REFRESH == "ON" ? 0 :
                                                       ((tREFI-(tRCD+((LCL+4)*tCK)+tRP)) / ((PRESCALER_DIV+1)*tCK*nCK_PER_CLK)) - 1;


  localparam GWMC_PRESCALER_WIDTH     = clogb2(PRESCALER_DIV);
  localparam GWMC_REFRESH_TIMER_WIDTH = clogb2(REFRESH_TIMER_DIV);

  //***************************************************************************
  // Function cdiv
  //  Description:
  //    This function performs ceiling division (divide and round-up)
  //  Inputs:
  //    num: integer to be divided
  //    div: divisor
  // Outputs:
  //    cdiv: result of ceiling division (num/div, rounded up)
  //***************************************************************************

  function integer cdiv (input integer num, input integer div);
    begin
      // perform division, then add 1 if and only if remainder is non-zero
      cdiv = (num/div) + (((num%div)>0) ? 1 : 0);
    end
  endfunction // cdiv

  function integer clogb2 (input integer size); // ceiling logb2
    begin
      size = size - 1;
      for (clogb2=1; size>1; clogb2=clogb2+1)
            size = size >> 1;
    end
  endfunction // clogb2

