OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [boards/] [xilinx/] [atlys/] [rtl/] [verilog/] [xilinx_ddr2/] [mcb_soft_calibration.v] - Blame information for rev 627

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 627 stekern
//*****************************************************************************
2
// (c) Copyright 2009 Xilinx, Inc. All rights reserved.
3
//
4
// This file contains confidential and proprietary information
5
// of Xilinx, Inc. and is protected under U.S. and
6
// international copyright and other intellectual property
7
// laws.
8
//
9
// DISCLAIMER
10
// This disclaimer is not a license and does not grant any
11
// rights to the materials distributed herewith. Except as
12
// otherwise provided in a valid license issued to you by
13
// Xilinx, and to the maximum extent permitted by applicable
14
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
15
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
16
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
17
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
18
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
19
// (2) Xilinx shall not be liable (whether in contract or tort,
20
// including negligence, or under any other theory of
21
// liability) for any loss or damage of any kind or nature
22
// related to, arising under or in connection with these
23
// materials, including for any direct, or any indirect,
24
// special, incidental, or consequential loss or damage
25
// (including loss of data, profits, goodwill, or any type of
26
// loss or damage suffered as a result of any action brought
27
// by a third party) even if such damage or loss was
28
// reasonably foreseeable or Xilinx had been advised of the
29
// possibility of the same.
30
//
31
// CRITICAL APPLICATIONS
32
// Xilinx products are not designed or intended to be fail-
33
// safe, or for use in any application requiring fail-safe
34
// performance, such as life-support or safety devices or
35
// systems, Class III medical devices, nuclear facilities,
36
// applications related to the deployment of airbags, or any
37
// other applications that could lead to death, personal
38
// injury, or severe property or environmental damage
39
// (individually and collectively, "Critical
40
// Applications"). Customer assumes the sole risk and
41
// liability of any use of Xilinx products in Critical
42
// Applications, subject only to applicable laws and
43
// regulations governing limitations on product liability.
44
//
45
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
46
// PART OF THIS FILE AT ALL TIMES.
47
//
48
//*****************************************************************************
49
//   ____  ____
50
//  /   /\/   /
51
// /___/  \  /    Vendor: Xilinx
52
// \   \   \/     Version: %version
53
//  \   \         Application: MIG
54
//  /   /         Filename: mcb_soft_calibration.v
55
// /___/   /\     Date Last Modified: $Date: 2010/10/27 17:40:12 $
56
// \   \  /  \    Date Created: Mon Feb 9 2009
57
//  \___\/\___\
58
//
59
//Device: Spartan6
60
//Design Name: DDR/DDR2/DDR3/LPDDR
61
//Purpose:  Xilinx reference design for MCB Soft
62
//           Calibration
63
//Reference:
64
//
65
//  Revision:      Date:  Comment
66
//       1.0:  2/06/09:   Initial version for MIG wrapper.
67
//       1.1:  2/09/09:   moved Max_Value_Previous assignments to be completely inside CASE statement for next-state logic (needed to get it working correctly)
68
//       1.2:  2/12/09:   Many other changes.
69
//       1.3:  2/26/09:   Removed section with Max_Value_pre and DQS_COUNT_PREVIOUS_pre, and instead added PREVIOUS_STATE reg and moved assignment to within STATE
70
//       1.4:  3/02/09:   Removed comments out of sensitivity list of always block to mux SDI, SDO, CS, and ADD.  Also added reg declaration for PREVIOUS_STATE
71
//       1.5:  3/16/09:   Added pll_lock port, and using it to gate reset.  Changing RST (except input port) to RST_reg and gating it with pll_lock.
72
//       1.6:  6/05/09:   Added START_DYN_CAL_PRE with pulse on SYSRST; removed MCB_UIDQCOUNT.
73
//       1.7:  6/24/09:   Gave RZQ and ZIO each their own unique ADD and SDI nets
74
//       2.0:  7/30/09:   Added dynamic Input Termination
75
//       2.1:  8/02/09:   Added sampling of DQS input delays to make sure we never decrement below h00 (or increment above hEF).
76
//       2.2:  8/04/09:   Added 2's compliment register "DQS_COUNT_VIRTUAL", and signficantly changed the increment/decrement algorythm - now will track a virtual
77
//                        negative DQS_COUNT value if needed.  Got rid of DQS_COUNT_UP/DOWN registers
78
//       2.3:  10/10/09:  Massive overhaul
79
//       2.4:  10/14/09:  Fixed: from START, if SKIP_IN_TERM_CAL go to WRITE_CALIBRATE
80
//       2.5:  10/15/09:  Changed OVERRIDE_DQS_CAL to CALMODE_EQ_CALIBRATION, and made it override SKIP_DYNAMIC_CAL (to 1) whenever C_MC_CALIBRATION_MODE="NOCALIBRATION"
81
//       2.6:  12/15/09:  Changed STATE from 7-bit to 6-bit.  Dropped (* FSM_ENCODING="BINARY" *) for STATE. Moved MCB_UICMDEN = 0 from OFF_RZQ_PTERM to RST_DELAY. 
82
//                        Changed the "reset" always block so that RST_reg is always set to 1 when the PLL loses lock, and is now held in reset for at least 16 clocks.  Added PNSKEW option.
83
//       2.7:  12/23/09:  Added new states "SKEW" and "MULTIPLY_DIVIDE" to help with timing.
84
//       2.8:  01/14/10:  Added functionality to allow for SUSPEND.  Changed MCB_SYSRST port from wire to reg.
85
//       2.9:  02/01/10:  More changes to SUSPEND and Reset logic to handle SUSPEND properly.  Also - eliminated 2's comp DQS_COUNT_VIRTUAL, and replaced with 8bit TARGET_DQS_DELAY which
86
//                        will track most recnet Max_Value.  Eliminated DQS_COUNT_PREVIOUS. Combined DQS_COUNT_INITIAL and DQS_Delay into DQS_DELAY_INITIAL.  Changed DQS_COUNT* to DQS_DELAY*.
87
//                        Changed MCB_SYSRST port back to wire (from reg).
88
//       3.0:  02/10/10:  Added count_inc and count_dec to add a few (4) UI_CLK cycles latency to the INC and DEC signals (to deal with latency on UOREFRSHFLAG)
89
//       3.1:  02/23/10:  Registered the DONE_SOFTANDHARD_CAL for timing.   
90
//       3.2:  02/28/10:  Corrected the   WAIT_SELFREFRESH_EXIT_DQS_CAL logic;
91
//       3.3:  03/02/10:  Changed PNSKEW to default on (1'b1)
92
//       3.4:  03/04/10:  Recoded the RST_Reg logic.
93
//       3.5:  03/05/10:  Changed Result register to be 16-bits.  Changed DQS_NUMERATOR/DENOMINATOR values to 3/8 (from 6/16)
94
//       3.6:  03/10/10:  Improvements to Reset logic    
95
//       3.7:  04/12/10:  Added DDR2 Initialization fix to meet 400 ns wait as outlined in step d) of JEDEC DDR2 spec .
96
//       3.8:  05/24/10:  Added 200us Wait logic to control CKE_Train. The 200us Wait counter assumes UI_CLK freq not higher than 100 MHz.
97
// End Revision
98
//**********************************************************************************
99
 
100
 
101
`timescale 1ps/1ps
102
 
103
module mcb_soft_calibration # (
104
  parameter       C_MEM_TZQINIT_MAXCNT  = 10'd512,  // DDR3 Minimum delay between resets
105
  parameter       C_MC_CALIBRATION_MODE = "CALIBRATION", // if set to CALIBRATION will reset DQS IDELAY to DQS_NUMERATOR/DQS_DENOMINATOR local_param values
106
                                                         // if set to NOCALIBRATION then defaults to hard cal blocks setting of C_MC_CALBRATION_DELAY (Quarter, etc)
107
  parameter       C_SIMULATION          = "FALSE",  // Tells us whether the design is being simulated or implemented
108
  parameter       SKIP_IN_TERM_CAL      = 1'b0,     // provides option to skip the input termination calibration
109
  parameter       SKIP_DYNAMIC_CAL      = 1'b0,     // provides option to skip the dynamic delay calibration
110
  parameter       SKIP_DYN_IN_TERM      = 1'b1,      // provides option to skip the input termination calibration
111
  parameter       C_MEM_TYPE = "DDR"            // provides the memory device used for the design
112
 
113
  )
114
  (
115
  input   wire            UI_CLK,                   // main clock input for logic and IODRP CLK pins.  At top level, this should also connect to IODRP2_MCB CLK pins
116
  input   wire            RST,                      // main system reset for both this Soft Calibration block - also will act as a passthrough to MCB's SYSRST
117
  (* IOB = "FALSE" *) output  reg            DONE_SOFTANDHARD_CAL,
118
                                                    // active high flag signals soft calibration of input delays is complete and MCB_UODONECAL is high (MCB hard calib complete)
119
  input   wire            PLL_LOCK,                 // Lock signal from PLL
120
  input   wire            SELFREFRESH_REQ,
121
  input   wire            SELFREFRESH_MCB_MODE,
122
  output  reg             SELFREFRESH_MCB_REQ ,
123
  output  reg             SELFREFRESH_MODE,
124
  output  wire            IODRP_ADD,                // IODRP ADD port
125
  output  wire            IODRP_SDI,                // IODRP SDI port
126
  input   wire            RZQ_IN,                   // RZQ pin from board - expected to have a 2*R resistor to ground
127
  input   wire            RZQ_IODRP_SDO,            // RZQ IODRP's SDO port
128
  output  reg             RZQ_IODRP_CS      = 1'b0, // RZQ IODRP's CS port
129
  input   wire            ZIO_IN,                   // Z-stated IO pin - garanteed not to be driven externally
130
  input   wire            ZIO_IODRP_SDO,            // ZIO IODRP's SDO port
131
  output  reg             ZIO_IODRP_CS      = 1'b0, // ZIO IODRP's CS port
132
  output  wire            MCB_UIADD,                // to MCB's UIADD port
133
  output  wire            MCB_UISDI,                // to MCB's UISDI port
134
  input   wire            MCB_UOSDO,                // from MCB's UOSDO port (User output SDO)
135
  input   wire            MCB_UODONECAL,            // indicates when MCB hard calibration process is complete
136
  input   wire            MCB_UOREFRSHFLAG,         //  high during refresh cycle and time when MCB is innactive
137
  output  wire            MCB_UICS,                 // to MCB's UICS port (User Input CS)
138
  output  reg             MCB_UIDRPUPDATE   = 1'b1, // MCB's UIDRPUPDATE port (gets passed to IODRP2_MCB's MEMUPDATE port: this controls shadow latch used during IODRP2_MCB writes).  Currently just trasnparent
139
  output  wire            MCB_UIBROADCAST,          // only to MCB's UIBROADCAST port (User Input BROADCAST - gets passed to IODRP2_MCB's BKST port)
140
  output  reg   [4:0]     MCB_UIADDR        = 5'b0, //  to MCB's UIADDR port (gets passed to IODRP2_MCB's AUXADDR port
141
  output  reg             MCB_UICMDEN       = 1'b1, //  set to 1 to take control of UI interface - removes control from internal calib block
142
  output  reg             MCB_UIDONECAL     = 1'b0, //  set to 0 to "tell" controller that it's still in a calibrate state
143
  output  reg             MCB_UIDQLOWERDEC  = 1'b0,
144
  output  reg             MCB_UIDQLOWERINC  = 1'b0,
145
  output  reg             MCB_UIDQUPPERDEC  = 1'b0,
146
  output  reg             MCB_UIDQUPPERINC  = 1'b0,
147
  output  reg             MCB_UILDQSDEC     = 1'b0,
148
  output  reg             MCB_UILDQSINC     = 1'b0,
149
  output  wire            MCB_UIREAD,               //  enables read w/o writing by turning on a SDO->SDI loopback inside the IODRP2_MCBs (doesn't exist in regular IODRP2).  IODRPCTRLR_R_WB becomes don't-care.
150
  output  reg             MCB_UIUDQSDEC     = 1'b0,
151
  output  reg             MCB_UIUDQSINC     = 1'b0,
152
  output  reg             MCB_RECAL         = 1'b0, //  future hook to drive MCB's RECAL pin - initiates a hard re-calibration sequence when high
153
  output  reg             MCB_UICMD,
154
  output  reg             MCB_UICMDIN,
155
  output  reg   [3:0]     MCB_UIDQCOUNT,
156
  input   wire  [7:0]     MCB_UODATA,
157
  input   wire            MCB_UODATAVALID,
158
  input   wire            MCB_UOCMDREADY,
159
  input   wire            MCB_UO_CAL_START,
160
 
161
  output  wire            MCB_SYSRST,               //  drives the MCB's SYSRST pin - the main reset for MCB
162
  output  reg   [7:0]     Max_Value,
163
  output  reg            CKE_Train
164
  );
165
 
166
 
167
localparam [4:0]
168
          IOI_DQ0       = {4'h0, 1'b1},
169
          IOI_DQ1       = {4'h0, 1'b0},
170
          IOI_DQ2       = {4'h1, 1'b1},
171
          IOI_DQ3       = {4'h1, 1'b0},
172
          IOI_DQ4       = {4'h2, 1'b1},
173
          IOI_DQ5       = {4'h2, 1'b0},
174
          IOI_DQ6       = {4'h3, 1'b1},
175
          IOI_DQ7       = {4'h3, 1'b0},
176
          IOI_DQ8       = {4'h4, 1'b1},
177
          IOI_DQ9       = {4'h4, 1'b0},
178
          IOI_DQ10      = {4'h5, 1'b1},
179
          IOI_DQ11      = {4'h5, 1'b0},
180
          IOI_DQ12      = {4'h6, 1'b1},
181
          IOI_DQ13      = {4'h6, 1'b0},
182
          IOI_DQ14      = {4'h7, 1'b1},
183
          IOI_DQ15      = {4'h7, 1'b0},
184
          IOI_UDM       = {4'h8, 1'b1},
185
          IOI_LDM       = {4'h8, 1'b0},
186
          IOI_CK_P      = {4'h9, 1'b1},
187
          IOI_CK_N      = {4'h9, 1'b0},
188
          IOI_RESET     = {4'hA, 1'b1},
189
          IOI_A11       = {4'hA, 1'b0},
190
          IOI_WE        = {4'hB, 1'b1},
191
          IOI_BA2       = {4'hB, 1'b0},
192
          IOI_BA0       = {4'hC, 1'b1},
193
          IOI_BA1       = {4'hC, 1'b0},
194
          IOI_RASN      = {4'hD, 1'b1},
195
          IOI_CASN      = {4'hD, 1'b0},
196
          IOI_UDQS_CLK  = {4'hE, 1'b1},
197
          IOI_UDQS_PIN  = {4'hE, 1'b0},
198
          IOI_LDQS_CLK  = {4'hF, 1'b1},
199
          IOI_LDQS_PIN  = {4'hF, 1'b0};
200
 
201
localparam  [5:0]   START                     = 6'h00,
202
                    LOAD_RZQ_NTERM            = 6'h01,
203
                    WAIT1                     = 6'h02,
204
                    LOAD_RZQ_PTERM            = 6'h03,
205
                    WAIT2                     = 6'h04,
206
                    INC_PTERM                 = 6'h05,
207
                    MULTIPLY_DIVIDE           = 6'h06,
208
                    LOAD_ZIO_PTERM            = 6'h07,
209
                    WAIT3                     = 6'h08,
210
                    LOAD_ZIO_NTERM            = 6'h09,
211
                    WAIT4                     = 6'h0A,
212
                    INC_NTERM                 = 6'h0B,
213
                    SKEW                      = 6'h0C,
214
                    WAIT_FOR_START_BROADCAST  = 6'h0D,
215
                    BROADCAST_PTERM           = 6'h0E,
216
                    WAIT5                     = 6'h0F,
217
                    BROADCAST_NTERM           = 6'h10,
218
                    WAIT6                     = 6'h11,
219
                    OFF_RZQ_PTERM             = 6'h12,
220
                    WAIT7                     = 6'h13,
221
                    OFF_ZIO_NTERM             = 6'h14,
222
                    WAIT8                     = 6'h15,
223
                    RST_DELAY                 = 6'h16,
224
                    START_DYN_CAL_PRE         = 6'h17,
225
                    WAIT_FOR_UODONE           = 6'h18,
226
                    LDQS_WRITE_POS_INDELAY    = 6'h19,
227
                    LDQS_WAIT1                = 6'h1A,
228
                    LDQS_WRITE_NEG_INDELAY    = 6'h1B,
229
                    LDQS_WAIT2                = 6'h1C,
230
                    UDQS_WRITE_POS_INDELAY    = 6'h1D,
231
                    UDQS_WAIT1                = 6'h1E,
232
                    UDQS_WRITE_NEG_INDELAY    = 6'h1F,
233
                    UDQS_WAIT2                = 6'h20,
234
                    START_DYN_CAL             = 6'h21,
235
                    WRITE_CALIBRATE           = 6'h22,
236
                    WAIT9                     = 6'h23,
237
                    READ_MAX_VALUE            = 6'h24,
238
                    WAIT10                    = 6'h25,
239
                    ANALYZE_MAX_VALUE         = 6'h26,
240
                    FIRST_DYN_CAL             = 6'h27,
241
                    INCREMENT                 = 6'h28,
242
                    DECREMENT                 = 6'h29,
243
                    DONE                      = 6'h2A;
244
 
245
localparam  [1:0]   RZQ           = 2'b00,
246
                    ZIO           = 2'b01,
247
                    MCB_PORT      = 2'b11;
248
localparam          WRITE_MODE    = 1'b0;
249
localparam          READ_MODE     = 1'b1;
250
 
251
// IOI Registers
252
localparam  [7:0]   NoOp          = 8'h00,
253
                    DelayControl  = 8'h01,
254
                    PosEdgeInDly  = 8'h02,
255
                    NegEdgeInDly  = 8'h03,
256
                    PosEdgeOutDly = 8'h04,
257
                    NegEdgeOutDly = 8'h05,
258
                    MiscCtl1      = 8'h06,
259
                    MiscCtl2      = 8'h07,
260
                    MaxValue      = 8'h08;
261
 
262
// IOB Registers
263
localparam  [7:0]   PDrive        = 8'h80,
264
                    PTerm         = 8'h81,
265
                    NDrive        = 8'h82,
266
                    NTerm         = 8'h83,
267
                    SlewRateCtl   = 8'h84,
268
                    LVDSControl   = 8'h85,
269
                    MiscControl   = 8'h86,
270
                    InputControl  = 8'h87,
271
                    TestReadback  = 8'h88;
272
 
273
// No multi/divide is required when a 55 ohm resister is used on RZQ
274
//localparam          MULT          = 1;
275
//localparam          DIV           = 1;
276
// use 7/4 scaling factor when the 100 ohm RZQ is used
277
localparam          MULT          = 7;
278
localparam          DIV           = 4;
279
 
280
localparam          PNSKEW        = 1'b1; //Default is 1'b1. Change to 1'b0 if PSKEW and NSKEW are not required
281
localparam          PSKEW_MULT    = 9;
282
localparam          PSKEW_DIV     = 8;
283
localparam          NSKEW_MULT    = 7;
284
localparam          NSKEW_DIV     = 8;
285
 
286
localparam          DQS_NUMERATOR   = 3;
287
localparam          DQS_DENOMINATOR = 8;
288
localparam          INCDEC_THRESHOLD= 8'h03; // parameter for the threshold which triggers an inc/dec to occur.  2 for half, 4 for quarter, 3 for three eighths
289
 
290
reg   [5:0]   P_Term       /* synthesis syn_preserve = 1 */;
291
reg   [6:0]   N_Term       /* synthesis syn_preserve = 1 */;
292
reg   [5:0]   P_Term_Prev  /* synthesis syn_preserve = 1 */;
293
reg   [6:0]   N_Term_Prev  /* synthesis syn_preserve = 1 */;
294
//(* FSM_ENCODING="USER" *) reg [5:0] STATE = START;   //XST does not pick up "BINARY" - use COMPACT instead if binary is desired
295
reg [5:0] STATE = START;
296
reg   [7:0]   IODRPCTRLR_MEMCELL_ADDR /* synthesis syn_preserve = 1 */;
297
reg   [7:0]   IODRPCTRLR_WRITE_DATA /* synthesis syn_preserve = 1 */;
298
reg   [1:0]   Active_IODRP /* synthesis syn_maxfan = 1 */;
299
// synthesis attribute max_fanout of Active_IODRP is 1
300
reg           IODRPCTRLR_R_WB = 1'b0;
301
reg           IODRPCTRLR_CMD_VALID = 1'b0;
302
reg           IODRPCTRLR_USE_BKST = 1'b0;
303
reg           MCB_CMD_VALID = 1'b0;
304
reg           MCB_USE_BKST = 1'b0;
305
reg           Pre_SYSRST = 1'b1 /* synthesis syn_maxfan = 5 */; //internally generated reset which will OR with RST input to drive MCB's SYSRST pin (MCB_SYSRST)
306
// synthesis attribute max_fanout of Pre_SYSRST is 5
307
reg           IODRP_SDO;
308
reg   [7:0]   Max_Value_Previous  = 8'b0 /* synthesis syn_preserve = 1 */;
309
reg   [5:0]   count = 6'd0;               //counter for adding 18 extra clock cycles after setting Calibrate bit
310
reg           counter_en  = 1'b0;         //counter enable for "count"
311
reg           First_Dyn_Cal_Done = 1'b0;  //flag - high after the very first dynamic calibration is done
312
reg           START_BROADCAST = 1'b1;     // Trigger to start Broadcast to IODRP2_MCBs to set Input Impedance - state machine will wait for this to be high
313
reg   [7:0]   DQS_DELAY_INITIAL   = 8'b0 /* synthesis syn_preserve = 1 */;
314
reg   [7:0]   DQS_DELAY ;        // contains the latest values written to LDQS and UDQS Input Delays
315
reg   [7:0]   TARGET_DQS_DELAY;  // used to track the target for DQS input delays - only gets updated if the Max Value changes by more than the threshold
316
reg   [7:0]   counter_inc;       // used to delay Inc signal by several ui_clk cycles (to deal with latency on UOREFRSHFLAG)
317
reg   [7:0]   counter_dec;       // used to delay Dec signal by several ui_clk cycles (to deal with latency on UOREFRSHFLAG)
318
 
319
wire  [7:0]   IODRPCTRLR_READ_DATA;
320
wire          IODRPCTRLR_RDY_BUSY_N;
321
wire          IODRP_CS;
322
wire  [7:0]   MCB_READ_DATA;
323
 
324
reg           RST_reg;
325
reg           Block_Reset;
326
 
327
reg           MCB_UODATAVALID_U;
328
 
329
wire  [2:0]   Inc_Dec_REFRSH_Flag;  // 3-bit flag to show:Inc is needed, Dec needed, refresh cycle taking place
330
wire  [7:0]   Max_Value_Delta_Up;   // tracks amount latest Max Value has gone up from previous Max Value read
331
wire  [7:0]   Half_MV_DU;           // half of Max_Value_Delta_Up
332
wire  [7:0]   Max_Value_Delta_Dn;   // tracks amount latest Max Value has gone down from previous Max Value read
333
wire  [7:0]   Half_MV_DD;           // half of Max_Value_Delta_Dn
334
 
335
reg   [9:0]   RstCounter = 10'h0;
336
wire          rst_tmp;
337
reg           LastPass_DynCal;
338
reg           First_In_Term_Done;
339
wire          Inc_Flag;               // flag to increment Dynamic Delay
340
wire          Dec_Flag;               // flag to decrement Dynamic Delay
341
 
342
wire          CALMODE_EQ_CALIBRATION; // will calculate and set the DQS input delays if C_MC_CALIBRATION_MODE parameter = "CALIBRATION"
343
wire  [7:0]   DQS_DELAY_LOWER_LIMIT;  // Lower limit for DQS input delays 
344
wire  [7:0]   DQS_DELAY_UPPER_LIMIT;  // Upper limit for DQS input delays
345
wire          SKIP_DYN_IN_TERMINATION;//wire to allow skipping dynamic input termination if either the one-time or dynamic parameters are 1
346
wire          SKIP_DYNAMIC_DQS_CAL;   //wire allowing skipping dynamic DQS delay calibration if either SKIP_DYNIMIC_CAL=1, or if C_MC_CALIBRATION_MODE=NOCALIBRATION
347
wire  [7:0]   Quarter_Max_Value;
348
wire  [7:0]   Half_Max_Value;
349
reg           PLL_LOCK_R1;
350
reg           PLL_LOCK_R2;
351
 
352
reg           SELFREFRESH_REQ_R1;
353
reg           SELFREFRESH_REQ_R2;
354
reg           SELFREFRESH_REQ_R3;
355
reg           SELFREFRESH_MCB_MODE_R1;
356
reg           SELFREFRESH_MCB_MODE_R2;
357
reg           SELFREFRESH_MCB_MODE_R3;
358
 
359
reg           WAIT_SELFREFRESH_EXIT_DQS_CAL;
360
reg           PERFORM_START_DYN_CAL_AFTER_SELFREFRESH;
361
reg           START_DYN_CAL_STATE_R1;
362
reg           PERFORM_START_DYN_CAL_AFTER_SELFREFRESH_R1;
363
reg           Rst_condition1, Rst_condition2;
364
wire          non_violating_rst;
365
reg [15:0]    WAIT_200us_COUNTER;
366
 
367
// 'defines for which pass of the interleaved dynamic algorythm is taking place
368
`define IN_TERM_PASS  1'b0
369
`define DYN_CAL_PASS  1'b1
370
 
371
assign  Inc_Dec_REFRSH_Flag     = {Inc_Flag,Dec_Flag,MCB_UOREFRSHFLAG};
372
assign  Max_Value_Delta_Up      = Max_Value - Max_Value_Previous;
373
assign  Half_MV_DU              = {1'b0,Max_Value_Delta_Up[7:1]};
374
assign  Max_Value_Delta_Dn      = Max_Value_Previous - Max_Value;
375
assign  Half_MV_DD              = {1'b0,Max_Value_Delta_Dn[7:1]};
376
assign  CALMODE_EQ_CALIBRATION  = (C_MC_CALIBRATION_MODE == "CALIBRATION") ? 1'b1 : 1'b0; // will calculate and set the DQS input delays if = 1'b1
377
assign  Half_Max_Value          = Max_Value >> 1;
378
assign  Quarter_Max_Value       = Max_Value >> 2;
379
assign  DQS_DELAY_LOWER_LIMIT   = Quarter_Max_Value;  // limit for DQS_DELAY for decrements; could optionally be assigned to any 8-bit hex value here
380
assign  DQS_DELAY_UPPER_LIMIT   = Half_Max_Value;     // limit for DQS_DELAY for increments; could optionally be assigned to any 8-bit hex value here
381
assign  SKIP_DYN_IN_TERMINATION = SKIP_DYN_IN_TERM || SKIP_IN_TERM_CAL; //skip dynamic input termination if either the one-time or dynamic parameters are 1
382
assign  SKIP_DYNAMIC_DQS_CAL    = ~CALMODE_EQ_CALIBRATION || SKIP_DYNAMIC_CAL; //skip dynamic DQS delay calibration if either SKIP_DYNAMIC_CAL=1, or if C_MC_CALIBRATION_MODE=NOCALIBRATION
383
 
384
always @ (posedge UI_CLK)
385
     DONE_SOFTANDHARD_CAL    <= ((DQS_DELAY_INITIAL != 8'h00) || (STATE == DONE)) && MCB_UODONECAL;  //high when either DQS input delays initialized, or STATE=DONE and UODONECAL high
386
 
387
 
388
iodrp_controller iodrp_controller(
389
  .memcell_address  (IODRPCTRLR_MEMCELL_ADDR),
390
  .write_data       (IODRPCTRLR_WRITE_DATA),
391
  .read_data        (IODRPCTRLR_READ_DATA),
392
  .rd_not_write     (IODRPCTRLR_R_WB),
393
  .cmd_valid        (IODRPCTRLR_CMD_VALID),
394
  .rdy_busy_n       (IODRPCTRLR_RDY_BUSY_N),
395
  .use_broadcast    (1'b0),
396
  .sync_rst         (RST_reg),
397
  .DRP_CLK          (UI_CLK),
398
  .DRP_CS           (IODRP_CS),
399
  .DRP_SDI          (IODRP_SDI),
400
  .DRP_ADD          (IODRP_ADD),
401
  .DRP_SDO          (IODRP_SDO),
402
  .DRP_BKST         ()
403
  );
404
 
405
iodrp_mcb_controller iodrp_mcb_controller(
406
  .memcell_address  (IODRPCTRLR_MEMCELL_ADDR),
407
  .write_data       (IODRPCTRLR_WRITE_DATA),
408
  .read_data        (MCB_READ_DATA),
409
  .rd_not_write     (IODRPCTRLR_R_WB),
410
  .cmd_valid        (MCB_CMD_VALID),
411
  .rdy_busy_n       (MCB_RDY_BUSY_N),
412
  .use_broadcast    (MCB_USE_BKST),
413
  .drp_ioi_addr     (MCB_UIADDR),
414
  .sync_rst         (RST_reg),
415
  .DRP_CLK          (UI_CLK),
416
  .DRP_CS           (MCB_UICS),
417
  .DRP_SDI          (MCB_UISDI),
418
  .DRP_ADD          (MCB_UIADD),
419
  .DRP_BKST         (MCB_UIBROADCAST),
420
  .DRP_SDO          (MCB_UOSDO),
421
  .MCB_UIREAD       (MCB_UIREAD)
422
  );
423
 
424
 
425
//******************************************************************************************
426
// Mult_Divide Function - multiplies by a constant MULT and then divides by the DIV constant
427
//******************************************************************************************
428
function [7:0] Mult_Divide;
429
input   [7:0]   Input;
430
input   [7:0]   Mult;
431
input   [7:0]   Div;
432
reg     [3:0]   count;
433
reg     [15:0]   Result;
434
begin
435
  Result  = 0;
436
  for (count = 0; count < Mult; count = count+1) begin
437
    Result    = Result + Input;
438
  end
439
  Result      = Result / Div;
440
  Mult_Divide = Result[7:0];
441
end
442
endfunction
443
 
444
 
445
generate
446
if (C_SIMULATION == "FALSE") begin: init_sequence
447
   always @ (posedge UI_CLK, posedge RST)
448
   begin
449
   if (RST)
450
       WAIT_200us_COUNTER <= 'b0;
451
   else
452
      if (WAIT_200us_COUNTER[15])  // UI_CLK maximum is up to 100 MHz.
453
           WAIT_200us_COUNTER <= WAIT_200us_COUNTER                        ;
454
      else
455
           WAIT_200us_COUNTER <= WAIT_200us_COUNTER + 1'b1;
456
   end
457
end
458
else begin: init_sequence_skip
459
// synthesis translate_off        
460
   initial
461
   begin
462
      WAIT_200us_COUNTER = 16'hFFFF;
463
      $display("The 200 us wait period required before CKE goes active has been skipped in Simulation\n");
464
   end
465
// synthesis translate_on         
466
end
467
endgenerate
468
 
469
 
470
generate
471
if( C_MEM_TYPE == "DDR2") begin : gen_cketrain_a
472
 
473
 
474
always @ ( posedge UI_CLK, posedge RST)
475
begin
476
if (RST)
477
   CKE_Train <= 1'b0;
478
else
479
  if (STATE == WAIT_FOR_UODONE && MCB_UODONECAL)
480
   CKE_Train <= 1'b0;
481
  else if (WAIT_200us_COUNTER[15] && ~MCB_UODONECAL)
482
   CKE_Train <= 1'b1;
483
 
484
end
485
end
486
endgenerate
487
 
488
 
489
generate
490
if( C_MEM_TYPE != "DDR2") begin : gen_cketrain_b
491
always @ ( posedge UI_CLK)
492
   CKE_Train <= 1'b0;
493
end
494
endgenerate
495
 
496
//********************************************
497
//PLL_LOCK and Reset signals
498
//********************************************
499
localparam  RST_CNT         = 10'h010;          //defines pulse-width for reset
500
localparam  TZQINIT_MAXCNT  = C_MEM_TZQINIT_MAXCNT + RST_CNT;
501
assign MCB_SYSRST = Pre_SYSRST | RST_reg ;            //Pre_SYSRST is generated from the STATE state machine, and is OR'd with RST_reg input to drive MCB's SYSRST pin (MCB_SYSRST)
502
assign rst_tmp    = (~PLL_LOCK_R2 && ~SELFREFRESH_MODE); //rst_tmp becomes 1 if you lose PLL lock (registered twice for metastblty) and the device is not in SUSPEND
503
assign non_violating_rst = RST && Rst_condition1;         //non_violating_rst is when the user-reset RST occurs and TZQINIT (min time between resets for DDR3) is not being violated
504
 
505
 
506
 
507
 
508
always @ (posedge UI_CLK or posedge RST ) begin
509
  if (RST) begin
510
    Block_Reset <= 1'b0;
511
    RstCounter  <= 10'b0;
512
end
513
  else if (rst_tmp) begin    //this is to deal with not allowing the user-reset "RST" to violate TZQINIT_MAXCNT (min time between resets to DDR3)
514
    Block_Reset <= 1'b0;
515
    RstCounter  <= 10'b0;
516
  end
517
  else begin
518
    Block_Reset <= 1'b0;                   //default to allow STATE to move out of RST_DELAY state
519
    if (Pre_SYSRST)
520
      RstCounter  <= RST_CNT;              //whenever STATE wants to reset the MCB, set RstCounter to h10
521
    else begin
522
      if (RstCounter < TZQINIT_MAXCNT) begin //if RstCounter is less than d512 than this will execute
523
        Block_Reset <= 1'b1;               //STATE won't exit RST_DELAY state
524
        RstCounter  <= RstCounter + 1'b1;  //and Rst_Counter increments
525
      end
526
    end
527
  end
528
end
529
 
530
 
531
 
532
always @ (posedge UI_CLK ) begin
533
if (RstCounter >= TZQINIT_MAXCNT)
534
    Rst_condition1 <= 1'b1;
535
else
536
    Rst_condition1 <= 1'b0;
537
 
538
end
539
 
540
always @ (posedge UI_CLK ) begin
541
if (RstCounter < RST_CNT)
542
    Rst_condition2 <= 1'b1;
543
  else
544
    Rst_condition2 <= 1'b0;
545
 
546
end
547
always @ (posedge UI_CLK or posedge non_violating_rst ) begin
548
  if (non_violating_rst)
549
    RST_reg <= 1'b1;
550
  else if (~WAIT_200us_COUNTER[15])
551
    RST_reg <= 1'b1;
552
  else
553
    RST_reg     <= Rst_condition2 | rst_tmp ;
554
 
555
end
556
 
557
 
558
//********************************************
559
// SUSPEND Logic
560
//********************************************
561
 
562
always @ ( posedge UI_CLK) begin
563
  //SELFREFRESH_MCB_MODE is clocked by sysclk_2x_180
564
  SELFREFRESH_MCB_MODE_R1 <= SELFREFRESH_MCB_MODE;
565
  SELFREFRESH_MCB_MODE_R2 <= SELFREFRESH_MCB_MODE_R1;
566
  SELFREFRESH_MCB_MODE_R3 <= SELFREFRESH_MCB_MODE_R2;
567
 
568
  //SELFREFRESH_REQ is clocked by user's application clock
569
  SELFREFRESH_REQ_R1      <= SELFREFRESH_REQ;
570
  SELFREFRESH_REQ_R2      <= SELFREFRESH_REQ_R1;
571
  SELFREFRESH_REQ_R3      <= SELFREFRESH_REQ_R2;
572
 
573
  PLL_LOCK_R1             <= PLL_LOCK;
574
  PLL_LOCK_R2             <= PLL_LOCK_R1;
575
 
576
 
577
end
578
 
579
// SELFREFRESH should only be deasserted after PLL_LOCK is asserted.
580
// This is to make sure MCB get a locked sys_2x_clk before exiting
581
// SELFREFRESH mode.
582
 
583
always @ ( posedge UI_CLK) begin
584
  if (RST)
585
    SELFREFRESH_MCB_REQ <= 1'b0;
586
  else if (PLL_LOCK_R2 && ~SELFREFRESH_REQ_R1 && STATE == START_DYN_CAL)
587
    SELFREFRESH_MCB_REQ <=  1'b0;
588
  else if (STATE == START_DYN_CAL && SELFREFRESH_REQ_R1)
589
    SELFREFRESH_MCB_REQ <= 1'b1;
590
end
591
 
592
 
593
 
594
always @ (posedge UI_CLK) begin
595
  if (RST)
596
    WAIT_SELFREFRESH_EXIT_DQS_CAL <= 1'b0;
597
  else if (~SELFREFRESH_MCB_MODE_R3 && SELFREFRESH_MCB_MODE_R2)
598
 
599
    WAIT_SELFREFRESH_EXIT_DQS_CAL <= 1'b1;
600
  else if (WAIT_SELFREFRESH_EXIT_DQS_CAL && ~SELFREFRESH_REQ_R3 && PERFORM_START_DYN_CAL_AFTER_SELFREFRESH) // START_DYN_CAL is next state
601
    WAIT_SELFREFRESH_EXIT_DQS_CAL <= 1'b0;
602
end
603
 
604
//Need to detect when SM entering START_DYN_CAL
605
always @ (posedge UI_CLK) begin
606
  if (RST) begin
607
    PERFORM_START_DYN_CAL_AFTER_SELFREFRESH  <= 1'b0;
608
    START_DYN_CAL_STATE_R1 <= 1'b0;
609
  end
610
  else begin
611
    // register PERFORM_START_DYN_CAL_AFTER_SELFREFRESH to detect end of cycle
612
    PERFORM_START_DYN_CAL_AFTER_SELFREFRESH_R1 <= PERFORM_START_DYN_CAL_AFTER_SELFREFRESH;
613
    if (STATE == START_DYN_CAL)
614
      START_DYN_CAL_STATE_R1 <= 1'b1;
615
    else
616
      START_DYN_CAL_STATE_R1 <= 1'b0;
617
      if (WAIT_SELFREFRESH_EXIT_DQS_CAL && STATE != START_DYN_CAL && START_DYN_CAL_STATE_R1 )
618
        PERFORM_START_DYN_CAL_AFTER_SELFREFRESH <= 1'b1;
619
      else if (STATE == START_DYN_CAL && ~SELFREFRESH_MCB_MODE_R3)
620
        PERFORM_START_DYN_CAL_AFTER_SELFREFRESH <= 1'b0;
621
      end
622
  end
623
 
624
 
625
// SELFREFRESH_MCB_MODE deasserted status is hold off
626
// until Soft_Calib has at least done one loop of DQS update.
627
always @ (posedge UI_CLK) begin
628
  if (RST)
629
    SELFREFRESH_MODE <= 1'b0;
630
  else if (SELFREFRESH_MCB_MODE_R2)
631
    SELFREFRESH_MODE <= 1'b1;
632
  else if (!PERFORM_START_DYN_CAL_AFTER_SELFREFRESH && PERFORM_START_DYN_CAL_AFTER_SELFREFRESH_R1)
633
    SELFREFRESH_MODE <= 1'b0;
634
end
635
 
636
//********************************************
637
//Comparitors for Dynamic Calibration circuit
638
//********************************************
639
assign Dec_Flag = (TARGET_DQS_DELAY < DQS_DELAY);
640
assign Inc_Flag = (TARGET_DQS_DELAY > DQS_DELAY);
641
 
642
 
643
//*********************************************************************************************
644
//Counter for extra clock cycles injected after setting Calibrate bit in IODRP2 for Dynamic Cal
645
//*********************************************************************************************
646
 always @(posedge UI_CLK)
647
  begin
648
    if (RST_reg)
649
        count <= 6'd0;
650
    else if (counter_en)
651
        count <= count + 1'b1;
652
    else
653
        count <= 6'd0;
654
  end
655
 
656
//*********************************************************************************************
657
// Capture narrow MCB_UODATAVALID pulse - only one sysclk90 cycle wide
658
//*********************************************************************************************
659
 always @(posedge UI_CLK or posedge MCB_UODATAVALID)
660
  begin
661
    if (MCB_UODATAVALID)
662
        MCB_UODATAVALID_U <= 1'b1;
663
    else
664
        MCB_UODATAVALID_U <= MCB_UODATAVALID;
665
  end
666
 
667
  //**************************************************************************************************************
668
  //Always block to mux SDI, SDO, CS, and ADD depending on which IODRP is active: RZQ, ZIO or MCB's UI port (to IODRP2_MCBs)
669
  //**************************************************************************************************************
670
  always @(*) begin: ACTIVE_IODRP
671
    case (Active_IODRP)
672
      RZQ:      begin
673
        RZQ_IODRP_CS  = IODRP_CS;
674
        ZIO_IODRP_CS  = 1'b0;
675
        IODRP_SDO     = RZQ_IODRP_SDO;
676
      end
677
      ZIO:      begin
678
        RZQ_IODRP_CS  = 1'b0;
679
        ZIO_IODRP_CS  = IODRP_CS;
680
        IODRP_SDO     = ZIO_IODRP_SDO;
681
      end
682
      MCB_PORT: begin
683
        RZQ_IODRP_CS  = 1'b0;
684
        ZIO_IODRP_CS  = 1'b0;
685
        IODRP_SDO     = 1'b0;
686
      end
687
      default:  begin
688
        RZQ_IODRP_CS  = 1'b0;
689
        ZIO_IODRP_CS  = 1'b0;
690
        IODRP_SDO     = 1'b0;
691
      end
692
    endcase
693
  end
694
 
695
//******************************************************************
696
//State Machine's Always block / Case statement for Next State Logic
697
//
698
//The WAIT1,2,etc states were required after every state where the
699
//DRP controller was used to do a write to the IODRPs - this is because
700
//there's a clock cycle latency on IODRPCTRLR_RDY_BUSY_N whenever the DRP controller
701
//sees IODRPCTRLR_CMD_VALID go high.  OFF_RZQ_PTERM and OFF_ZIO_NTERM were added
702
//soley for the purpose of reducing power, particularly on RZQ as
703
//that pin is expected to have a permanent external resistor to gnd.
704
//******************************************************************
705
  always @(posedge UI_CLK) begin: NEXT_STATE_LOGIC
706
    if (RST_reg) begin                      // Synchronous reset
707
      MCB_CMD_VALID           <= 1'b0;
708
      MCB_UIADDR              <= 5'b0;
709
      MCB_UICMDEN             <= 1'b1;      // take control of UI/UO port
710
      MCB_UIDONECAL           <= 1'b0;      // tells MCB that it is in Soft Cal.
711
      MCB_USE_BKST            <= 1'b0;
712
      MCB_UIDRPUPDATE         <= 1'b1;
713
      Pre_SYSRST              <= 1'b1;      // keeps MCB in reset
714
      IODRPCTRLR_CMD_VALID    <= 1'b0;
715
      IODRPCTRLR_MEMCELL_ADDR <= NoOp;
716
      IODRPCTRLR_WRITE_DATA   <= 1'b0;
717
      IODRPCTRLR_R_WB         <= WRITE_MODE;
718
      IODRPCTRLR_USE_BKST     <= 1'b0;
719
      P_Term                  <= 6'b0;
720
      N_Term                  <= 7'b0;
721
      P_Term_Prev             <= 6'b0;
722
      N_Term_Prev             <= 7'b0;
723
      Active_IODRP            <= RZQ;
724
      MCB_UILDQSINC           <= 1'b0;      //no inc or dec
725
      MCB_UIUDQSINC           <= 1'b0;      //no inc or dec
726
      MCB_UILDQSDEC           <= 1'b0;      //no inc or dec
727
      MCB_UIUDQSDEC           <= 1'b0;      //no inc or dec
728
      counter_en              <= 1'b0;
729
      First_Dyn_Cal_Done      <= 1'b0;      //flag that the First Dynamic Calibration completed
730
      Max_Value               <= 8'b0;
731
      Max_Value_Previous      <= 8'b0;
732
      STATE                   <= START;
733
      DQS_DELAY               <= 8'h0; //tracks the cumulative incrementing/decrementing that has been done
734
      DQS_DELAY_INITIAL       <= 8'h0;
735
      TARGET_DQS_DELAY        <= 8'h0;
736
      LastPass_DynCal         <= `IN_TERM_PASS;
737
      First_In_Term_Done      <= 1'b0;
738
      MCB_UICMD               <= 1'b0;
739
      MCB_UICMDIN             <= 1'b0;
740
      MCB_UIDQCOUNT           <= 4'h0;
741
      counter_inc             <= 8'h0;
742
      counter_dec             <= 8'h0;
743
    end
744
    else begin
745
      counter_en              <= 1'b0;
746
      IODRPCTRLR_CMD_VALID    <= 1'b0;
747
      IODRPCTRLR_MEMCELL_ADDR <= NoOp;
748
      IODRPCTRLR_R_WB         <= READ_MODE;
749
      IODRPCTRLR_USE_BKST     <= 1'b0;
750
      MCB_CMD_VALID           <= 1'b0;
751
      MCB_UILDQSINC           <= 1'b0;            //no inc or dec
752
      MCB_UIUDQSINC           <= 1'b0;            //no inc or dec
753
      MCB_UILDQSDEC           <= 1'b0;            //no inc or dec
754
      MCB_UIUDQSDEC           <= 1'b0;            //no inc or dec
755
      MCB_USE_BKST            <= 1'b0;
756
      MCB_UICMDIN             <= 1'b0;
757
      DQS_DELAY               <= DQS_DELAY;
758
      TARGET_DQS_DELAY        <= TARGET_DQS_DELAY;
759
      case (STATE)
760
        START:  begin   //h00
761
          MCB_UICMDEN     <= 1'b1;        // take control of UI/UO port
762
          MCB_UIDONECAL   <= 1'b0;        // tells MCB that it is in Soft Cal.
763
          P_Term          <= 6'b0;
764
          N_Term          <= 7'b0;
765
          Pre_SYSRST      <= 1'b1;        // keeps MCB in reset
766
          LastPass_DynCal <= `IN_TERM_PASS;
767
          if (SKIP_IN_TERM_CAL)
768
            STATE <= WRITE_CALIBRATE;
769
          else if (IODRPCTRLR_RDY_BUSY_N)
770
            STATE  <= LOAD_RZQ_NTERM;
771
          else
772
            STATE  <= START;
773
        end
774
//***************************
775
// IOB INPUT TERMINATION CAL
776
//***************************
777
        LOAD_RZQ_NTERM: begin   //h01
778
          Active_IODRP            <= RZQ;
779
          IODRPCTRLR_CMD_VALID    <= 1'b1;
780
          IODRPCTRLR_MEMCELL_ADDR <= NTerm;
781
          IODRPCTRLR_WRITE_DATA   <= {1'b0,N_Term};
782
          IODRPCTRLR_R_WB         <= WRITE_MODE;
783
          if (IODRPCTRLR_RDY_BUSY_N)
784
            STATE <= LOAD_RZQ_NTERM;
785
          else
786
            STATE <= WAIT1;
787
        end
788
        WAIT1:  begin   //h02
789
          if (!IODRPCTRLR_RDY_BUSY_N)
790
            STATE <= WAIT1;
791
          else
792
            STATE <= LOAD_RZQ_PTERM;
793
        end
794
        LOAD_RZQ_PTERM: begin //h03
795
          IODRPCTRLR_CMD_VALID    <= 1'b1;
796
          IODRPCTRLR_MEMCELL_ADDR <= PTerm;
797
          IODRPCTRLR_WRITE_DATA   <= {2'b00,P_Term};
798
          IODRPCTRLR_R_WB         <= WRITE_MODE;
799
          if (IODRPCTRLR_RDY_BUSY_N)
800
            STATE <= LOAD_RZQ_PTERM;
801
          else
802
            STATE <= WAIT2;
803
        end
804
        WAIT2:  begin   //h04
805
          if (!IODRPCTRLR_RDY_BUSY_N)
806
            STATE <= WAIT2;
807
          else if ((RZQ_IN)||(P_Term == 6'b111111)) begin
808
            STATE <= MULTIPLY_DIVIDE;//LOAD_ZIO_PTERM;
809
          end
810
          else
811
            STATE <= INC_PTERM;
812
        end
813
        INC_PTERM: begin    //h05
814
          P_Term  <= P_Term + 1;
815
          STATE   <= LOAD_RZQ_PTERM;
816
        end
817
        MULTIPLY_DIVIDE: begin //06
818
           P_Term  <= Mult_Divide(P_Term, MULT, DIV);
819
           STATE <= LOAD_ZIO_PTERM;
820
        end
821
        LOAD_ZIO_PTERM: begin   //h07
822
          Active_IODRP            <= ZIO;
823
          IODRPCTRLR_CMD_VALID    <= 1'b1;
824
          IODRPCTRLR_MEMCELL_ADDR <= PTerm;
825
          IODRPCTRLR_WRITE_DATA   <= {2'b00,P_Term};
826
          IODRPCTRLR_R_WB         <= WRITE_MODE;
827
          if (IODRPCTRLR_RDY_BUSY_N)
828
            STATE <= LOAD_ZIO_PTERM;
829
          else
830
            STATE <= WAIT3;
831
        end
832
        WAIT3:  begin   //h08
833
          if (!IODRPCTRLR_RDY_BUSY_N)
834
            STATE <= WAIT3;
835
          else begin
836
            STATE   <= LOAD_ZIO_NTERM;
837
          end
838
        end
839
        LOAD_ZIO_NTERM: begin   //h09
840
          Active_IODRP            <= ZIO;
841
          IODRPCTRLR_CMD_VALID    <= 1'b1;
842
          IODRPCTRLR_MEMCELL_ADDR <= NTerm;
843
          IODRPCTRLR_WRITE_DATA   <= {1'b0,N_Term};
844
          IODRPCTRLR_R_WB         <= WRITE_MODE;
845
          if (IODRPCTRLR_RDY_BUSY_N)
846
            STATE <= LOAD_ZIO_NTERM;
847
          else
848
            STATE <= WAIT4;
849
        end
850
        WAIT4:  begin   //h0A
851
          if (!IODRPCTRLR_RDY_BUSY_N)
852
            STATE <= WAIT4;
853
          else if ((!ZIO_IN)||(N_Term == 7'b1111111)) begin
854
            if (PNSKEW) begin
855
              STATE    <= SKEW;
856
            end
857
            else
858
            STATE <= WAIT_FOR_START_BROADCAST;
859
          end
860
          else
861
            STATE <= INC_NTERM;
862
        end
863
        INC_NTERM: begin    //h0B
864
          N_Term  <= N_Term + 1;
865
          STATE   <= LOAD_ZIO_NTERM;
866
        end
867
        SKEW : begin //0C
868
            P_Term <= Mult_Divide(P_Term, PSKEW_MULT, PSKEW_DIV);
869
            N_Term <= Mult_Divide(N_Term, NSKEW_MULT, NSKEW_DIV);
870
            STATE  <= WAIT_FOR_START_BROADCAST;
871
        end
872
        WAIT_FOR_START_BROADCAST: begin   //h0D
873
          Pre_SYSRST    <= 1'b0;      //release SYSRST, but keep UICMDEN=1 and UIDONECAL=0. This is needed to do Broadcast through UI interface, while keeping the MCB in calibration mode
874
          Active_IODRP  <= MCB_PORT;
875
          if (START_BROADCAST && IODRPCTRLR_RDY_BUSY_N) begin
876
            if (P_Term != P_Term_Prev) begin
877
              STATE       <= BROADCAST_PTERM;
878
              P_Term_Prev <= P_Term;
879
            end
880
            else if (N_Term != N_Term_Prev) begin
881
              N_Term_Prev <= N_Term;
882
              STATE       <= BROADCAST_NTERM;
883
            end
884
            else
885
              STATE <= OFF_RZQ_PTERM;
886
          end
887
          else
888
            STATE   <= WAIT_FOR_START_BROADCAST;
889
        end
890
        BROADCAST_PTERM:  begin    //h0E
891
//SBS redundant?          MCB_UICMDEN             <= 1'b1;        // take control of UI/UO port for reentrant use of dynamic In Term tuning
892
          IODRPCTRLR_MEMCELL_ADDR <= PTerm;
893
          IODRPCTRLR_WRITE_DATA   <= {2'b00,P_Term};
894
          IODRPCTRLR_R_WB         <= WRITE_MODE;
895
          MCB_CMD_VALID           <= 1'b1;
896
          MCB_UIDRPUPDATE         <= ~First_In_Term_Done; // Set the update flag if this is the first time through
897
          MCB_USE_BKST            <= 1'b1;
898
          if (MCB_RDY_BUSY_N)
899
            STATE <= BROADCAST_PTERM;
900
          else
901
            STATE <= WAIT5;
902
        end
903
        WAIT5:  begin   //h0F
904
          if (!MCB_RDY_BUSY_N)
905
            STATE <= WAIT5;
906
          else if (First_In_Term_Done) begin  // If first time through is already set, then this must be dynamic in term
907
            if (MCB_UOREFRSHFLAG) begin
908
              MCB_UIDRPUPDATE <= 1'b1;
909
              if (N_Term != N_Term_Prev) begin
910
                N_Term_Prev <= N_Term;
911
                STATE       <= BROADCAST_NTERM;
912
              end
913
              else
914
                STATE <= OFF_RZQ_PTERM;
915
            end
916
            else
917
              STATE <= WAIT5;   // wait for a Refresh cycle
918
          end
919
          else begin
920
            N_Term_Prev <= N_Term;
921
            STATE <= BROADCAST_NTERM;
922
          end
923
        end
924
        BROADCAST_NTERM:  begin    //h10
925
          IODRPCTRLR_MEMCELL_ADDR <= NTerm;
926
          IODRPCTRLR_WRITE_DATA   <= {2'b00,N_Term};
927
          IODRPCTRLR_R_WB         <= WRITE_MODE;
928
          MCB_CMD_VALID           <= 1'b1;
929
          MCB_USE_BKST            <= 1'b1;
930
          MCB_UIDRPUPDATE         <= ~First_In_Term_Done; // Set the update flag if this is the first time through
931
          if (MCB_RDY_BUSY_N)
932
            STATE <= BROADCAST_NTERM;
933
          else
934
            STATE <= WAIT6;
935
        end
936
        WAIT6:  begin             // 7'h11
937
          if (!MCB_RDY_BUSY_N)
938
            STATE <= WAIT6;
939
          else if (First_In_Term_Done) begin  // If first time through is already set, then this must be dynamic in term
940
            if (MCB_UOREFRSHFLAG) begin
941
              MCB_UIDRPUPDATE <= 1'b1;
942
              STATE           <= OFF_RZQ_PTERM;
943
            end
944
            else
945
              STATE <= WAIT6;   // wait for a Refresh cycle
946
          end
947
          else
948
            STATE <= OFF_RZQ_PTERM;
949
        end
950
        OFF_RZQ_PTERM:  begin     // 7'h12
951
          Active_IODRP            <= RZQ;
952
          IODRPCTRLR_CMD_VALID    <= 1'b1;
953
          IODRPCTRLR_MEMCELL_ADDR <= PTerm;
954
          IODRPCTRLR_WRITE_DATA   <= 8'b00;
955
          IODRPCTRLR_R_WB         <= WRITE_MODE;
956
          P_Term                  <= 6'b0;
957
          N_Term                  <= 5'b0;
958
          MCB_UIDRPUPDATE         <= ~First_In_Term_Done; // Set the update flag if this is the first time through
959
          if (IODRPCTRLR_RDY_BUSY_N)
960
            STATE <= OFF_RZQ_PTERM;
961
          else
962
            STATE <= WAIT7;
963
        end
964
        WAIT7:  begin             // 7'h13
965
          if (!IODRPCTRLR_RDY_BUSY_N)
966
            STATE <= WAIT7;
967
          else
968
            STATE <= OFF_ZIO_NTERM;
969
        end
970
        OFF_ZIO_NTERM:  begin     // 7'h14
971
          Active_IODRP            <= ZIO;
972
          IODRPCTRLR_CMD_VALID    <= 1'b1;
973
          IODRPCTRLR_MEMCELL_ADDR <= NTerm;
974
          IODRPCTRLR_WRITE_DATA   <= 8'b00;
975
          IODRPCTRLR_R_WB         <= WRITE_MODE;
976
          if (IODRPCTRLR_RDY_BUSY_N)
977
            STATE <= OFF_ZIO_NTERM;
978
          else
979
            STATE <= WAIT8;
980
        end
981
        WAIT8:  begin             // 7'h15
982
          if (!IODRPCTRLR_RDY_BUSY_N)
983
            STATE <= WAIT8;
984
          else begin
985
            if (First_In_Term_Done) begin
986
              STATE               <= START_DYN_CAL; // No need to reset the MCB if we are in InTerm tuning
987
            end
988
            else begin
989
              STATE               <= WRITE_CALIBRATE; // go read the first Max_Value from RZQ
990
            end
991
          end
992
        end
993
        RST_DELAY:  begin     // 7'h16
994
          MCB_UICMDEN             <= 1'b0;  // release control of UI/UO port
995
          if (Block_Reset) begin  // this ensures that more than 512 clock cycles occur since the last reset after MCB_WRITE_CALIBRATE ???
996
            STATE       <= RST_DELAY;
997
          end
998
          else begin
999
            STATE <= START_DYN_CAL_PRE;
1000
          end
1001
        end
1002
//****************************
1003
// DYNAMIC CALIBRATION PORTION
1004
//****************************
1005
        START_DYN_CAL_PRE:  begin   // 7'h17
1006
          LastPass_DynCal <= `IN_TERM_PASS;
1007
          MCB_UICMDEN     <= 1'b0;    // release UICMDEN
1008
          MCB_UIDONECAL   <= 1'b1;    // release UIDONECAL - MCB will now initialize.
1009
          Pre_SYSRST      <= 1'b1;    // SYSRST pulse
1010
          if (~CALMODE_EQ_CALIBRATION)      // if C_MC_CALIBRATION_MODE is set to NOCALIBRATION
1011
            STATE       <= START_DYN_CAL;  // we'll skip setting the DQS delays manually
1012
          else
1013
            STATE       <= WAIT_FOR_UODONE;
1014
          end
1015
        WAIT_FOR_UODONE:  begin  //7'h18
1016
          Pre_SYSRST      <= 1'b0;    // SYSRST pulse
1017
          if (IODRPCTRLR_RDY_BUSY_N && MCB_UODONECAL) begin //IODRP Controller needs to be ready, & MCB needs to be done with hard calibration
1018
            MCB_UICMDEN <= 1'b1;    // grab UICMDEN
1019
            DQS_DELAY_INITIAL <= Mult_Divide(Max_Value, DQS_NUMERATOR, DQS_DENOMINATOR);
1020
            STATE       <= LDQS_WRITE_POS_INDELAY;
1021
          end
1022
          else
1023
            STATE       <= WAIT_FOR_UODONE;
1024
        end
1025
        LDQS_WRITE_POS_INDELAY:  begin// 7'h19
1026
          IODRPCTRLR_MEMCELL_ADDR <= PosEdgeInDly;
1027
          IODRPCTRLR_R_WB         <= WRITE_MODE;
1028
          IODRPCTRLR_WRITE_DATA   <= DQS_DELAY_INITIAL;
1029
          MCB_UIADDR              <= IOI_LDQS_CLK;
1030
          MCB_CMD_VALID           <= 1'b1;
1031
          if (MCB_RDY_BUSY_N)
1032
            STATE <= LDQS_WRITE_POS_INDELAY;
1033
          else
1034
            STATE <= LDQS_WAIT1;
1035
        end
1036
        LDQS_WAIT1:  begin           // 7'h1A
1037
          if (!MCB_RDY_BUSY_N)
1038
            STATE <= LDQS_WAIT1;
1039
          else begin
1040
            STATE           <= LDQS_WRITE_NEG_INDELAY;
1041
          end
1042
        end
1043
        LDQS_WRITE_NEG_INDELAY:  begin// 7'h1B
1044
          IODRPCTRLR_MEMCELL_ADDR <= NegEdgeInDly;
1045
          IODRPCTRLR_R_WB         <= WRITE_MODE;
1046
          IODRPCTRLR_WRITE_DATA   <= DQS_DELAY_INITIAL;
1047
          MCB_UIADDR              <= IOI_LDQS_CLK;
1048
          MCB_CMD_VALID           <= 1'b1;
1049
          if (MCB_RDY_BUSY_N)
1050
            STATE <= LDQS_WRITE_NEG_INDELAY;
1051
          else
1052
            STATE <= LDQS_WAIT2;
1053
        end
1054
        LDQS_WAIT2:  begin           // 7'h1C
1055
          if (!MCB_RDY_BUSY_N)
1056
            STATE <= LDQS_WAIT2;
1057
          else begin
1058
            STATE <= UDQS_WRITE_POS_INDELAY;
1059
          end
1060
        end
1061
        UDQS_WRITE_POS_INDELAY:  begin// 7'h1D
1062
          IODRPCTRLR_MEMCELL_ADDR <= PosEdgeInDly;
1063
          IODRPCTRLR_R_WB         <= WRITE_MODE;
1064
          IODRPCTRLR_WRITE_DATA   <= DQS_DELAY_INITIAL;
1065
          MCB_UIADDR              <= IOI_UDQS_CLK;
1066
          MCB_CMD_VALID           <= 1'b1;
1067
          if (MCB_RDY_BUSY_N)
1068
            STATE <= UDQS_WRITE_POS_INDELAY;
1069
          else
1070
            STATE <= UDQS_WAIT1;
1071
        end
1072
        UDQS_WAIT1:  begin           // 7'h1E
1073
          if (!MCB_RDY_BUSY_N)
1074
            STATE <= UDQS_WAIT1;
1075
          else begin
1076
            STATE           <= UDQS_WRITE_NEG_INDELAY;
1077
          end
1078
        end
1079
        UDQS_WRITE_NEG_INDELAY:  begin// 7'h1F
1080
          IODRPCTRLR_MEMCELL_ADDR <= NegEdgeInDly;
1081
          IODRPCTRLR_R_WB         <= WRITE_MODE;
1082
          IODRPCTRLR_WRITE_DATA   <= DQS_DELAY_INITIAL;
1083
          MCB_UIADDR              <= IOI_UDQS_CLK;
1084
          MCB_CMD_VALID           <= 1'b1;
1085
          if (MCB_RDY_BUSY_N)
1086
            STATE <= UDQS_WRITE_NEG_INDELAY;
1087
          else
1088
            STATE <= UDQS_WAIT2;
1089
        end
1090
        UDQS_WAIT2:  begin           // 7'h20
1091
          if (!MCB_RDY_BUSY_N)
1092
            STATE <= UDQS_WAIT2;
1093
          else begin
1094
            DQS_DELAY         <= DQS_DELAY_INITIAL;
1095
            TARGET_DQS_DELAY  <= DQS_DELAY_INITIAL;
1096
            STATE             <= START_DYN_CAL;
1097
          end
1098
        end
1099
//**************************************************************************************
1100
        START_DYN_CAL:  begin       // 7'h21
1101
          Pre_SYSRST        <= 1'b0;      // SYSRST not driven
1102
          counter_inc       <= 8'b0;
1103
          counter_dec       <= 8'b0;
1104
          if (SKIP_DYNAMIC_DQS_CAL & SKIP_DYN_IN_TERMINATION)
1105
            STATE <= DONE;  //if we're skipping both dynamic algorythms, go directly to DONE
1106
          else
1107
          if (IODRPCTRLR_RDY_BUSY_N && MCB_UODONECAL && ~SELFREFRESH_REQ_R1 ) begin  //IODRP Controller needs to be ready, & MCB needs to be done with hard calibration
1108
 
1109
            // Alternate between Dynamic Input Termination and Dynamic Tuning routines
1110
            if (~SKIP_DYN_IN_TERMINATION & (LastPass_DynCal == `DYN_CAL_PASS)) begin
1111
              LastPass_DynCal <= `IN_TERM_PASS;
1112
              STATE           <= LOAD_RZQ_NTERM;
1113
            end
1114
            else begin
1115
              LastPass_DynCal <= `DYN_CAL_PASS;
1116
              STATE           <= WRITE_CALIBRATE;
1117
            end
1118
          end
1119
          else
1120
            STATE     <= START_DYN_CAL;
1121
        end
1122
        WRITE_CALIBRATE:  begin   // 7'h22
1123
          Pre_SYSRST              <= 1'b0; // SYSRST not driven
1124
          IODRPCTRLR_CMD_VALID    <= 1'b1;
1125
          IODRPCTRLR_MEMCELL_ADDR <= DelayControl;
1126
          IODRPCTRLR_WRITE_DATA   <= 8'h20; // Set calibrate bit
1127
          IODRPCTRLR_R_WB         <= WRITE_MODE;
1128
          Active_IODRP            <= RZQ;
1129
          if (IODRPCTRLR_RDY_BUSY_N)
1130
            STATE <= WRITE_CALIBRATE;
1131
          else
1132
            STATE <= WAIT9;
1133
        end
1134
        WAIT9:  begin     // 7'h23
1135
          counter_en  <= 1'b1;
1136
          if (count < 6'd38)  //this adds approximately 22 extra clock cycles after WRITE_CALIBRATE
1137
            STATE     <= WAIT9;
1138
          else
1139
            STATE     <= READ_MAX_VALUE;
1140
        end
1141
        READ_MAX_VALUE: begin     // 7'h24
1142
          IODRPCTRLR_CMD_VALID    <= 1'b1;
1143
          IODRPCTRLR_MEMCELL_ADDR <= MaxValue;
1144
          IODRPCTRLR_R_WB         <= READ_MODE;
1145
          Max_Value_Previous      <= Max_Value;
1146
          if (IODRPCTRLR_RDY_BUSY_N)
1147
            STATE <= READ_MAX_VALUE;
1148
          else
1149
            STATE <= WAIT10;
1150
        end
1151
        WAIT10:  begin    // 7'h25
1152
          if (!IODRPCTRLR_RDY_BUSY_N)
1153
            STATE <= WAIT10;
1154
          else begin
1155
            Max_Value           <= IODRPCTRLR_READ_DATA;  //record the Max_Value from the IODRP controller
1156
            if (~First_In_Term_Done) begin
1157
              STATE               <= RST_DELAY;
1158
              First_In_Term_Done  <= 1'b1;
1159
            end
1160
            else
1161
              STATE               <= ANALYZE_MAX_VALUE;
1162
          end
1163
        end
1164
        ANALYZE_MAX_VALUE:  begin // 7'h26   only do a Inc or Dec during a REFRESH cycle.
1165
          if (!First_Dyn_Cal_Done)
1166
            STATE <= FIRST_DYN_CAL;
1167
          else
1168
            if ((Max_Value<Max_Value_Previous)&&(Max_Value_Delta_Dn>=INCDEC_THRESHOLD)) begin
1169
              STATE <= DECREMENT;         //May need to Decrement
1170
              TARGET_DQS_DELAY   <= Mult_Divide(Max_Value, DQS_NUMERATOR, DQS_DENOMINATOR);
1171
            end
1172
          else
1173
            if ((Max_Value>Max_Value_Previous)&&(Max_Value_Delta_Up>=INCDEC_THRESHOLD)) begin
1174
              STATE <= INCREMENT;         //May need to Increment
1175
              TARGET_DQS_DELAY   <= Mult_Divide(Max_Value, DQS_NUMERATOR, DQS_DENOMINATOR);
1176
            end
1177
          else begin
1178
            Max_Value           <= Max_Value_Previous;
1179
            STATE <= START_DYN_CAL;
1180
          end
1181
        end
1182
        FIRST_DYN_CAL:  begin // 7'h27
1183
          First_Dyn_Cal_Done  <= 1'b1;          //set flag that the First Dynamic Calibration has been completed
1184
          STATE               <= START_DYN_CAL;
1185
        end
1186
        INCREMENT: begin      // 7'h28
1187
          STATE               <= START_DYN_CAL; // Default case: Inc is not high or no longer in REFRSH
1188
          MCB_UILDQSINC       <= 1'b0;          // Default case: no inc or dec
1189
          MCB_UIUDQSINC       <= 1'b0;          // Default case: no inc or dec
1190
          MCB_UILDQSDEC       <= 1'b0;          // Default case: no inc or dec
1191
          MCB_UIUDQSDEC       <= 1'b0;          // Default case: no inc or dec
1192
          case (Inc_Dec_REFRSH_Flag)            // {Increment_Flag,Decrement_Flag,MCB_UOREFRSHFLAG},
1193
            3'b101: begin
1194
              counter_inc <= counter_inc + 1'b1;
1195
                STATE               <= INCREMENT; //Increment is still high, still in REFRSH cycle
1196
              if (DQS_DELAY < DQS_DELAY_UPPER_LIMIT && counter_inc >= 8'h04) begin //if not at the upper limit yet, and you've waited 4 clks, increment
1197
                MCB_UILDQSINC       <= 1'b1;      //increment
1198
                MCB_UIUDQSINC       <= 1'b1;      //increment
1199
                DQS_DELAY           <= DQS_DELAY + 1'b1;
1200
              end
1201
            end
1202
            3'b100: begin
1203
              if (DQS_DELAY < DQS_DELAY_UPPER_LIMIT)
1204
                STATE                <= INCREMENT; //Increment is still high, REFRESH ended - wait for next REFRESH
1205
              end
1206
            default:
1207
                STATE               <= START_DYN_CAL; // Default case
1208
          endcase
1209
        end
1210
        DECREMENT: begin      // 7'h29
1211
          STATE               <= START_DYN_CAL; // Default case: Dec is not high or no longer in REFRSH
1212
          MCB_UILDQSINC       <= 1'b0;          // Default case: no inc or dec
1213
          MCB_UIUDQSINC       <= 1'b0;          // Default case: no inc or dec
1214
          MCB_UILDQSDEC       <= 1'b0;          // Default case: no inc or dec
1215
          MCB_UIUDQSDEC       <= 1'b0;          // Default case: no inc or dec
1216
          if (DQS_DELAY != 8'h00) begin
1217
            case (Inc_Dec_REFRSH_Flag)            // {Increment_Flag,Decrement_Flag,MCB_UOREFRSHFLAG},
1218
              3'b011: begin
1219
                counter_dec <= counter_dec + 1'b1;
1220
                  STATE               <= DECREMENT; // Decrement is still high, still in REFRESH cycle
1221
                if (DQS_DELAY > DQS_DELAY_LOWER_LIMIT  && counter_dec >= 8'h04) begin //if not at the lower limit, and you've waited 4 clks, decrement
1222
                  MCB_UILDQSDEC       <= 1'b1;      // decrement
1223
                  MCB_UIUDQSDEC       <= 1'b1;      // decrement
1224
                  DQS_DELAY           <= DQS_DELAY - 1'b1; //SBS
1225
                end
1226
              end
1227
              3'b010: begin
1228
                if (DQS_DELAY > DQS_DELAY_LOWER_LIMIT) //if not at the lower limit, decrement
1229
                  STATE                 <= DECREMENT; //Decrement is still high, REFRESH ended - wait for next REFRESH
1230
                end
1231
              default: begin
1232
                  STATE               <= START_DYN_CAL; // Default case
1233
              end
1234
            endcase
1235
          end
1236
        end
1237
        DONE: begin           // 7'h2A
1238
          Pre_SYSRST              <= 1'b0;    // SYSRST cleared
1239
          MCB_UICMDEN             <= 1'b0;  // release UICMDEN
1240
          STATE <= DONE;
1241
        end
1242
        default:        begin
1243
          MCB_UICMDEN             <= 1'b0;  // release UICMDEN
1244
          MCB_UIDONECAL           <= 1'b1;  // release UIDONECAL - MCB will now initialize.
1245
          Pre_SYSRST              <= 1'b0;  // SYSRST not driven
1246
          IODRPCTRLR_CMD_VALID    <= 1'b0;
1247
          IODRPCTRLR_MEMCELL_ADDR <= 8'h00;
1248
          IODRPCTRLR_WRITE_DATA   <= 8'h00;
1249
          IODRPCTRLR_R_WB         <= 1'b0;
1250
          IODRPCTRLR_USE_BKST     <= 1'b0;
1251
          P_Term                  <= 6'b0;
1252
          N_Term                  <= 5'b0;
1253
          Active_IODRP            <= ZIO;
1254
          Max_Value_Previous      <= 8'b0;
1255
          MCB_UILDQSINC           <= 1'b0;  // no inc or dec
1256
          MCB_UIUDQSINC           <= 1'b0;  // no inc or dec
1257
          MCB_UILDQSDEC           <= 1'b0;  // no inc or dec
1258
          MCB_UIUDQSDEC           <= 1'b0;  // no inc or dec
1259
          counter_en              <= 1'b0;
1260
          First_Dyn_Cal_Done      <= 1'b0;  // flag that the First Dynamic Calibration completed
1261
          Max_Value               <= Max_Value;
1262
          STATE                   <= START;
1263
        end
1264
      endcase
1265
    end
1266
  end
1267
 
1268
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.