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

Subversion Repositories spacewiresystemc

[/] [spacewiresystemc/] [trunk/] [altera_work/] [spw_fifo_ulight/] [hps_isw_handoff/] [ulight_fifo_hps_0/] [sequencer.c] - Blame information for rev 32

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 32 redbear
/*
2
* Copyright Altera Corporation (C) 2012-2014. All rights reserved
3
*
4
* SPDX-License-Identifier:  BSD-3-Clause
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions are met:
8
*  * Redistributions of source code must retain the above copyright
9
*  notice, this list of conditions and the following disclaimer.
10
*  * Redistributions in binary form must reproduce the above copyright
11
*  notice, this list of conditions and the following disclaimer in the
12
*  documentation and/or other materials provided with the distribution.
13
*  * Neither the name of Altera Corporation nor the
14
*  names of its contributors may be used to endorse or promote products
15
*  derived from this software without specific prior written permission.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
* DISCLAIMED. IN NO EVENT SHALL ALTERA CORPORATION BE LIABLE FOR ANY
21
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
*/
28
 
29
 
30
#include "sequencer_defines.h"
31
 
32
#include "alt_types.h"
33
#include "system.h"
34
#if HPS_HW
35
#include "sdram_io.h"
36
#else
37
#include "io.h"
38
#endif
39
#include "sequencer.h"
40
#include "tclrpt.h"
41
#include "sequencer_auto.h"
42
 
43
#if HHP_HPS_SIMULATION
44
#include "hps_controller.h"
45
#endif
46
 
47
 
48
/******************************************************************************
49
 ******************************************************************************
50
 ** NOTE: Special Rules for Globale Variables                                **
51
 **                                                                          **
52
 ** All global variables that are explicitly initialized (including          **
53
 ** explicitly initialized to zero), are only initialized once, during       **
54
 ** configuration time, and not again on reset.  This means that they        **
55
 ** preserve their current contents across resets, which is needed for some  **
56
 ** special cases involving communication with external modules.  In         **
57
 ** addition, this avoids paying the price to have the memory initialized,   **
58
 ** even for zeroed data, provided it is explicitly set to zero in the code, **
59
 ** and doesn't rely on implicit initialization.                             **
60
 ******************************************************************************
61
 ******************************************************************************/
62
 
63
#ifndef ARMCOMPILER
64
#if ARRIAV
65
// Temporary workaround to place the initial stack pointer at a safe offset from end
66
#define STRINGIFY(s)            STRINGIFY_STR(s)
67
#define STRINGIFY_STR(s)        #s
68
asm(".global __alt_stack_pointer");
69
asm("__alt_stack_pointer = " STRINGIFY(STACK_POINTER));
70
#endif
71
 
72
#if CYCLONEV
73
// Temporary workaround to place the initial stack pointer at a safe offset from end
74
#define STRINGIFY(s)            STRINGIFY_STR(s)
75
#define STRINGIFY_STR(s)        #s
76
asm(".global __alt_stack_pointer");
77
asm("__alt_stack_pointer = " STRINGIFY(STACK_POINTER));
78
#endif
79
#endif
80
 
81
#if ENABLE_PRINTF_LOG
82
#include <stdio.h>
83
#include <string.h>
84
 
85
typedef struct {
86
        alt_u32 v;
87
        alt_u32 p;
88
        alt_u32 d;
89
        alt_u32 ps;
90
} dqs_pos_t;
91
 
92
/*
93
The parameters that were previously here are now supplied by generation, until the new data manager is working.
94
*/
95
 
96
struct {
97
        const char *stage;
98
 
99
        alt_u32 vfifo_idx;
100
 
101
        dqs_pos_t gwrite_pos[RW_MGR_MEM_IF_WRITE_DQS_WIDTH];
102
 
103
        dqs_pos_t dqs_enable_left_edge[RW_MGR_MEM_IF_READ_DQS_WIDTH];
104
        dqs_pos_t dqs_enable_right_edge[RW_MGR_MEM_IF_READ_DQS_WIDTH];
105
        dqs_pos_t dqs_enable_mid[RW_MGR_MEM_IF_READ_DQS_WIDTH];
106
 
107
        dqs_pos_t dqs_wlevel_left_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH];
108
        dqs_pos_t dqs_wlevel_right_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH];
109
        dqs_pos_t dqs_wlevel_mid[RW_MGR_MEM_IF_WRITE_DQS_WIDTH];
110
 
111
        alt_32 dq_read_left_edge[RW_MGR_MEM_IF_READ_DQS_WIDTH][RW_MGR_MEM_DQ_PER_READ_DQS];
112
        alt_32 dq_read_right_edge[RW_MGR_MEM_IF_READ_DQS_WIDTH][RW_MGR_MEM_DQ_PER_READ_DQS];
113
        alt_32 dq_write_left_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH][RW_MGR_MEM_DQ_PER_READ_DQS];
114
        alt_32 dq_write_right_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH][RW_MGR_MEM_DQ_PER_READ_DQS];
115
        alt_32 dm_left_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH][RW_MGR_NUM_DM_PER_WRITE_GROUP];
116
        alt_32 dm_right_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH][RW_MGR_NUM_DM_PER_WRITE_GROUP];
117
} bfm_gbl;
118
 
119
#endif
120
 
121
#if HPS_HW
122
#include <sdram.h>
123
#endif // HPS_HW
124
 
125
#if BFM_MODE
126
#include <stdio.h>
127
 
128
// DPI access function via library
129
extern long long get_sim_time(void);
130
 
131
typedef struct {
132
        alt_u32 v;
133
        alt_u32 p;
134
        alt_u32 d;
135
        alt_u32 ps;
136
} dqs_pos_t;
137
 
138
/*
139
The parameters that were previously here are now supplied by generation, until the new data manager is working.
140
*/
141
 
142
struct {
143
        FILE *outfp;
144
        int bfm_skip_guaranteed_write;
145
        int trk_sample_count;
146
        int trk_long_idle_updates;
147
        int lfifo_margin;
148
        const char *stage;
149
 
150
        alt_u32 vfifo_idx;
151
 
152
        dqs_pos_t gwrite_pos[RW_MGR_MEM_IF_WRITE_DQS_WIDTH];
153
 
154
        dqs_pos_t dqs_enable_left_edge[RW_MGR_MEM_IF_READ_DQS_WIDTH];
155
        dqs_pos_t dqs_enable_right_edge[RW_MGR_MEM_IF_READ_DQS_WIDTH];
156
        dqs_pos_t dqs_enable_mid[RW_MGR_MEM_IF_READ_DQS_WIDTH];
157
 
158
        dqs_pos_t dqs_wlevel_left_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH];
159
        dqs_pos_t dqs_wlevel_right_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH];
160
        dqs_pos_t dqs_wlevel_mid[RW_MGR_MEM_IF_WRITE_DQS_WIDTH];
161
 
162
        alt_32 dq_read_left_edge[RW_MGR_MEM_IF_READ_DQS_WIDTH][RW_MGR_MEM_DQ_PER_READ_DQS];
163
        alt_32 dq_read_right_edge[RW_MGR_MEM_IF_READ_DQS_WIDTH][RW_MGR_MEM_DQ_PER_READ_DQS];
164
        alt_32 dq_write_left_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH][RW_MGR_MEM_DQ_PER_WRITE_DQS];
165
        alt_32 dq_write_right_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH][RW_MGR_MEM_DQ_PER_WRITE_DQS];
166
        alt_32 dm_left_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH][RW_MGR_NUM_DM_PER_WRITE_GROUP];
167
        alt_32 dm_right_edge[RW_MGR_MEM_IF_WRITE_DQS_WIDTH][RW_MGR_NUM_DM_PER_WRITE_GROUP];
168
} bfm_gbl;
169
 
170
 
171
#endif
172
 
173
#if ENABLE_TCL_DEBUG
174
debug_data_t my_debug_data;
175
#endif
176
 
177
#define NEWVERSION_RDDESKEW 1
178
#define NEWVERSION_WRDESKEW 1
179
#define NEWVERSION_GW 1
180
#define NEWVERSION_WL 1
181
#define NEWVERSION_DQSEN 1
182
 
183
// Just to make the debugging code more uniform
184
#ifndef RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM
185
#define RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM 0
186
#endif
187
 
188
#if HALF_RATE
189
#define HALF_RATE_MODE 1
190
#else
191
#define HALF_RATE_MODE 0
192
#endif
193
 
194
#if QUARTER_RATE
195
#define QUARTER_RATE_MODE 1
196
#else
197
#define QUARTER_RATE_MODE 0
198
#endif
199
#define DELTA_D 1
200
 
201
// case:56390
202
// VFIFO_CONTROL_WIDTH_PER_DQS is the number of VFIFOs actually instantiated per DQS. This is always one except:
203
// AV QDRII where it is 2 for x18 and x18w2, and 4 for x36 and x36w2
204
// RLDRAMII x36 and x36w2 where it is 2.
205
// In 12.0sp1 we set this to 4 for all of the special cases above to keep it simple.
206
// In 12.0sp2 or 12.1 this should get moved to generation and unified with the same constant used in the phy mgr
207
 
208
#define VFIFO_CONTROL_WIDTH_PER_DQS 1
209
 
210
#if ARRIAV
211
 
212
#if QDRII 
213
 #if RW_MGR_MEM_DQ_PER_READ_DQS > 9
214
  #undef VFIFO_CONTROL_WIDTH_PER_DQS
215
  #define VFIFO_CONTROL_WIDTH_PER_DQS 4
216
 #endif
217
#endif // protocol check
218
 
219
#if RLDRAMII
220
 #if RW_MGR_MEM_DQ_PER_READ_DQS > 9
221
  #undef VFIFO_CONTROL_WIDTH_PER_DQS
222
  #define VFIFO_CONTROL_WIDTH_PER_DQS 2
223
 #endif
224
#endif // protocol check
225
 
226
#endif // family check
227
 
228
// In order to reduce ROM size, most of the selectable calibration steps are
229
// decided at compile time based on the user's calibration mode selection,
230
// as captured by the STATIC_CALIB_STEPS selection below.
231
//
232
// However, to support simulation-time selection of fast simulation mode, where
233
// we skip everything except the bare minimum, we need a few of the steps to
234
// be dynamic.  In those cases, we either use the DYNAMIC_CALIB_STEPS for the
235
// check, which is based on the rtl-supplied value, or we dynamically compute the
236
// value to use based on the dynamically-chosen calibration mode
237
 
238
#if QDRII
239
#define BTFLD_FMT "%llx"
240
#else
241
#define BTFLD_FMT "%lx"
242
#endif
243
 
244
#if BFM_MODE // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
245
 
246
 
247
// TODO: should make this configurable; could even have it read from config file or env at startup
248
#define DLEVEL 2
249
// space around comma is required for varargs macro to remove comma if args is empty
250
#define DPRINT(level, fmt, args...)     if (DLEVEL >= (level)) printf("[%lld] SEQ.C: " fmt "\n" , get_sim_time(), ## args)
251
#define IPRINT(fmt, args...)    printf("[%lld] SEQ.C: " fmt "\n" , get_sim_time(), ## args)
252
#define BFM_GBL_SET(field,value)        bfm_gbl.field = value
253
#define BFM_GBL_GET(field)              bfm_gbl.field
254
#define BFM_STAGE(label)                BFM_GBL_SET(stage,label)
255
#define BFM_INC_VFIFO                   bfm_gbl.vfifo_idx = (bfm_gbl.vfifo_idx + 1) % VFIFO_SIZE
256
#define COV(label)                      getpid() /* no-op marker for coverage */
257
 
258
#elif ENABLE_PRINTF_LOG // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
259
 
260
#define DLEVEL 2
261
 
262
void wait_printf_queue()
263
{
264
        alt_u32 next_entry;
265
 
266
        while (debug_printf_output->count == PRINTF_READ_BUFFER_FIFO_WORDS || debug_printf_output->slave_lock != 0)
267
        {}
268
 
269
        debug_printf_output->master_lock = 1;
270
        next_entry = (debug_printf_output->head + debug_printf_output->count) % PRINTF_READ_BUFFER_FIFO_WORDS;
271
        strcpy((char*)(&(debug_printf_output->read_buffer[next_entry])), (char*)(debug_printf_output->active_word));
272
        debug_printf_output->count++;
273
        debug_printf_output->master_lock = 0;
274
}
275
#define DPRINT(level, fmt, args...) \
276
        if (DLEVEL >= (level)) { \
277
                snprintf((char*)(debug_printf_output->active_word), PRINTF_READ_BUFFER_SIZE*4, "DEBUG:" fmt, ## args); \
278
                wait_printf_queue(); \
279
        }
280
#define IPRINT(fmt, args...) \
281
                snprintf((char*)(debug_printf_output->active_word), PRINTF_READ_BUFFER_SIZE*4, "INFO:" fmt, ## args); \
282
                wait_printf_queue();
283
 
284
#define BFM_GBL_SET(field,value)        bfm_gbl.field = value
285
#define BFM_GBL_GET(field)              bfm_gbl.field
286
#define BFM_STAGE(label)                BFM_GBL_SET(stage,label)
287
#define BFM_INC_VFIFO                   bfm_gbl.vfifo_idx = (bfm_gbl.vfifo_idx + 1) % VFIFO_SIZE
288
#define COV(label)
289
 
290
#elif HPS_HW // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
291
 
292
// For HPS running on actual hardware
293
 
294
#define DLEVEL 0
295
#ifdef HPS_HW_SERIAL_SUPPORT
296
// space around comma is required for varargs macro to remove comma if args is empty
297
#define DPRINT(level, fmt, args...)     if (DLEVEL >= (level)) printf("SEQ.C: " fmt "\n" , ## args)
298
#define IPRINT(fmt, args...)            printf("SEQ.C: " fmt "\n" , ## args)
299
#if RUNTIME_CAL_REPORT
300
#define RPRINT(fmt, args...)            printf("SEQ.C: " fmt "\n" , ## args)
301
#endif 
302
#else
303
#define DPRINT(level, fmt, args...)
304
#define IPRINT(fmt, args...)
305
#endif
306
#define BFM_GBL_SET(field,value)
307
#define BFM_GBL_GET(field)              ((long unsigned int)0)
308
#define BFM_STAGE(stage)        
309
#define BFM_INC_VFIFO
310
#define COV(label)
311
 
312
#else // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-----------------------------------
313
 
314
// Default mode
315
#define DPRINT(level, fmt, args...) 
316
#define IPRINT(fmt, args...)
317
#define BFM_GBL_SET(field,value)
318
#define BFM_GBL_GET(field) 0
319
#define BFM_STAGE(stage)        
320
#define BFM_INC_VFIFO
321
#define COV(label)
322
 
323
#endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~----------------------------------
324
 
325
#if BFM_MODE
326
#define TRACE_FUNC(fmt, args...) DPRINT(1, "%s[%ld]: " fmt, __func__, __LINE__ , ## args)
327
#else
328
#define TRACE_FUNC(fmt, args...) DPRINT(1, "%s[%d]: " fmt, __func__, __LINE__ , ## args)
329
#endif
330
 
331
#if BFM_MODE
332
// In BFM mode, we do full calibration as for real-rtl
333
#define DYNAMIC_CALIB_STEPS STATIC_CALIB_STEPS
334
#else
335
#define DYNAMIC_CALIB_STEPS (dyn_calib_steps)
336
#endif
337
 
338
#if STATIC_SIM_FILESET
339
#define STATIC_IN_RTL_SIM CALIB_IN_RTL_SIM
340
#else
341
#define STATIC_IN_RTL_SIM 0
342
#endif
343
 
344
#if STATIC_SKIP_MEM_INIT
345
#define STATIC_SKIP_DELAY_LOOPS CALIB_SKIP_DELAY_LOOPS
346
#else
347
#define STATIC_SKIP_DELAY_LOOPS 0
348
#endif
349
 
350
#if STATIC_FULL_CALIBRATION
351
#define STATIC_CALIB_STEPS (STATIC_IN_RTL_SIM | CALIB_SKIP_FULL_TEST | STATIC_SKIP_DELAY_LOOPS)
352
#elif STATIC_QUICK_CALIBRATION
353
#define STATIC_CALIB_STEPS (STATIC_IN_RTL_SIM | CALIB_SKIP_FULL_TEST | CALIB_SKIP_WRITES | CALIB_SKIP_DELAY_SWEEPS | CALIB_SKIP_ALL_BITS_CHK | STATIC_SKIP_DELAY_LOOPS)
354
#elif STATIC_SKIP_CALIBRATION
355
#define STATIC_CALIB_STEPS (STATIC_IN_RTL_SIM | CALIB_SKIP_FULL_TEST | CALIB_SKIP_WRITES | CALIB_SKIP_WLEVEL | CALIB_SKIP_LFIFO | CALIB_SKIP_VFIFO | CALIB_SKIP_DELAY_SWEEPS | CALIB_SKIP_ALL_BITS_CHK | STATIC_SKIP_DELAY_LOOPS)
356
#else
357
#undef STATIC_CALIB_STEPS
358
// This should force an error
359
#endif
360
 
361
// calibration steps requested by the rtl
362
alt_u16 dyn_calib_steps = 0;
363
 
364
// To make CALIB_SKIP_DELAY_LOOPS a dynamic conditional option
365
// instead of static, we use boolean logic to select between
366
// non-skip and skip values
367
//
368
// The mask is set to include all bits when not-skipping, but is
369
// zero when skipping
370
 
371
alt_u16 skip_delay_mask = 0;     // mask off bits when skipping/not-skipping
372
 
373
#define SKIP_DELAY_LOOP_VALUE_OR_ZERO(non_skip_value) \
374
        ((non_skip_value) & skip_delay_mask)
375
 
376
 
377
// TODO: The skip group strategy is completely missing
378
 
379
gbl_t *gbl = 0;
380
param_t *param = 0;
381
 
382
alt_u32 curr_shadow_reg = 0;
383
 
384
#if ENABLE_DELAY_CHAIN_WRITE
385
alt_u32 vfifo_settings[RW_MGR_MEM_IF_READ_DQS_WIDTH];
386
#endif // ENABLE_DELAY_CHAIN_WRITE
387
 
388
#if ENABLE_NON_DESTRUCTIVE_CALIB
389
// Technically, the use of these variables could be separated from ENABLE_NON_DESTRUCTIVE_CALIB
390
// but currently they are part of a single feature which is not fully validated, so we're keeping
391
// them together
392
 
393
// These variables can be modified by external rtl modules, and hence are "volatile"
394
volatile alt_u32 no_init = 0;
395
volatile alt_u32 abort_cal = 0;
396
#endif
397
 
398
alt_u32 rw_mgr_mem_calibrate_write_test (alt_u32 rank_bgn, alt_u32 write_group, alt_u32 use_dm, alt_u32 all_correct, t_btfld *bit_chk, alt_u32 all_ranks);
399
 
400
#if ENABLE_BRINGUP_DEBUGGING
401
 
402
#define DI_BUFFER_DEBUG_SIZE   64
403
 
404
alt_u8 di_buf_gbl[DI_BUFFER_DEBUG_SIZE*4] = {0};
405
 
406
void load_di_buf_gbl(void)
407
{
408
        int i;
409
        int j;
410
 
411
        for (i = 0; i < DI_BUFFER_DEBUG_SIZE; i++) {
412
                alt_u32 val = IORD_32DIRECT(RW_MGR_DI_BASE + i*4, 0);
413
                for (j = 0; j < 4; j++) {
414
                        alt_u8 byte = (val >> (8*j)) & 0xff;
415
                        di_buf_gbl[i*4 + j] = byte;
416
                }
417
        }
418
}
419
 
420
#endif  /* ENABLE_BRINGUP_DEBUGGING */
421
 
422
 
423
#if ENABLE_DQSEN_SWEEP
424
void init_di_buffer(void)
425
{
426
        alt_u32 i;
427
 
428
        debug_data->di_report.flags = 0;
429
        debug_data->di_report.cur_samples = 0;
430
 
431
        for (i = 0; i < NUM_DI_SAMPLE; i++)
432
        {
433
                debug_data->di_report.di_buffer[i].bit_chk = 0;
434
                debug_data->di_report.di_buffer[i].delay = 0;
435
                debug_data->di_report.di_buffer[i].d = 0;
436
                debug_data->di_report.di_buffer[i].v = 0;
437
                debug_data->di_report.di_buffer[i].p = 0;
438
                debug_data->di_report.di_buffer[i].di_buffer_0a = 0;
439
                debug_data->di_report.di_buffer[i].di_buffer_0b = 0;
440
                debug_data->di_report.di_buffer[i].di_buffer_1a = 0;
441
                debug_data->di_report.di_buffer[i].di_buffer_1b = 0;
442
                debug_data->di_report.di_buffer[i].di_buffer_2a = 0;
443
                debug_data->di_report.di_buffer[i].di_buffer_2b = 0;
444
                debug_data->di_report.di_buffer[i].di_buffer_3a = 0;
445
                debug_data->di_report.di_buffer[i].di_buffer_3b = 0;
446
                debug_data->di_report.di_buffer[i].di_buffer_4a = 0;
447
                debug_data->di_report.di_buffer[i].di_buffer_4b = 0;
448
        }
449
}
450
 
451
inline void flag_di_buffer_ready()
452
{
453
        debug_data->di_report.flags |= DI_REPORT_FLAGS_READY;
454
}
455
 
456
inline void flag_di_buffer_done()
457
{
458
        debug_data->di_report.flags |= DI_REPORT_FLAGS_READY;
459
        debug_data->di_report.flags |= DI_REPORT_FLAGS_DONE;
460
}
461
 
462
void wait_di_buffer(void)
463
{
464
        if (debug_data->di_report.cur_samples == NUM_DI_SAMPLE)
465
        {
466
                flag_di_buffer_ready();
467
                while (debug_data->di_report.cur_samples != 0)
468
                {
469
                }
470
                debug_data->di_report.flags = 0;
471
        }
472
}
473
 
474
void sample_di_data(alt_u32 bit_chk, alt_u32 delay, alt_u32 d, alt_u32 v, alt_u32 p)
475
{
476
        alt_u32 k;
477
        alt_u32 di_status_word;
478
        alt_u32 di_word_avail;
479
        alt_u32 di_write_to_read_ratio;
480
        alt_u32 di_write_to_read_ratio_2_exp;
481
 
482
        wait_di_buffer();
483
 
484
        k = debug_data->di_report.cur_samples;
485
 
486
        debug_data->di_report.di_buffer[k].bit_chk = bit_chk;
487
        debug_data->di_report.di_buffer[k].delay = delay;
488
        debug_data->di_report.di_buffer[k].d = d;
489
        debug_data->di_report.di_buffer[k].v = v;
490
        debug_data->di_report.di_buffer[k].p = p;
491
 
492
        di_status_word = IORD_32DIRECT(BASE_RW_MGR + 8, 0);
493
        di_word_avail = di_status_word & 0x0000FFFF;
494
        di_write_to_read_ratio = (di_status_word & 0x00FF0000) >> 16;
495
        di_write_to_read_ratio_2_exp = (di_status_word & 0xFF000000) >> 24;
496
 
497
        debug_data->di_report.di_buffer[k].di_buffer_0a = IORD_32DIRECT(BASE_RW_MGR + 16 + 0*4, 0);
498
        debug_data->di_report.di_buffer[k].di_buffer_0b = IORD_32DIRECT(BASE_RW_MGR + 16 + 1*4, 0);
499
        debug_data->di_report.di_buffer[k].di_buffer_1a = IORD_32DIRECT(BASE_RW_MGR + 16 + 2*4, 0);
500
        debug_data->di_report.di_buffer[k].di_buffer_1b = IORD_32DIRECT(BASE_RW_MGR + 16 + 3*4, 0);
501
        debug_data->di_report.di_buffer[k].di_buffer_2a = IORD_32DIRECT(BASE_RW_MGR + 16 + 4*4, 0);
502
        debug_data->di_report.di_buffer[k].di_buffer_2b = IORD_32DIRECT(BASE_RW_MGR + 16 + 5*4, 0);
503
        debug_data->di_report.di_buffer[k].di_buffer_3a = IORD_32DIRECT(BASE_RW_MGR + 16 + 6*4, 0);
504
        debug_data->di_report.di_buffer[k].di_buffer_3b = IORD_32DIRECT(BASE_RW_MGR + 16 + 7*4, 0);
505
        debug_data->di_report.di_buffer[k].di_buffer_4a = IORD_32DIRECT(BASE_RW_MGR + 16 + 8*4, 0);
506
        debug_data->di_report.di_buffer[k].di_buffer_4b = IORD_32DIRECT(BASE_RW_MGR + 16 + 9*4, 0);
507
 
508
        debug_data->di_report.cur_samples = debug_data->di_report.cur_samples + 1;
509
}
510
#endif
511
 
512
// This (TEST_SIZE) is used to test handling of large roms, to make
513
// sure we are sizing things correctly
514
// Note, the initialized data takes up twice the space in rom, since
515
// there needs to be a copy with the initial value and a copy that is
516
// written too, since on soft-reset, it needs to have the initial values
517
// without reloading the memory from external sources
518
 
519
// #define TEST_SIZE    (6*1024)
520
 
521
#ifdef TEST_SIZE
522
 
523
#define PRE_POST_TEST_SIZE 3
524
 
525
unsigned int pre_test_size_mem[PRE_POST_TEST_SIZE] = { 1, 2, 3};
526
 
527
unsigned int test_size_mem[TEST_SIZE/sizeof(unsigned int)] = { 100, 200, 300 };
528
 
529
unsigned int post_test_size_mem[PRE_POST_TEST_SIZE] = {10, 20, 30};
530
 
531
void write_test_mem(void)
532
{
533
        int i;
534
 
535
        for (i = 0; i < PRE_POST_TEST_SIZE; i++) {
536
                pre_test_size_mem[i] = (i+1)*10;
537
                post_test_size_mem[i] = (i+1);
538
        }
539
 
540
        for (i = 0; i < sizeof(test_size_mem)/sizeof(unsigned int); i++) {
541
                test_size_mem[i] = i;
542
        }
543
 
544
}
545
 
546
int check_test_mem(int start)
547
{
548
        int i;
549
 
550
        for (i = 0; i < PRE_POST_TEST_SIZE; i++) {
551
                if (start) {
552
                        if (pre_test_size_mem[i] != (i+1)) {
553
                                return 0;
554
                        }
555
                        if (post_test_size_mem[i] != (i+1)*10) {
556
                                return 0;
557
                        }
558
                } else {
559
                        if (pre_test_size_mem[i] != (i+1)*10) {
560
                                return 0;
561
                        }
562
                        if (post_test_size_mem[i] != (i+1)) {
563
                                return 0;
564
                        }
565
                }
566
        }
567
 
568
        for (i = 0; i < sizeof(test_size_mem)/sizeof(unsigned int); i++) {
569
                if (start) {
570
                        if (i < 3) {
571
                                if (test_size_mem[i] != (i+1)*100) {
572
                                        return 0;
573
                                }
574
                        } else {
575
                                if (test_size_mem[i] != 0) {
576
                                        return 0;
577
                                }
578
                        }
579
                } else {
580
                        if (test_size_mem[i] != i) {
581
                                return 0;
582
                        }
583
                }
584
        }
585
 
586
        return 1;
587
}
588
 
589
#endif // TEST_SIZE
590
 
591
static void set_failing_group_stage(alt_u32 group, alt_u32 stage, alt_u32 substage)
592
{
593
        ALTERA_ASSERT(group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
594
 
595
        // Only set the global stage if there was not been any other failing group
596
        if (gbl->error_stage == CAL_STAGE_NIL)
597
        {
598
                gbl->error_substage = substage;
599
                gbl->error_stage = stage;
600
                gbl->error_group = group;
601
                TCLRPT_SET(debug_summary_report->error_sub_stage, substage);
602
                TCLRPT_SET(debug_summary_report->error_stage, stage);
603
                TCLRPT_SET(debug_summary_report->error_group, group);
604
 
605
        }
606
 
607
        // Always set the group specific errors
608
        TCLRPT_SET(debug_cal_report->cal_status_per_group[curr_shadow_reg][group].error_stage, stage);
609
        TCLRPT_SET(debug_cal_report->cal_status_per_group[curr_shadow_reg][group].error_sub_stage, substage);
610
 
611
}
612
 
613
static inline void reg_file_set_group(alt_u32 set_group)
614
{
615
        // Read the current group and stage
616
        alt_u32 cur_stage_group = IORD_32DIRECT (REG_FILE_CUR_STAGE, 0);
617
 
618
        // Clear the group
619
        cur_stage_group &= 0x0000FFFF;
620
 
621
        // Set the group
622
        cur_stage_group |= (set_group << 16);
623
 
624
        // Write the data back
625
        IOWR_32DIRECT (REG_FILE_CUR_STAGE, 0, cur_stage_group);
626
}
627
 
628
static inline void reg_file_set_stage(alt_u32 set_stage)
629
{
630
        // Read the current group and stage
631
        alt_u32 cur_stage_group = IORD_32DIRECT (REG_FILE_CUR_STAGE, 0);
632
 
633
        // Clear the stage and substage
634
        cur_stage_group &= 0xFFFF0000;
635
 
636
        // Set the stage
637
        cur_stage_group |= (set_stage & 0x000000FF);
638
 
639
        // Write the data back
640
        IOWR_32DIRECT (REG_FILE_CUR_STAGE, 0, cur_stage_group);
641
}
642
 
643
static inline void reg_file_set_sub_stage(alt_u32 set_sub_stage)
644
{
645
        // Read the current group and stage
646
        alt_u32 cur_stage_group = IORD_32DIRECT (REG_FILE_CUR_STAGE, 0);
647
 
648
        // Clear the substage
649
        cur_stage_group &= 0xFFFF00FF;
650
 
651
        // Set the sub stage
652
        cur_stage_group |= ((set_sub_stage << 8) & 0x0000FF00);
653
 
654
        // Write the data back
655
        IOWR_32DIRECT (REG_FILE_CUR_STAGE, 0, cur_stage_group);
656
}
657
 
658
static inline alt_u32 is_write_group_enabled_for_dm(alt_u32 write_group)
659
{
660
#if DM_PINS_ENABLED
661
 #if RLDRAMII
662
        alt_32 decrement_counter = write_group + 1;
663
 
664
        while (decrement_counter > 0)
665
        {
666
                decrement_counter -= RW_MGR_MEM_IF_WRITE_DQS_WIDTH/RW_MGR_MEM_DATA_MASK_WIDTH;
667
        }
668
 
669
        if (decrement_counter == 0)
670
        {
671
                return 1;
672
        }
673
        else
674
        {
675
                return 0;
676
        }
677
 #else
678
        return 1;
679
 #endif
680
#else
681
        return 0;
682
#endif
683
}
684
 
685
static inline void select_curr_shadow_reg_using_rank(alt_u32 rank)
686
{
687
#if USE_SHADOW_REGS
688
        //USER Map the rank to its shadow reg and set the global variable
689
        curr_shadow_reg = (rank >> (NUM_RANKS_PER_SHADOW_REG - 1));
690
#endif
691
}
692
 
693
void initialize(void)
694
{
695
        TRACE_FUNC();
696
 
697
        //USER calibration has control over path to memory 
698
 
699
#if HARD_PHY
700
        // In Hard PHY this is a 2-bit control:
701
        // 0: AFI Mux Select
702
        // 1: DDIO Mux Select
703
        IOWR_32DIRECT (PHY_MGR_MUX_SEL, 0, 0x3);
704
#else
705
        IOWR_32DIRECT (PHY_MGR_MUX_SEL, 0, 1);
706
#endif
707
 
708
        //USER memory clock is not stable we begin initialization 
709
 
710
        IOWR_32DIRECT (PHY_MGR_RESET_MEM_STBL, 0, 0);
711
 
712
        //USER calibration status all set to zero 
713
 
714
        IOWR_32DIRECT (PHY_MGR_CAL_STATUS, 0, 0);
715
        IOWR_32DIRECT (PHY_MGR_CAL_DEBUG_INFO, 0, 0);
716
 
717
        if (((DYNAMIC_CALIB_STEPS) & CALIB_SKIP_ALL) != CALIB_SKIP_ALL) {
718
                param->read_correct_mask_vg  = ((t_btfld)1 << (RW_MGR_MEM_DQ_PER_READ_DQS / RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS)) - 1;
719
                param->write_correct_mask_vg = ((t_btfld)1 << (RW_MGR_MEM_DQ_PER_READ_DQS / RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS)) - 1;
720
                param->read_correct_mask     = ((t_btfld)1 << RW_MGR_MEM_DQ_PER_READ_DQS) - 1;
721
                param->write_correct_mask    = ((t_btfld)1 << RW_MGR_MEM_DQ_PER_WRITE_DQS) - 1;
722
                param->dm_correct_mask       = ((t_btfld)1 << (RW_MGR_MEM_DATA_WIDTH / RW_MGR_MEM_DATA_MASK_WIDTH)) - 1;
723
        }
724
}
725
 
726
 
727
#if MRS_MIRROR_PING_PONG_ATSO
728
// This code is specific to the ATSO setup.  There are two ways to set
729
// the cs/odt mask:
730
// 1. the normal way (set_rank_and_odt_mask)
731
//  This method will be used in general.  The behavior will be to unmask
732
//  BOTH CS (i.e. broadcast to both sides as if calibrating one large interface).
733
// 2. this function
734
//  This method will be used for MRS settings only.  This allows us to do settings
735
//  on a per-side basis.  This is needed because Slot 1 Rank 1 needs a mirrored MRS.
736
// This function is specific to our setup ONLY.
737
void set_rank_and_odt_mask_for_ping_pong_atso(alt_u32 side, alt_u32 odt_mode)
738
{
739
        alt_u32 odt_mask_0 = 0;
740
        alt_u32 odt_mask_1 = 0;
741
        alt_u32 cs_and_odt_mask;
742
 
743
        if(odt_mode == RW_MGR_ODT_MODE_READ_WRITE)
744
        {
745
                //USER 1 Rank
746
                //USER Read: ODT = 0
747
                //USER Write: ODT = 1
748
                odt_mask_0 = 0x0;
749
                odt_mask_1 = 0x1;
750
        }
751
        else
752
        {
753
                odt_mask_0 = 0x0;
754
                odt_mask_1 = 0x0;
755
        }
756
 
757
        cs_and_odt_mask =
758
                (0xFF & ~(1 << side)) |
759
                ((0xFF & odt_mask_0) << 8) |
760
                ((0xFF & odt_mask_1) << 16);
761
 
762
        IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, cs_and_odt_mask);
763
}
764
#endif
765
 
766
#if DDR3
767
void set_rank_and_odt_mask(alt_u32 rank, alt_u32 odt_mode)
768
{
769
        alt_u32 odt_mask_0 = 0;
770
        alt_u32 odt_mask_1 = 0;
771
        alt_u32 cs_and_odt_mask;
772
 
773
        if(odt_mode == RW_MGR_ODT_MODE_READ_WRITE)
774
        {
775
#if USE_SHADOW_REGS     
776
                alt_u32 rank_one_hot = (0xFF & (1 << rank));
777
                select_curr_shadow_reg_using_rank(rank);
778
 
779
                //USER Assert afi_rrank and afi_wrank. These signals ultimately drive
780
                //USER the read/write rank select signals which select the shadow register.
781
                IOWR_32DIRECT (RW_MGR_SET_ACTIVE_RANK, 0, rank_one_hot);
782
#endif  
783
 
784
                if ( LRDIMM ) {
785
                        // USER LRDIMMs have two cases to consider: single-slot and dual-slot.
786
                        // USER In single-slot, assert ODT for write only.
787
                        // USER In dual-slot, assert ODT for both slots for write,
788
                        // USER and on the opposite slot only for reads.
789
                        // USER
790
                        // USER Further complicating this is that both DIMMs have either 1 or 2 ODT
791
                        // USER inputs, which do the same thing (only one is actually required).
792
                        if ((RW_MGR_MEM_CHIP_SELECT_WIDTH/RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM) == 1) {
793
                                // USER Single-slot case
794
                                if (RW_MGR_MEM_ODT_WIDTH == 1) {
795
                                        // USER Read = 0, Write = 1
796
                                        odt_mask_0 = 0x0;
797
                                        odt_mask_1 = 0x1;
798
                                } else if (RW_MGR_MEM_ODT_WIDTH == 2) {
799
                                        // USER Read = 00, Write = 11
800
                                        odt_mask_0 = 0x0;
801
                                        odt_mask_1 = 0x3;
802
                                }
803
                        } else if ((RW_MGR_MEM_CHIP_SELECT_WIDTH/RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM) == 2) {
804
                                // USER Dual-slot case
805
                                if (RW_MGR_MEM_ODT_WIDTH == 2) {
806
                                        // USER Read: asserted for opposite slot, Write: asserted for both
807
                                        odt_mask_0 = (rank < 2) ? 0x2 : 0x1;
808
                                        odt_mask_1 = 0x3;
809
                                } else if (RW_MGR_MEM_ODT_WIDTH == 4) {
810
                                        // USER Read: asserted for opposite slot, Write: asserted for both
811
                                        odt_mask_0 = (rank < 2) ? 0xC : 0x3;
812
                                        odt_mask_1 = 0xF;
813
                                }
814
                        }
815
                } else if(RW_MGR_MEM_NUMBER_OF_RANKS == 1) {
816
                        //USER 1 Rank
817
                        //USER Read: ODT = 0
818
                        //USER Write: ODT = 1
819
                        odt_mask_0 = 0x0;
820
                        odt_mask_1 = 0x1;
821
                } else if(RW_MGR_MEM_NUMBER_OF_RANKS == 2) {
822
                        //USER 2 Ranks
823
                        if(RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM == 1 ||
824
                           (RDIMM && RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM == 2
825
                           && RW_MGR_MEM_CHIP_SELECT_WIDTH == 4)) {
826
                                //USER - Dual-Slot , Single-Rank (1 chip-select per DIMM)
827
                                //USER OR
828
                                //USER - RDIMM, 4 total CS (2 CS per DIMM) means 2 DIMM
829
                                //USER Since MEM_NUMBER_OF_RANKS is 2 they are both single rank
830
                                //USER with 2 CS each (special for RDIMM)
831
                                //USER Read: Turn on ODT on the opposite rank
832
                                //USER Write: Turn on ODT on all ranks
833
                                odt_mask_0 = 0x3 & ~(1 << rank);
834
                                odt_mask_1 = 0x3;
835
                        } else {
836
                                //USER - Single-Slot , Dual-rank DIMMs (2 chip-selects per DIMM)
837
                                //USER Read: Turn on ODT off on all ranks
838
                                //USER Write: Turn on ODT on active rank
839
                                odt_mask_0 = 0x0;
840
                                odt_mask_1 = 0x3 & (1 << rank);
841
                        }
842
                                } else {
843
                        //USER 4 Ranks
844
                        //USER Read:
845
                        //USER ----------+-----------------------+
846
                        //USER           |                       |
847
                        //USER           |         ODT           |
848
                        //USER Read From +-----------------------+
849
                        //USER   Rank    |  3  |  2  |  1  |  0  |
850
                        //USER ----------+-----+-----+-----+-----+
851
                        //USER     0     |  0  |  1  |  0  |  0  |
852
                        //USER     1     |  1  |  0  |  0  |  0  |
853
                        //USER     2     |  0  |  0  |  0  |  1  |
854
                        //USER     3     |  0  |  0  |  1  |  0  |
855
                        //USER ----------+-----+-----+-----+-----+
856
                        //USER
857
                        //USER Write:
858
                        //USER ----------+-----------------------+
859
                        //USER           |                       |
860
                        //USER           |         ODT           |
861
                        //USER Write To  +-----------------------+
862
                        //USER   Rank    |  3  |  2  |  1  |  0  |
863
                        //USER ----------+-----+-----+-----+-----+
864
                        //USER     0     |  0  |  1  |  0  |  1  |
865
                        //USER     1     |  1  |  0  |  1  |  0  |
866
                        //USER     2     |  0  |  1  |  0  |  1  |
867
                        //USER     3     |  1  |  0  |  1  |  0  |
868
                        //USER ----------+-----+-----+-----+-----+
869
                        switch(rank)
870
                        {
871
                                case 0:
872
                                        odt_mask_0 = 0x4;
873
                                        odt_mask_1 = 0x5;
874
                                break;
875
                                case 1:
876
                                        odt_mask_0 = 0x8;
877
                                        odt_mask_1 = 0xA;
878
                                break;
879
                                case 2:
880
                                        odt_mask_0 = 0x1;
881
                                        odt_mask_1 = 0x5;
882
                                break;
883
                                case 3:
884
                                        odt_mask_0 = 0x2;
885
                                        odt_mask_1 = 0xA;
886
                                break;
887
                        }
888
                }
889
        }
890
        else
891
        {
892
                odt_mask_0 = 0x0;
893
                odt_mask_1 = 0x0;
894
        }
895
 
896
#if ADVANCED_ODT_CONTROL
897
        // odt_mask_0 = read
898
        // odt_mask_1 = write
899
        odt_mask_0  = (CFG_READ_ODT_CHIP  >> (RW_MGR_MEM_ODT_WIDTH * rank));
900
        odt_mask_1  = (CFG_WRITE_ODT_CHIP >> (RW_MGR_MEM_ODT_WIDTH * rank));
901
        odt_mask_0 &= ((1 << RW_MGR_MEM_ODT_WIDTH) - 1);
902
        odt_mask_1 &= ((1 << RW_MGR_MEM_ODT_WIDTH) - 1);
903
#endif
904
 
905
#if MRS_MIRROR_PING_PONG_ATSO
906
        // See set_cs_and_odt_mask_for_ping_pong_atso
907
        cs_and_odt_mask =
908
                        (0xFC) |
909
                        ((0xFF & odt_mask_0) << 8) |
910
                        ((0xFF & odt_mask_1) << 16);
911
#else
912
        if(RDIMM && RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM == 2
913
           && RW_MGR_MEM_CHIP_SELECT_WIDTH == 4 && RW_MGR_MEM_NUMBER_OF_RANKS == 2) {
914
                //USER See RDIMM special case above
915
                cs_and_odt_mask =
916
                        (0xFF & ~(1 << (2*rank))) |
917
                        ((0xFF & odt_mask_0) << 8) |
918
                        ((0xFF & odt_mask_1) << 16);
919
        } else if (LRDIMM) {
920
#if LRDIMM
921
                // USER LRDIMM special cases - When RM=2, CS[2] is remapped to A[16] so skip it,
922
                // USER and when RM=4, CS[3:2] are remapped to A[17:16] so skip them both.
923
                alt_u32 lrdimm_rank = 0;
924
                alt_u32 lrdimm_rank_mask = 0;
925
 
926
                //USER When rank multiplication is active, the remapped CS pins must be forced low
927
                //USER instead of high for proper targetted RTT_NOM programming.
928
                if (LRDIMM_RANK_MULTIPLICATION_FACTOR == 2) {
929
                        // USER Mask = CS[5:0] = 011011
930
                        lrdimm_rank_mask = (0x3 | (0x3 << 3));
931
                } else if (LRDIMM_RANK_MULTIPLICATION_FACTOR == 4) {
932
                        // USER Mask = CS[7:0] = 00110011
933
                        lrdimm_rank_mask = (0x3 | (0x3 << 4));
934
                }
935
 
936
                // USER Handle LRDIMM cases where Rank multiplication may be active
937
                if (((RW_MGR_MEM_CHIP_SELECT_WIDTH/RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM) == 1)) {
938
                        // USER Single-DIMM case
939
                        lrdimm_rank = ~(1 << rank);
940
                } else if ((RW_MGR_MEM_CHIP_SELECT_WIDTH/RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM) == 2) {
941
                        if (rank < (RW_MGR_MEM_NUMBER_OF_RANKS >> 1)) {
942
                        // USER Dual-DIMM case, accessing first slot
943
                                lrdimm_rank = ~(1 << rank);
944
                        } else {
945
                        // USER Dual-DIMM case, accessing second slot
946
                                lrdimm_rank = ~(1 << (rank + RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM - (RW_MGR_MEM_NUMBER_OF_RANKS>>1)));
947
                        }
948
                }
949
                cs_and_odt_mask =
950
                        (lrdimm_rank_mask & lrdimm_rank) |
951
                        ((0xFF & odt_mask_0) << 8) |
952
                        ((0xFF & odt_mask_1) << 16);
953
#endif // LRDIMM
954
        } else {
955
                cs_and_odt_mask =
956
                        (0xFF & ~(1 << rank)) |
957
                        ((0xFF & odt_mask_0) << 8) |
958
                        ((0xFF & odt_mask_1) << 16);
959
        }
960
#endif
961
 
962
        IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, cs_and_odt_mask);
963
}
964
#else
965
#if DDR2
966
void set_rank_and_odt_mask(alt_u32 rank, alt_u32 odt_mode)
967
{
968
        alt_u32 odt_mask_0 = 0;
969
        alt_u32 odt_mask_1 = 0;
970
        alt_u32 cs_and_odt_mask;
971
 
972
        if(odt_mode == RW_MGR_ODT_MODE_READ_WRITE)
973
        {
974
                if(RW_MGR_MEM_NUMBER_OF_RANKS == 1) {
975
                        //USER 1 Rank
976
                        //USER Read: ODT = 0
977
                        //USER Write: ODT = 1
978
                        odt_mask_0 = 0x0;
979
                        odt_mask_1 = 0x1;
980
                } else if(RW_MGR_MEM_NUMBER_OF_RANKS == 2) {
981
                        //USER 2 Ranks
982
                        if(RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM == 1 ||
983
                           (RDIMM && RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM == 2
984
                           && RW_MGR_MEM_CHIP_SELECT_WIDTH == 4)) {
985
                                //USER - Dual-Slot , Single-Rank (1 chip-select per DIMM)
986
                                //USER OR
987
                                //USER - RDIMM, 4 total CS (2 CS per DIMM) means 2 DIMM
988
                                //USER Since MEM_NUMBER_OF_RANKS is 2 they are both single rank
989
                                //USER with 2 CS each (special for RDIMM)
990
                                //USER Read/Write: Turn on ODT on the opposite rank
991
                                odt_mask_0 = 0x3 & ~(1 << rank);
992
                                odt_mask_1 = 0x3 & ~(1 << rank);
993
                        } else {
994
                                //USER - Single-Slot , Dual-rank DIMMs (2 chip-selects per DIMM)
995
                                //USER Read: Turn on ODT off on all ranks
996
                                //USER Write: Turn on ODT on active rank
997
                                odt_mask_0 = 0x0;
998
                                odt_mask_1 = 0x3 & (1 << rank);
999
                        }
1000
                } else {
1001
                        //USER 4 Ranks
1002
                        //USER Read/Write:
1003
                        //USER -----------+-----------------------+
1004
                        //USER            |                       |
1005
                        //USER            |         ODT           |
1006
                        //USER Read/Write |                       |
1007
                        //USER   From     +-----------------------+
1008
                        //USER   Rank     |  3  |  2  |  1  |  0  |
1009
                        //USER -----------+-----+-----+-----+-----+
1010
                        //USER     0      |  0  |  1  |  0  |  0  |
1011
                        //USER     1      |  1  |  0  |  0  |  0  |
1012
                        //USER     2      |  0  |  0  |  0  |  1  |
1013
                        //USER     3      |  0  |  0  |  1  |  0  |
1014
                        //USER -----------+-----+-----+-----+-----+
1015
                        switch(rank)
1016
                        {
1017
                                case 0:
1018
                                        odt_mask_0 = 0x4;
1019
                                        odt_mask_1 = 0x4;
1020
                                break;
1021
                                case 1:
1022
                                        odt_mask_0 = 0x8;
1023
                                        odt_mask_1 = 0x8;
1024
                                break;
1025
                                case 2:
1026
                                        odt_mask_0 = 0x1;
1027
                                        odt_mask_1 = 0x1;
1028
                                break;
1029
                                case 3:
1030
                                        odt_mask_0 = 0x2;
1031
                                        odt_mask_1 = 0x2;
1032
                                break;
1033
                        }
1034
                }
1035
        }
1036
        else
1037
        {
1038
                odt_mask_0 = 0x0;
1039
                odt_mask_1 = 0x0;
1040
        }
1041
 
1042
        if(RDIMM && RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM == 2
1043
           && RW_MGR_MEM_CHIP_SELECT_WIDTH == 4 && RW_MGR_MEM_NUMBER_OF_RANKS == 2) {
1044
                //USER See RDIMM/LRDIMM special case above
1045
                cs_and_odt_mask =
1046
                        (0xFF & ~(1 << (2*rank))) |
1047
                        ((0xFF & odt_mask_0) << 8) |
1048
                        ((0xFF & odt_mask_1) << 16);
1049
        } else {
1050
                cs_and_odt_mask =
1051
                        (0xFF & ~(1 << rank)) |
1052
                        ((0xFF & odt_mask_0) << 8) |
1053
                        ((0xFF & odt_mask_1) << 16);
1054
        }
1055
 
1056
        IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, cs_and_odt_mask);
1057
}
1058
#else // QDRII and RLDRAMx
1059
void set_rank_and_odt_mask(alt_u32 rank, alt_u32 odt_mode)
1060
{
1061
        alt_u32 cs_and_odt_mask =
1062
                (0xFF & ~(1 << rank));
1063
 
1064
        IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, cs_and_odt_mask);
1065
}
1066
#endif
1067
#endif
1068
 
1069
//USER Given a rank, select the set of shadow registers that is responsible for the
1070
//USER delays of such rank, so that subsequent SCC updates will go to those shadow
1071
//USER registers. 
1072
void select_shadow_regs_for_update (alt_u32 rank, alt_u32 group, alt_u32 update_scan_chains)
1073
{
1074
#if USE_SHADOW_REGS
1075
        alt_u32 rank_one_hot = (0xFF & (1 << rank));
1076
 
1077
        //USER Assert afi_rrank and afi_wrank. These signals ultimately drive
1078
        //USER the read/write rank select signals which select the shadow register.
1079
        IOWR_32DIRECT (RW_MGR_SET_ACTIVE_RANK, 0, rank_one_hot);
1080
 
1081
        //USER Cause the SCC manager to switch its register file, which is used as
1082
        //USER local cache of the various dtap/ptap settings. There's one register file
1083
        //USER per shadow register set.
1084
        IOWR_32DIRECT (SCC_MGR_ACTIVE_RANK, 0, rank_one_hot);
1085
 
1086
        if (update_scan_chains) {
1087
                alt_u32 i;
1088
 
1089
                //USER On the read side, a memory read is required because the read rank
1090
                //USER select signal (as well as the postamble delay chain settings) is clocked
1091
                //USER into the periphery by the postamble signal. Simply asserting afi_rrank
1092
                //USER is not enough. If update_scc_regfile is not set, we assume there'll be a 
1093
                //USER subsequent read that'll handle this.
1094
                for (i = 0; i < RW_MGR_MEM_NUMBER_OF_RANKS; ++i) {
1095
 
1096
                        //USER The dummy read can go to any non-skipped rank.
1097
                        //USER Skipped ranks are uninitialized and their banks are un-activated.
1098
                        //USER Accessing skipped ranks can lead to bad behavior.
1099
                        if (! param->skip_ranks[i]) {
1100
 
1101
                                set_rank_and_odt_mask(i, RW_MGR_ODT_MODE_READ_WRITE);
1102
 
1103
                                // must re-assert afi_wrank/afi_rrank prior to issuing read 
1104
                                // because set_rank_and_odt_mask may have changed the signals.
1105
                                IOWR_32DIRECT (RW_MGR_SET_ACTIVE_RANK, 0, rank_one_hot);
1106
 
1107
                                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x10);
1108
                                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_READ_B2B_WAIT1);
1109
 
1110
                                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0x10);
1111
                                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_READ_B2B_WAIT2);
1112
 
1113
                                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x0);
1114
                                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_READ_B2B);
1115
 
1116
                                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_3, 0, 0x0);
1117
                                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_3, 0, __RW_MGR_READ_B2B);
1118
 
1119
                                IOWR_32DIRECT (RW_MGR_RUN_ALL_GROUPS, 0, __RW_MGR_READ_B2B);
1120
 
1121
                                //USER The dummy read above may cause the DQS enable signal to be stuck high.
1122
                                //USER The following corrects this.
1123
                                IOWR_32DIRECT (RW_MGR_RUN_ALL_GROUPS, 0, __RW_MGR_CLEAR_DQS_ENABLE);
1124
 
1125
                                set_rank_and_odt_mask(i, RW_MGR_ODT_MODE_OFF);
1126
 
1127
                                break;
1128
                        }
1129
                }
1130
 
1131
                //USER Reset the fifos to get pointers to known state 
1132
                IOWR_32DIRECT (PHY_MGR_CMD_FIFO_RESET, 0, 0);
1133
                IOWR_32DIRECT (RW_MGR_RESET_READ_DATAPATH, 0, 0);
1134
 
1135
                //USER On the write side the afi_wrank signal eventually propagates to the I/O 
1136
                //USER through the write datapath. We need to make sure we wait long enough for
1137
                //USER this to happen. The operations above should be enough, hence no extra delay
1138
                //USER inserted here.
1139
 
1140
                //USER Make sure the data in the I/O scan chains are in-sync with the register
1141
                //USER file inside the SCC manager. If we don't do this, a subsequent SCC_UPDATE
1142
                //USER may cause stale data for the other shadow register to be loaded. This must
1143
                //USER be done for every scan chain of the current group. Note that in shadow
1144
                //USER register mode, the SCC_UPDATE signal is per-group.
1145
                IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, group);
1146
 
1147
                IOWR_32DIRECT (SCC_MGR_DQS_ENA, 0, group);
1148
                IOWR_32DIRECT (SCC_MGR_DQS_IO_ENA, 0, 0);
1149
 
1150
                for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
1151
                        IOWR_32DIRECT (SCC_MGR_DQ_ENA, 0, i);
1152
                }
1153
                for (i = 0; i < RW_MGR_NUM_DM_PER_WRITE_GROUP; i++) {
1154
                        IOWR_32DIRECT (SCC_MGR_DM_ENA, 0, i);
1155
                }
1156
        }
1157
 
1158
        //USER Map the rank to its shadow reg
1159
        select_curr_shadow_reg_using_rank(rank);
1160
#endif
1161
}
1162
 
1163
#if HHP_HPS
1164
void scc_mgr_initialize(void)
1165
{
1166
        // Clear register file for HPS
1167
        // 16 (2^4) is the size of the full register file in the scc mgr:
1168
        //      RFILE_DEPTH = log2(MEM_DQ_PER_DQS + 1 + MEM_DM_PER_DQS + MEM_IF_READ_DQS_WIDTH - 1) + 1;
1169
        alt_u32 i;
1170
        for (i = 0; i < 16; i++) {
1171
                DPRINT(1, "Clearing SCC RFILE index %lu", i);
1172
                IOWR_32DIRECT(SCC_MGR_HHP_RFILE, i << 2, 0);
1173
        }
1174
}
1175
#endif
1176
 
1177
inline void scc_mgr_set_dqs_bus_in_delay(alt_u32 read_group, alt_u32 delay)
1178
{
1179
        ALTERA_ASSERT(read_group < RW_MGR_MEM_IF_READ_DQS_WIDTH);
1180
 
1181
        // Load the setting in the SCC manager
1182
        WRITE_SCC_DQS_IN_DELAY(read_group, delay);
1183
 
1184
        // Make the setting in the TCL report
1185
        TCLRPT_SET(debug_cal_report->cal_dqs_in_settings[curr_shadow_reg][read_group].dqs_bus_in_delay, delay);
1186
 
1187
}
1188
 
1189
static inline void scc_mgr_set_dqs_io_in_delay(alt_u32 write_group, alt_u32 delay)
1190
{
1191
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1192
 
1193
        // Load the setting in the SCC manager
1194
        WRITE_SCC_DQS_IO_IN_DELAY(delay);
1195
 
1196
        // Make the setting in the TCL report
1197
        TCLRPT_SET(debug_cal_report->cal_dqs_out_settings[curr_shadow_reg][write_group].dqs_io_in_delay, delay);
1198
 
1199
}
1200
 
1201
static inline void scc_mgr_set_dqs_en_phase(alt_u32 read_group, alt_u32 phase)
1202
{
1203
        ALTERA_ASSERT(read_group < RW_MGR_MEM_IF_READ_DQS_WIDTH);
1204
 
1205
        // Load the setting in the SCC manager
1206
        WRITE_SCC_DQS_EN_PHASE(read_group, phase);
1207
 
1208
        // Make the setting in the TCL report
1209
        TCLRPT_SET(debug_cal_report->cal_dqs_in_settings[curr_shadow_reg][read_group].dqs_en_phase, phase);
1210
 
1211
}
1212
 
1213
void scc_mgr_set_dqs_en_phase_all_ranks (alt_u32 read_group, alt_u32 phase)
1214
{
1215
        alt_u32 r;
1216
        alt_u32 update_scan_chains;
1217
 
1218
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
1219
                //USER although the h/w doesn't support different phases per shadow register,
1220
                //USER for simplicity our scc manager modeling keeps different phase settings per 
1221
                //USER shadow reg, and it's important for us to keep them in sync to match h/w.
1222
                //USER for efficiency, the scan chain update should occur only once to sr0.
1223
                update_scan_chains = (r == 0) ? 1 : 0;
1224
 
1225
                select_shadow_regs_for_update(r, read_group, update_scan_chains);
1226
                scc_mgr_set_dqs_en_phase(read_group, phase);
1227
 
1228
                if (update_scan_chains) {
1229
                        IOWR_32DIRECT (SCC_MGR_DQS_ENA, 0, read_group);
1230
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1231
                }
1232
        }
1233
}
1234
 
1235
 
1236
static inline void scc_mgr_set_dqdqs_output_phase(alt_u32 write_group, alt_u32 phase)
1237
{
1238
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1239
 
1240
        #if CALIBRATE_BIT_SLIPS
1241
        alt_u32 num_fr_slips = 0;
1242
        while (phase > IO_DQDQS_OUT_PHASE_MAX) {
1243
                phase -= IO_DLL_CHAIN_LENGTH;
1244
                num_fr_slips++;
1245
        }
1246
        IOWR_32DIRECT (PHY_MGR_FR_SHIFT, write_group*4, num_fr_slips);
1247
#endif
1248
 
1249
        // Load the setting in the SCC manager
1250
        WRITE_SCC_DQDQS_OUT_PHASE(write_group, phase);
1251
 
1252
        // Make the setting in the TCL report
1253
        TCLRPT_SET(debug_cal_report->cal_dqs_out_settings[curr_shadow_reg][write_group].dqdqs_out_phase, phase);
1254
 
1255
}
1256
 
1257
void scc_mgr_set_dqdqs_output_phase_all_ranks (alt_u32 write_group, alt_u32 phase)
1258
{
1259
        alt_u32 r;
1260
        alt_u32 update_scan_chains;
1261
 
1262
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
1263
                //USER although the h/w doesn't support different phases per shadow register,
1264
                //USER for simplicity our scc manager modeling keeps different phase settings per 
1265
                //USER shadow reg, and it's important for us to keep them in sync to match h/w.
1266
                //USER for efficiency, the scan chain update should occur only once to sr0.
1267
                update_scan_chains = (r == 0) ? 1 : 0;
1268
 
1269
                select_shadow_regs_for_update(r, write_group, update_scan_chains);
1270
                scc_mgr_set_dqdqs_output_phase(write_group, phase);
1271
 
1272
                if (update_scan_chains) {
1273
                        IOWR_32DIRECT (SCC_MGR_DQS_ENA, 0, write_group);
1274
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1275
                }
1276
        }
1277
}
1278
 
1279
 
1280
static inline void scc_mgr_set_dqs_en_delay(alt_u32 read_group, alt_u32 delay)
1281
{
1282
        ALTERA_ASSERT(read_group < RW_MGR_MEM_IF_READ_DQS_WIDTH);
1283
 
1284
        // Load the setting in the SCC manager
1285
        WRITE_SCC_DQS_EN_DELAY(read_group, delay);
1286
 
1287
        // Make the setting in the TCL report
1288
        TCLRPT_SET(debug_cal_report->cal_dqs_in_settings[curr_shadow_reg][read_group].dqs_en_delay, delay);
1289
 
1290
}
1291
 
1292
void scc_mgr_set_dqs_en_delay_all_ranks (alt_u32 read_group, alt_u32 delay)
1293
{
1294
        alt_u32 r;
1295
 
1296
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
1297
 
1298
                select_shadow_regs_for_update(r, read_group, 0);
1299
 
1300
                scc_mgr_set_dqs_en_delay(read_group, delay);
1301
 
1302
                IOWR_32DIRECT (SCC_MGR_DQS_ENA, 0, read_group);
1303
 
1304
#if !USE_SHADOW_REGS            
1305
                // In shadow register mode, the T11 settings are stored in registers
1306
                // in the core, which are updated by the DQS_ENA signals. Not issuing
1307
                // the SCC_MGR_UPD command allows us to save lots of rank switching
1308
                // overhead, by calling select_shadow_regs_for_update with update_scan_chains
1309
                // set to 0.
1310
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1311
#endif          
1312
        }
1313
}
1314
 
1315
static void scc_mgr_set_oct_out1_delay(alt_u32 write_group, alt_u32 delay)
1316
{
1317
        alt_u32 read_group;
1318
 
1319
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1320
 
1321
        // Load the setting in the SCC manager
1322
        // Although OCT affects only write data, the OCT delay is controlled by the DQS logic block
1323
        // which is instantiated once per read group. For protocols where a write group consists
1324
        // of multiple read groups, the setting must be set multiple times.
1325
        for (read_group = write_group * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH;
1326
                 read_group < (write_group + 1) * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH;
1327
                 ++read_group) {
1328
 
1329
                WRITE_SCC_OCT_OUT1_DELAY(read_group, delay);
1330
        }
1331
 
1332
        // Make the setting in the TCL report
1333
        TCLRPT_SET(debug_cal_report->cal_dqs_out_settings[curr_shadow_reg][write_group].oct_out_delay1, delay);
1334
 
1335
}
1336
 
1337
static void scc_mgr_set_oct_out2_delay(alt_u32 write_group, alt_u32 delay)
1338
{
1339
        alt_u32 read_group;
1340
 
1341
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1342
 
1343
        // Load the setting in the SCC manager
1344
        // Although OCT affects only write data, the OCT delay is controlled by the DQS logic block
1345
        // which is instantiated once per read group. For protocols where a write group consists
1346
        // of multiple read groups, the setting must be set multiple times.
1347
        for (read_group = write_group * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH;
1348
                 read_group < (write_group + 1) * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH;
1349
                 ++read_group) {
1350
 
1351
                WRITE_SCC_OCT_OUT2_DELAY(read_group, delay);
1352
        }
1353
 
1354
        // Make the setting in the TCL report
1355
        TCLRPT_SET(debug_cal_report->cal_dqs_out_settings[curr_shadow_reg][write_group].oct_out_delay2, delay);
1356
 
1357
}
1358
 
1359
static inline void scc_mgr_set_dqs_bypass(alt_u32 write_group, alt_u32 bypass)
1360
{
1361
        // Load the setting in the SCC manager
1362
        WRITE_SCC_DQS_BYPASS(write_group, bypass);
1363
}
1364
 
1365
inline void scc_mgr_set_dq_out1_delay(alt_u32 write_group, alt_u32 dq_in_group, alt_u32 delay)
1366
{
1367
#if ENABLE_TCL_DEBUG || ENABLE_ASSERT
1368
        alt_u32 dq = write_group*RW_MGR_MEM_DQ_PER_WRITE_DQS + dq_in_group;
1369
#endif
1370
 
1371
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1372
        ALTERA_ASSERT(dq < RW_MGR_MEM_DATA_WIDTH);
1373
 
1374
        // Load the setting in the SCC manager
1375
        WRITE_SCC_DQ_OUT1_DELAY(dq_in_group, delay);
1376
 
1377
        // Make the setting in the TCL report
1378
        TCLRPT_SET(debug_cal_report->cal_dq_settings[curr_shadow_reg][dq].dq_out_delay1, delay);
1379
 
1380
}
1381
 
1382
inline void scc_mgr_set_dq_out2_delay(alt_u32 write_group, alt_u32 dq_in_group, alt_u32 delay)
1383
{
1384
#if ENABLE_TCL_DEBUG || ENABLE_ASSERT
1385
        alt_u32 dq = write_group*RW_MGR_MEM_DQ_PER_WRITE_DQS + dq_in_group;
1386
#endif
1387
 
1388
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1389
        ALTERA_ASSERT(dq < RW_MGR_MEM_DATA_WIDTH);
1390
 
1391
        // Load the setting in the SCC manager
1392
        WRITE_SCC_DQ_OUT2_DELAY(dq_in_group, delay);
1393
 
1394
        // Make the setting in the TCL report
1395
        TCLRPT_SET(debug_cal_report->cal_dq_settings[curr_shadow_reg][dq].dq_out_delay2, delay);
1396
 
1397
}
1398
 
1399
inline void scc_mgr_set_dq_in_delay(alt_u32 write_group, alt_u32 dq_in_group, alt_u32 delay)
1400
{
1401
#if ENABLE_TCL_DEBUG || ENABLE_ASSERT
1402
        alt_u32 dq = write_group*RW_MGR_MEM_DQ_PER_WRITE_DQS + dq_in_group;
1403
#endif
1404
 
1405
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1406
        ALTERA_ASSERT(dq < RW_MGR_MEM_DATA_WIDTH);
1407
 
1408
        // Load the setting in the SCC manager
1409
        WRITE_SCC_DQ_IN_DELAY(dq_in_group, delay);
1410
 
1411
        // Make the setting in the TCL report
1412
        TCLRPT_SET(debug_cal_report->cal_dq_settings[curr_shadow_reg][dq].dq_in_delay, delay);
1413
 
1414
}
1415
 
1416
static inline void scc_mgr_set_dq_bypass(alt_u32 write_group, alt_u32 dq_in_group, alt_u32 bypass)
1417
{
1418
        // Load the setting in the SCC manager
1419
        WRITE_SCC_DQ_BYPASS(dq_in_group, bypass);
1420
}
1421
 
1422
static inline void scc_mgr_set_rfifo_mode(alt_u32 write_group, alt_u32 dq_in_group, alt_u32 mode)
1423
{
1424
        // Load the setting in the SCC manager
1425
        WRITE_SCC_RFIFO_MODE(dq_in_group, mode);
1426
}
1427
 
1428
static inline void scc_mgr_set_hhp_extras(void)
1429
{
1430
        // Load the fixed setting in the SCC manager
1431
        // bits: 0:0 = 1'b1   - dqs bypass
1432
        // bits: 1:1 = 1'b1   - dq bypass
1433
        // bits: 4:2 = 3'b001   - rfifo_mode
1434
        // bits: 6:5 = 2'b01  - rfifo clock_select
1435
        // bits: 7:7 = 1'b0  - separate gating from ungating setting
1436
        // bits: 8:8 = 1'b0  - separate OE from Output delay setting
1437
        alt_u32 value = (0<<8) | (0<<7) | (1<<5) | (1<<2) | (1<<1) | (1<<0);
1438
        WRITE_SCC_HHP_EXTRAS(value);
1439
}
1440
 
1441
static inline void scc_mgr_set_hhp_dqse_map(void)
1442
{
1443
        // Load the fixed setting in the SCC manager
1444
        WRITE_SCC_HHP_DQSE_MAP(0);
1445
}
1446
 
1447
static inline void scc_mgr_set_dqs_out1_delay(alt_u32 write_group, alt_u32 delay)
1448
{
1449
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1450
 
1451
        // Load the setting in the SCC manager
1452
        WRITE_SCC_DQS_IO_OUT1_DELAY(delay);
1453
 
1454
        // Make the setting in the TCL report
1455
        TCLRPT_SET(debug_cal_report->cal_dqs_out_settings[curr_shadow_reg][write_group].dqs_out_delay1, delay);
1456
 
1457
}
1458
 
1459
static inline void scc_mgr_set_dqs_out2_delay(alt_u32 write_group, alt_u32 delay)
1460
{
1461
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1462
 
1463
        // Load the setting in the SCC manager
1464
        WRITE_SCC_DQS_IO_OUT2_DELAY(delay);
1465
 
1466
        // Make the setting in the TCL report
1467
        TCLRPT_SET(debug_cal_report->cal_dqs_out_settings[curr_shadow_reg][write_group].dqs_out_delay2, delay);
1468
 
1469
}
1470
 
1471
inline void scc_mgr_set_dm_out1_delay(alt_u32 write_group, alt_u32 dm, alt_u32 delay)
1472
{
1473
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1474
        ALTERA_ASSERT(dm < RW_MGR_NUM_DM_PER_WRITE_GROUP);
1475
 
1476
        // Load the setting in the SCC manager
1477
        WRITE_SCC_DM_IO_OUT1_DELAY(dm, delay);
1478
 
1479
        // Make the setting in the TCL report
1480
 
1481
        if (RW_MGR_NUM_TRUE_DM_PER_WRITE_GROUP > 0)
1482
        {
1483
                TCLRPT_SET(debug_cal_report->cal_dm_settings[curr_shadow_reg][write_group][dm].dm_out_delay1, delay);
1484
        }
1485
}
1486
 
1487
inline void scc_mgr_set_dm_out2_delay(alt_u32 write_group, alt_u32 dm, alt_u32 delay)
1488
{
1489
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1490
        ALTERA_ASSERT(dm < RW_MGR_NUM_DM_PER_WRITE_GROUP);
1491
 
1492
        // Load the setting in the SCC manager
1493
        WRITE_SCC_DM_IO_OUT2_DELAY(dm, delay);
1494
 
1495
        // Make the setting in the TCL report
1496
 
1497
        if (RW_MGR_NUM_TRUE_DM_PER_WRITE_GROUP > 0)
1498
        {
1499
                TCLRPT_SET(debug_cal_report->cal_dm_settings[curr_shadow_reg][write_group][dm].dm_out_delay2, delay);
1500
        }
1501
}
1502
 
1503
static inline void scc_mgr_set_dm_in_delay(alt_u32 write_group, alt_u32 dm, alt_u32 delay)
1504
{
1505
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
1506
        ALTERA_ASSERT(dm < RW_MGR_NUM_DM_PER_WRITE_GROUP);
1507
 
1508
        // Load the setting in the SCC manager
1509
        WRITE_SCC_DM_IO_IN_DELAY(dm, delay);
1510
 
1511
        // Make the setting in the TCL report
1512
 
1513
        if (RW_MGR_NUM_TRUE_DM_PER_WRITE_GROUP > 0)
1514
        {
1515
                TCLRPT_SET(debug_cal_report->cal_dm_settings[curr_shadow_reg][write_group][dm].dm_in_delay, delay);
1516
        }
1517
}
1518
 
1519
static inline void scc_mgr_set_dm_bypass(alt_u32 write_group, alt_u32 dm, alt_u32 bypass)
1520
{
1521
        // Load the setting in the SCC manager
1522
        WRITE_SCC_DM_BYPASS(dm, bypass);
1523
}
1524
 
1525
//USER Zero all DQS config
1526
// TODO: maybe rename to scc_mgr_zero_dqs_config (or something)
1527
void scc_mgr_zero_all (void)
1528
{
1529
        alt_u32 i, r;
1530
 
1531
        //USER Zero all DQS config settings, across all groups and all shadow registers
1532
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
1533
 
1534
                // Strictly speaking this should be called once per group to make
1535
                // sure each group's delay chain is refreshed from the SCC register file,
1536
                // but since we're resetting all delay chains anyway, we can save some
1537
                // runtime by calling select_shadow_regs_for_update just once to switch
1538
                // rank.
1539
                select_shadow_regs_for_update(r, 0, 1);
1540
 
1541
                for (i = 0; i < RW_MGR_MEM_IF_READ_DQS_WIDTH; i++) {
1542
                        // The phases actually don't exist on a per-rank basis, but there's
1543
                        // no harm updating them several times, so let's keep the code simple.
1544
                        scc_mgr_set_dqs_bus_in_delay(i, IO_DQS_IN_RESERVE);
1545
                        scc_mgr_set_dqs_en_phase(i, 0);
1546
                        scc_mgr_set_dqs_en_delay(i, 0);
1547
                }
1548
 
1549
                for (i = 0; i < RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
1550
                        scc_mgr_set_dqdqs_output_phase(i, 0);
1551
#if ARRIAV || CYCLONEV
1552
                        // av/cv don't have out2
1553
                        scc_mgr_set_oct_out1_delay(i, IO_DQS_OUT_RESERVE);
1554
#else
1555
                        scc_mgr_set_oct_out1_delay(i, 0);
1556
                        scc_mgr_set_oct_out2_delay(i, IO_DQS_OUT_RESERVE);
1557
#endif
1558
                }
1559
 
1560
                //USER multicast to all DQS group enables
1561
                IOWR_32DIRECT (SCC_MGR_DQS_ENA, 0, 0xff);
1562
 
1563
#if USE_SHADOW_REGS             
1564
                //USER in shadow-register mode, SCC_UPDATE is done on a per-group basis
1565
                //USER unless we explicitly ask for a multicast via the group counter
1566
                IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, 0xFF);
1567
#endif          
1568
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1569
        }
1570
}
1571
 
1572
void scc_set_bypass_mode(alt_u32 write_group, alt_u32 mode)
1573
{
1574
        // mode = 0 : Do NOT bypass - Half Rate Mode
1575
        // mode = 1 : Bypass - Full Rate Mode
1576
 
1577
#if !HHP_HPS
1578
        alt_u32 i;
1579
#endif
1580
 
1581
#if HHP_HPS
1582
        // only need to set once for all groups, pins, dq, dqs, dm
1583
        if (write_group == 0) {
1584
                DPRINT(1, "Setting HHP Extras");
1585
                scc_mgr_set_hhp_extras();
1586
                DPRINT(1, "Done Setting HHP Extras");
1587
        }
1588
#endif
1589
 
1590
#if !HHP_HPS
1591
        for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++)
1592
        {
1593
                scc_mgr_set_dq_bypass(write_group, i, mode);
1594
                scc_mgr_set_rfifo_mode(write_group, i, mode);
1595
        }
1596
#endif
1597
 
1598
        //USER multicast to all DQ enables 
1599
        IOWR_32DIRECT (SCC_MGR_DQ_ENA, 0, 0xff);
1600
 
1601
#if !HHP_HPS
1602
        for (i = 0; i < RW_MGR_NUM_DM_PER_WRITE_GROUP; i++)
1603
        {
1604
                scc_mgr_set_dm_bypass(write_group, i, mode);
1605
        }
1606
#endif
1607
 
1608
        IOWR_32DIRECT (SCC_MGR_DM_ENA, 0, 0xff);
1609
 
1610
#if !HHP_HPS
1611
        scc_mgr_set_dqs_bypass(write_group, mode);
1612
#endif
1613
 
1614
        //USER update current DQS IO enable
1615
        IOWR_32DIRECT (SCC_MGR_DQS_IO_ENA, 0, 0);
1616
 
1617
        //USER update the DQS logic
1618
        IOWR_32DIRECT (SCC_MGR_DQS_ENA, 0, write_group);
1619
 
1620
        //USER hit update
1621
        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1622
}
1623
 
1624
// Moving up to avoid warnings
1625
void scc_mgr_load_dqs_for_write_group (alt_u32 write_group)
1626
{
1627
        alt_u32 read_group;
1628
 
1629
        // Although OCT affects only write data, the OCT delay is controlled by the DQS logic block
1630
        // which is instantiated once per read group. For protocols where a write group consists
1631
        // of multiple read groups, the setting must be scanned multiple times.
1632
        for (read_group = write_group * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH;
1633
                 read_group < (write_group + 1) * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH;
1634
                 ++read_group) {
1635
 
1636
                IOWR_32DIRECT (SCC_MGR_DQS_ENA, 0, read_group);
1637
        }
1638
}
1639
 
1640
void scc_mgr_zero_group (alt_u32 write_group, alt_u32 test_begin, alt_32 out_only)
1641
{
1642
        alt_u32 i, r;
1643
 
1644
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
1645
 
1646
                select_shadow_regs_for_update(r, write_group, 1);
1647
 
1648
                //USER Zero all DQ config settings
1649
                for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++)
1650
                {
1651
                        scc_mgr_set_dq_out1_delay(write_group, i, 0);
1652
                        scc_mgr_set_dq_out2_delay(write_group, i, IO_DQ_OUT_RESERVE);
1653
                        if (!out_only) {
1654
                                scc_mgr_set_dq_in_delay(write_group, i, 0);
1655
                        }
1656
                }
1657
 
1658
                //USER multicast to all DQ enables
1659
                IOWR_32DIRECT (SCC_MGR_DQ_ENA, 0, 0xff);
1660
 
1661
                //USER Zero all DM config settings 
1662
                for (i = 0; i < RW_MGR_NUM_DM_PER_WRITE_GROUP; i++)
1663
                {
1664
                        if (!out_only) {
1665
                                // Do we really need this?
1666
                                scc_mgr_set_dm_in_delay(write_group, i, 0);
1667
                        }
1668
                        scc_mgr_set_dm_out1_delay(write_group, i, 0);
1669
                        scc_mgr_set_dm_out2_delay(write_group, i, IO_DM_OUT_RESERVE);
1670
                }
1671
 
1672
                //USER multicast to all DM enables
1673
                IOWR_32DIRECT (SCC_MGR_DM_ENA, 0, 0xff);
1674
 
1675
                //USER zero all DQS io settings 
1676
                if (!out_only) {
1677
                        scc_mgr_set_dqs_io_in_delay(write_group, 0);
1678
                }
1679
#if ARRIAV || CYCLONEV
1680
                // av/cv don't have out2
1681
                scc_mgr_set_dqs_out1_delay(write_group, IO_DQS_OUT_RESERVE);
1682
                scc_mgr_set_oct_out1_delay(write_group, IO_DQS_OUT_RESERVE);
1683
                scc_mgr_load_dqs_for_write_group (write_group);
1684
#else
1685
                scc_mgr_set_dqs_out1_delay(write_group, 0);
1686
                scc_mgr_set_dqs_out2_delay(write_group, IO_DQS_OUT_RESERVE);
1687
                scc_mgr_set_oct_out1_delay(write_group, 0);
1688
                scc_mgr_set_oct_out2_delay(write_group, IO_DQS_OUT_RESERVE);
1689
                scc_mgr_load_dqs_for_write_group (write_group);
1690
#endif
1691
 
1692
                //USER multicast to all DQS IO enables (only 1)
1693
                IOWR_32DIRECT (SCC_MGR_DQS_IO_ENA, 0, 0);
1694
 
1695
#if USE_SHADOW_REGS             
1696
                //USER in shadow-register mode, SCC_UPDATE is done on a per-group basis
1697
                //USER unless we explicitly ask for a multicast via the group counter
1698
                IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, 0xFF);
1699
#endif                          
1700
                //USER hit update to zero everything 
1701
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1702
        }
1703
}
1704
 
1705
//USER load up dqs config settings 
1706
 
1707
void scc_mgr_load_dqs (alt_u32 dqs)
1708
{
1709
        IOWR_32DIRECT (SCC_MGR_DQS_ENA, 0, dqs);
1710
}
1711
 
1712
 
1713
//USER load up dqs io config settings 
1714
 
1715
void scc_mgr_load_dqs_io (void)
1716
{
1717
        IOWR_32DIRECT (SCC_MGR_DQS_IO_ENA, 0, 0);
1718
}
1719
 
1720
//USER load up dq config settings 
1721
 
1722
void scc_mgr_load_dq (alt_u32 dq_in_group)
1723
{
1724
        IOWR_32DIRECT (SCC_MGR_DQ_ENA, 0, dq_in_group);
1725
}
1726
 
1727
//USER load up dm config settings 
1728
 
1729
void scc_mgr_load_dm (alt_u32 dm)
1730
{
1731
        IOWR_32DIRECT (SCC_MGR_DM_ENA, 0, dm);
1732
}
1733
 
1734
//USER apply and load a particular input delay for the DQ pins in a group
1735
//USER group_bgn is the index of the first dq pin (in the write group)
1736
 
1737
void scc_mgr_apply_group_dq_in_delay (alt_u32 write_group, alt_u32 group_bgn, alt_u32 delay)
1738
{
1739
        alt_u32 i, p;
1740
 
1741
        for (i = 0, p = group_bgn; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++, p++) {
1742
                scc_mgr_set_dq_in_delay(write_group, p, delay);
1743
                scc_mgr_load_dq (p);
1744
        }
1745
}
1746
 
1747
//USER apply and load a particular output delay for the DQ pins in a group
1748
 
1749
void scc_mgr_apply_group_dq_out1_delay (alt_u32 write_group, alt_u32 group_bgn, alt_u32 delay1)
1750
{
1751
        alt_u32 i, p;
1752
 
1753
        for (i = 0, p = group_bgn; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++, p++) {
1754
                scc_mgr_set_dq_out1_delay(write_group, i, delay1);
1755
                scc_mgr_load_dq (i);
1756
        }
1757
}
1758
 
1759
void scc_mgr_apply_group_dq_out2_delay (alt_u32 write_group, alt_u32 group_bgn, alt_u32 delay2)
1760
{
1761
        alt_u32 i, p;
1762
 
1763
        for (i = 0, p = group_bgn; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++, p++) {
1764
                scc_mgr_set_dq_out2_delay(write_group, i, delay2);
1765
                scc_mgr_load_dq (i);
1766
        }
1767
}
1768
 
1769
//USER apply and load a particular output delay for the DM pins in a group
1770
 
1771
void scc_mgr_apply_group_dm_out1_delay (alt_u32 write_group, alt_u32 delay1)
1772
{
1773
        alt_u32 i;
1774
 
1775
        for (i = 0; i < RW_MGR_NUM_DM_PER_WRITE_GROUP; i++) {
1776
                scc_mgr_set_dm_out1_delay(write_group, i, delay1);
1777
                scc_mgr_load_dm (i);
1778
        }
1779
}
1780
 
1781
 
1782
//USER apply and load delay on both DQS and OCT out1
1783
void scc_mgr_apply_group_dqs_io_and_oct_out1 (alt_u32 write_group, alt_u32 delay)
1784
{
1785
        scc_mgr_set_dqs_out1_delay(write_group, delay);
1786
        scc_mgr_load_dqs_io ();
1787
 
1788
        scc_mgr_set_oct_out1_delay(write_group, delay);
1789
        scc_mgr_load_dqs_for_write_group (write_group);
1790
}
1791
 
1792
//USER apply and load delay on both DQS and OCT out2
1793
void scc_mgr_apply_group_dqs_io_and_oct_out2 (alt_u32 write_group, alt_u32 delay)
1794
{
1795
        scc_mgr_set_dqs_out2_delay(write_group, delay);
1796
        scc_mgr_load_dqs_io ();
1797
 
1798
        scc_mgr_set_oct_out2_delay(write_group, delay);
1799
        scc_mgr_load_dqs_for_write_group (write_group);
1800
}
1801
 
1802
//USER set delay on both DQS and OCT out1 by incrementally changing
1803
//USER the settings one dtap at a time towards the target value, to avoid
1804
//USER breaking the lock of the DLL/PLL on the memory device.
1805
void scc_mgr_set_group_dqs_io_and_oct_out1_gradual (alt_u32 write_group, alt_u32 delay)
1806
{
1807
        alt_u32 d = READ_SCC_DQS_IO_OUT1_DELAY();
1808
 
1809
        while (d > delay) {
1810
                --d;
1811
                scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, d);
1812
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1813
                if (QDRII)
1814
                {
1815
                        rw_mgr_mem_dll_lock_wait();
1816
                }
1817
        }
1818
        while (d < delay) {
1819
                ++d;
1820
                scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, d);
1821
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1822
                if (QDRII)
1823
                {
1824
                        rw_mgr_mem_dll_lock_wait();
1825
                }
1826
        }
1827
}
1828
 
1829
//USER set delay on both DQS and OCT out2 by incrementally changing
1830
//USER the settings one dtap at a time towards the target value, to avoid
1831
//USER breaking the lock of the DLL/PLL on the memory device.
1832
void scc_mgr_set_group_dqs_io_and_oct_out2_gradual (alt_u32 write_group, alt_u32 delay)
1833
{
1834
        alt_u32 d = READ_SCC_DQS_IO_OUT2_DELAY();
1835
 
1836
        while (d > delay) {
1837
                --d;
1838
                scc_mgr_apply_group_dqs_io_and_oct_out2 (write_group, d);
1839
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1840
                if (QDRII)
1841
                {
1842
                        rw_mgr_mem_dll_lock_wait();
1843
                }
1844
        }
1845
        while (d < delay) {
1846
                ++d;
1847
                scc_mgr_apply_group_dqs_io_and_oct_out2 (write_group, d);
1848
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1849
                if (QDRII)
1850
                {
1851
                        rw_mgr_mem_dll_lock_wait();
1852
                }
1853
        }
1854
}
1855
 
1856
//USER apply a delay to the entire output side: DQ, DM, DQS, OCT 
1857
 
1858
void scc_mgr_apply_group_all_out_delay (alt_u32 write_group, alt_u32 group_bgn, alt_u32 delay)
1859
{
1860
        //USER dq shift 
1861
 
1862
        scc_mgr_apply_group_dq_out1_delay (write_group, group_bgn, delay);
1863
 
1864
        //USER dm shift 
1865
 
1866
        scc_mgr_apply_group_dm_out1_delay (write_group, delay);
1867
 
1868
        //USER dqs and oct shift 
1869
 
1870
        scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, delay);
1871
}
1872
 
1873
//USER apply a delay to the entire output side (DQ, DM, DQS, OCT) and to all ranks
1874
void scc_mgr_apply_group_all_out_delay_all_ranks (alt_u32 write_group, alt_u32 group_bgn, alt_u32 delay)
1875
{
1876
        alt_u32 r;
1877
 
1878
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
1879
 
1880
                select_shadow_regs_for_update(r, write_group, 1);
1881
 
1882
                scc_mgr_apply_group_all_out_delay (write_group, group_bgn, delay);
1883
 
1884
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1885
        }
1886
}
1887
 
1888
//USER apply a delay to the entire output side: DQ, DM, DQS, OCT 
1889
 
1890
void scc_mgr_apply_group_all_out_delay_add (alt_u32 write_group, alt_u32 group_bgn, alt_u32 delay)
1891
{
1892
        alt_u32 i, p, new_delay;
1893
 
1894
        //USER dq shift 
1895
 
1896
        for (i = 0, p = group_bgn; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++, p++) {
1897
 
1898
                new_delay = READ_SCC_DQ_OUT2_DELAY(i);
1899
                new_delay += delay;
1900
 
1901
                if (new_delay > IO_IO_OUT2_DELAY_MAX) {
1902
                        DPRINT(1, "%s(%lu, %lu, %lu) DQ[%lu,%lu]: %lu > %lu => %lu",
1903
                               __func__, write_group, group_bgn, delay, i, p,
1904
                               new_delay, (long unsigned int)IO_IO_OUT2_DELAY_MAX, (long unsigned int)IO_IO_OUT2_DELAY_MAX);
1905
                        new_delay = IO_IO_OUT2_DELAY_MAX;
1906
                }
1907
 
1908
                scc_mgr_set_dq_out2_delay(write_group, i, new_delay);
1909
                scc_mgr_load_dq (i);
1910
        }
1911
 
1912
        //USER dm shift 
1913
 
1914
        for (i = 0; i < RW_MGR_NUM_DM_PER_WRITE_GROUP; i++) {
1915
                new_delay = READ_SCC_DM_IO_OUT2_DELAY(i);
1916
                new_delay += delay;
1917
 
1918
                if (new_delay > IO_IO_OUT2_DELAY_MAX) {
1919
                        DPRINT(1, "%s(%lu, %lu, %lu) DM[%lu]: %lu > %lu => %lu",
1920
                               __func__, write_group, group_bgn, delay, i,
1921
                               new_delay, (long unsigned int)IO_IO_OUT2_DELAY_MAX, (long unsigned int)IO_IO_OUT2_DELAY_MAX);
1922
                        new_delay = IO_IO_OUT2_DELAY_MAX;
1923
                }
1924
 
1925
                scc_mgr_set_dm_out2_delay(write_group, i, new_delay);
1926
                scc_mgr_load_dm (i);
1927
        }
1928
 
1929
        //USER dqs shift 
1930
 
1931
        new_delay = READ_SCC_DQS_IO_OUT2_DELAY();
1932
        new_delay += delay;
1933
 
1934
        if (new_delay > IO_IO_OUT2_DELAY_MAX) {
1935
                DPRINT(1, "%s(%lu, %lu, %lu) DQS: %lu > %d => %d; adding %lu to OUT1",
1936
                       __func__, write_group, group_bgn, delay,
1937
                       new_delay, IO_IO_OUT2_DELAY_MAX, IO_IO_OUT2_DELAY_MAX,
1938
                        new_delay - IO_IO_OUT2_DELAY_MAX);
1939
                scc_mgr_set_dqs_out1_delay(write_group, new_delay - IO_IO_OUT2_DELAY_MAX);
1940
                new_delay = IO_IO_OUT2_DELAY_MAX;
1941
        }
1942
 
1943
        scc_mgr_set_dqs_out2_delay(write_group, new_delay);
1944
        scc_mgr_load_dqs_io ();
1945
 
1946
        //USER oct shift 
1947
 
1948
        new_delay = READ_SCC_OCT_OUT2_DELAY(write_group);
1949
        new_delay += delay;
1950
 
1951
        if (new_delay > IO_IO_OUT2_DELAY_MAX) {
1952
                DPRINT(1, "%s(%lu, %lu, %lu) DQS: %lu > %d => %d; adding %lu to OUT1",
1953
                       __func__, write_group, group_bgn, delay,
1954
                       new_delay, IO_IO_OUT2_DELAY_MAX, IO_IO_OUT2_DELAY_MAX,
1955
                        new_delay - IO_IO_OUT2_DELAY_MAX);
1956
                scc_mgr_set_oct_out1_delay(write_group, new_delay - IO_IO_OUT2_DELAY_MAX);
1957
                new_delay = IO_IO_OUT2_DELAY_MAX;
1958
        }
1959
 
1960
        scc_mgr_set_oct_out2_delay(write_group, new_delay);
1961
        scc_mgr_load_dqs_for_write_group (write_group);
1962
}
1963
 
1964
//USER apply a delay to the entire output side (DQ, DM, DQS, OCT) and to all ranks
1965
void scc_mgr_apply_group_all_out_delay_add_all_ranks (alt_u32 write_group, alt_u32 group_bgn, alt_u32 delay)
1966
{
1967
        alt_u32 r;
1968
 
1969
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
1970
 
1971
                select_shadow_regs_for_update(r, write_group, 1);
1972
 
1973
                scc_mgr_apply_group_all_out_delay_add (write_group, group_bgn, delay);
1974
 
1975
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
1976
        }
1977
}
1978
 
1979
static inline void scc_mgr_spread_out2_delay_all_ranks (alt_u32 write_group, alt_u32 test_bgn)
1980
{
1981
#if STRATIXV || ARRIAVGZ
1982
        alt_u32 found;
1983
        alt_u32 i;
1984
        alt_u32 p;
1985
        alt_u32 d;
1986
        alt_u32 r;
1987
 
1988
        const alt_u32 delay_step = IO_IO_OUT2_DELAY_MAX/(RW_MGR_MEM_DQ_PER_WRITE_DQS-1); /* we start at zero, so have one less dq to devide among */
1989
 
1990
        TRACE_FUNC("(%lu,%lu)", write_group, test_bgn);
1991
 
1992
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
1993
                select_shadow_regs_for_update(r, write_group, 1);
1994
                for (i = 0, p = test_bgn, d = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++, p++, d += delay_step) {
1995
                        DPRINT(1, "rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase_sweep_dq_in_delay: g=%lu r=%lu, i=%lu p=%lu d=%lu",
1996
                               write_group, r, i, p, d);
1997
                        scc_mgr_set_dq_out2_delay(write_group, i, d);
1998
                        scc_mgr_load_dq (i);
1999
                }
2000
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
2001
        }
2002
#endif
2003
}
2004
 
2005
#if DDR3
2006
// optimization used to recover some slots in ddr3 inst_rom
2007
// could be applied to other protocols if we wanted to
2008
void set_jump_as_return(void)
2009
{
2010
        // to save space, we replace return with jump to special shared RETURN instruction
2011
        // so we set the counter to large value so that we always jump
2012
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0xFF);
2013
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_RETURN);
2014
 
2015
}
2016
#endif
2017
 
2018
// should always use constants as argument to ensure all computations are performed at compile time
2019
static inline void delay_for_n_mem_clocks(const alt_u32 clocks)
2020
{
2021
        alt_u32 afi_clocks;
2022
        alt_u8 inner;
2023
        alt_u8 outer;
2024
        alt_u16 c_loop;
2025
 
2026
        TRACE_FUNC("clocks=%lu ... start", clocks);
2027
 
2028
        afi_clocks = (clocks + AFI_RATE_RATIO-1) / AFI_RATE_RATIO; /* scale (rounding up) to get afi clocks */
2029
 
2030
        // Note, we don't bother accounting for being off a little bit because of a few extra instructions in outer loops
2031
        // Note, the loops have a test at the end, and do the test before the decrement, and so always perform the loop
2032
        // 1 time more than the counter value
2033
        if (afi_clocks == 0) {
2034
                inner = outer = c_loop = 0;
2035
        } else if (afi_clocks <= 0x100) {
2036
                inner = afi_clocks-1;
2037
                outer = 0;
2038
                c_loop = 0;
2039
        } else if (afi_clocks <= 0x10000) {
2040
                inner = 0xff;
2041
                outer = (afi_clocks-1) >> 8;
2042
                c_loop = 0;
2043
        } else {
2044
                inner = 0xff;
2045
                outer = 0xff;
2046
                c_loop = (afi_clocks-1) >> 16;
2047
        }
2048
 
2049
        // rom instructions are structured as follows:
2050
        //
2051
        //    IDLE_LOOP2: jnz cntr0, TARGET_A
2052
        //    IDLE_LOOP1: jnz cntr1, TARGET_B
2053
        //                return
2054
        //
2055
        // so, when doing nested loops, TARGET_A is set to IDLE_LOOP2, and TARGET_B is
2056
        // set to IDLE_LOOP2 as well
2057
        //
2058
        // if we have no outer loop, though, then we can use IDLE_LOOP1 only, and set
2059
        // TARGET_B to IDLE_LOOP1 and we skip IDLE_LOOP2 entirely
2060
        //
2061
        // a little confusing, but it helps save precious space in the inst_rom and sequencer rom
2062
        // and keeps the delays more accurate and reduces overhead
2063
        if (afi_clocks <= 0x100) {
2064
 
2065
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(inner));
2066
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_IDLE_LOOP1);
2067
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_IDLE_LOOP1);
2068
 
2069
        } else {
2070
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(inner));
2071
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(outer));
2072
 
2073
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_IDLE_LOOP2);
2074
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_IDLE_LOOP2);
2075
 
2076
                // hack to get around compiler not being smart enough
2077
                if (afi_clocks <= 0x10000) {
2078
                        // only need to run once
2079
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_IDLE_LOOP2);
2080
                } else {
2081
                        do {
2082
                                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_IDLE_LOOP2);
2083
                        } while (c_loop-- != 0);
2084
                }
2085
        }
2086
 
2087
        TRACE_FUNC("clocks=%lu ... end", clocks);
2088
}
2089
 
2090
// should always use constants as argument to ensure all computations are performed at compile time
2091
static inline void delay_for_n_ns(const alt_u32 nanoseconds)
2092
{
2093
        TRACE_FUNC("nanoseconds=%lu ... end", nanoseconds);
2094
        delay_for_n_mem_clocks((1000*nanoseconds) / (1000000/AFI_CLK_FREQ) * AFI_RATE_RATIO);
2095
}
2096
 
2097
#if RLDRAM3
2098
// Special routine to recover memory device from illegal state after
2099
// ck/dk relationship is potentially violated.
2100
static inline void recover_mem_device_after_ck_dqs_violation(void)
2101
{
2102
        //USER Issue MRS0 command. For some reason this is required once we
2103
        //USER violate tCKDK. Without this all subsequent write tests will fail
2104
        //USER even with known good delays.
2105
 
2106
   //USER Load MR0
2107
        if ( RW_MGR_MEM_NUMBER_OF_RANKS == 1 ) {
2108
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFE);
2109
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0);
2110
        } else if ( RW_MGR_MEM_NUMBER_OF_RANKS == 2 ) {
2111
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFC);
2112
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0);
2113
        } else if ( RW_MGR_MEM_NUMBER_OF_RANKS == 4 ) {
2114
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFC);
2115
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0);
2116
                //USER Wait MRSC
2117
                delay_for_n_mem_clocks(12);
2118
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xF3);
2119
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_QUAD_RANK);
2120
        }
2121
        else {
2122
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFE);
2123
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0);
2124
        }
2125
 
2126
        //USER Wait MRSC
2127
        delay_for_n_mem_clocks(12);
2128
}
2129
#else
2130
// Special routine to recover memory device from illegal state after
2131
// ck/dqs relationship is violated.
2132
static inline void recover_mem_device_after_ck_dqs_violation(void)
2133
{
2134
        // Current protocol doesn't require any special recovery
2135
}
2136
#endif
2137
 
2138
#if (LRDIMM && DDR3)
2139
// Routine to program specific LRDIMM control words.
2140
static void rw_mgr_lrdimm_rc_program(alt_u32 fscw, alt_u32 rc_addr, alt_u32 rc_val)
2141
{
2142
        alt_u32 i;
2143
        const alt_u32 AC_BASE_CONTENT = __RW_MGR_CONTENT_ac_rdimm;
2144
        //USER These values should be dynamically loaded instead of hard-coded
2145
        const alt_u32 AC_ADDRESS_POSITION = 0x0;
2146
        const alt_u32 AC_BANK_ADDRESS_POSITION = 0xD;
2147
        alt_u32 ac_content;
2148
        alt_u32 lrdimm_cs_msk = RW_MGR_RANK_NONE;
2149
 
2150
        TRACE_FUNC();
2151
 
2152
        //USER Turn on only CS0 and CS1 for each DIMM.
2153
        for (i = 0; i < RW_MGR_MEM_CHIP_SELECT_WIDTH; i+= RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM)
2154
        {
2155
                lrdimm_cs_msk &= (~(3 << i));
2156
        }
2157
 
2158
        IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, lrdimm_cs_msk);
2159
 
2160
        // Program the fscw first (RC7), followed by the actual value
2161
        for (i = 0; i < 2; i++)
2162
        {
2163
                alt_u32 addr;
2164
                alt_u32 val;
2165
 
2166
                addr = (i == 0) ? 7 : rc_addr;
2167
                val = (i == 0) ? fscw : rc_val;
2168
 
2169
                ac_content =
2170
                        AC_BASE_CONTENT |
2171
                        //USER Word address
2172
                        ((addr & 0x7) << AC_ADDRESS_POSITION) |
2173
                        (((addr >> 3) & 0x1) << (AC_BANK_ADDRESS_POSITION + 2)) |
2174
                        //USER Configuration Word
2175
                        (((val >> 2) & 0x3) << (AC_BANK_ADDRESS_POSITION)) |
2176
                        ((val & 0x3) << (AC_ADDRESS_POSITION + 3));
2177
 
2178
                //USER Override the AC row with the RDIMM command
2179
                IOWR_32DIRECT(BASE_RW_MGR, 0x1C00 + (__RW_MGR_ac_rdimm << 2), ac_content);
2180
 
2181
                set_jump_as_return();
2182
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_RDIMM_CMD);
2183
        }
2184
 
2185
        // USER The following registers require a delay of tSTAB (6us) for proper functionality.
2186
        // USER F0RC2, F0RC10, F0RC11, F1RC8, F1RC11-F1RC15
2187
        // USER Note that it is only necessary to wait tSTAB after all of these
2188
        // USER control words have been written, not after each one. Only F0RC0-F0RC15
2189
        // USER are guaranteed to be written (and in order), but F1* are not so
2190
        // USER wait after each.
2191
        if (    ((fscw == 0) && ((rc_addr==2) || (rc_addr==10) || (rc_addr==11)))
2192
                  || ((fscw == 1) && (rc_addr >= 8)))
2193
        {
2194
                delay_for_n_ns(6000);
2195
        }
2196
}
2197
#endif
2198
#if (RDIMM || LRDIMM) && DDR3
2199
void rw_mgr_rdimm_initialize(void)
2200
{
2201
        alt_u32 i;
2202
        alt_u32 conf_word;
2203
#if RDIMM
2204
        const alt_u32 AC_BASE_CONTENT = __RW_MGR_CONTENT_ac_rdimm;
2205
        //USER These values should be dynamically loaded instead of hard-coded
2206
        const alt_u32 AC_ADDRESS_POSITION = 0x0;
2207
        const alt_u32 AC_BANK_ADDRESS_POSITION = 0xD;
2208
        alt_u32 ac_content;
2209
#endif
2210
 
2211
        TRACE_FUNC();
2212
 
2213
        //USER RDIMM registers are programmed by writing 16 configuration words
2214
        //USER 1. An RDIMM command is a NOP with all CS asserted
2215
        //USER 2. The 4-bit address of the configuration words is 
2216
        //USER    * { mem_ba[2] , mem_a[2] , mem_a[1] , mem_a[0] }
2217
        //USER 3. The 4-bit configuration word is
2218
        //USER    * { mem_ba[1] , mem_ba[0] , mem_a[4] , mem_a[3] }
2219
 
2220
#if RDIMM
2221
        //USER Turn on all ranks
2222
        IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, RW_MGR_RANK_ALL);
2223
#endif
2224
 
2225
        for(i = 0; i < 16; i++)
2226
        {
2227
 
2228
 
2229
                if(i < 8)
2230
                {
2231
#if ENABLE_TCL_DEBUG && USE_USER_RDIMM_VALUE
2232
                        conf_word = (my_debug_data.command_parameters[0] >> (i * 4)) & 0xF;
2233
#else                   
2234
                        conf_word = (RDIMM_CONFIG_WORD_LOW >> (i * 4)) & 0xF;
2235
#endif                  
2236
                }
2237
                else
2238
                {
2239
#if ENABLE_TCL_DEBUG && USE_USER_RDIMM_VALUE    
2240
                        conf_word = (my_debug_data.command_parameters[1] >> ((i - 8) * 4)) & 0xF;
2241
#else                   
2242
                        conf_word = (RDIMM_CONFIG_WORD_HIGH >> ((i - 8) * 4)) & 0xF;
2243
#endif          
2244
                }
2245
 
2246
#if RDIMM
2247
                ac_content =
2248
                        AC_BASE_CONTENT |
2249
                        //USER Word address
2250
                        ((i & 0x7) << AC_ADDRESS_POSITION) |
2251
                        (((i >> 3) & 0x1) << (AC_BANK_ADDRESS_POSITION + 2)) |
2252
                        //USER Configuration Word
2253
                        (((conf_word >> 2) & 0x3) << (AC_BANK_ADDRESS_POSITION)) |
2254
                        ((conf_word & 0x3) << (AC_ADDRESS_POSITION + 3));
2255
 
2256
                //USER Override the AC row with the RDIMM command
2257
                IOWR_32DIRECT(BASE_RW_MGR, 0x1C00 + (__RW_MGR_ac_rdimm << 2), ac_content);
2258
 
2259
                set_jump_as_return();
2260
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_RDIMM_CMD);
2261
                //USER When sending the RC2 or RC10 word, tSTAB time must elapse before the next command
2262
                //USER is sent out. tSTAB is currently hard-coded to 6us.
2263
                if((i == 2) || (i == 10))
2264
                {
2265
                        //USER tSTAB = 6 us
2266
                        delay_for_n_ns(6000);
2267
                }
2268
 
2269
#endif
2270
#if LRDIMM
2271
                // USER Program configuration word with FSCW set to zero.
2272
                rw_mgr_lrdimm_rc_program(0, i, conf_word);
2273
#endif
2274
        }
2275
}
2276
#else
2277
void rw_mgr_rdimm_initialize(void) { }
2278
#endif
2279
 
2280
#if DDR3
2281
 
2282
#if (ADVANCED_ODT_CONTROL || LRDIMM)
2283
alt_u32 ddr3_mirror_mrs_cmd(alt_u32 bit_vector) {
2284
        // This function performs address mirroring of an AC ROM command, which
2285
        // requires swapping the following DDR3 bits:
2286
        //     A[3] <=> A[4]
2287
        //     A[5] <=> A[6]
2288
        //     A[7] <=> A[8]
2289
        //    BA[0] <=>BA[1]
2290
        // We assume AC_ROM_ENTRY = {BA[2:0], A[15:0]}.
2291
        alt_u32 unchanged_bits;
2292
        alt_u32 mask_a;
2293
        alt_u32 mask_b;
2294
        alt_u32 retval;
2295
 
2296
        unchanged_bits = (~(DDR3_AC_MIRR_MASK | (DDR3_AC_MIRR_MASK << 1))) & bit_vector;
2297
        mask_a = DDR3_AC_MIRR_MASK & bit_vector;
2298
        mask_b = (DDR3_AC_MIRR_MASK << 1) & bit_vector;
2299
 
2300
        retval = unchanged_bits | (mask_a << 1) | (mask_b >> 1);
2301
 
2302
        return retval;
2303
}
2304
 
2305
void rtt_change_MRS1_MRS2_NOM_WR (alt_u32 prev_ac_mr , alt_u32 odt_ac_mr, alt_u32 mirr_on, alt_u32 mr_cmd ) {
2306
        // This function updates the ODT-specific Mode Register bits (MRS1 or MRS2) in the AC ROM.
2307
        // Parameters:  prev_ac_mr - Original, *un-mirrored* AC ROM Entry
2308
        //              odt_ac_mr  - ODT bits to update (un-mirrored)
2309
        //              mirr_on    - boolean flag indicating if the regular or mirrored entry is updated
2310
        //              mr_cmd     - Mode register command (only MR1 and MR2 are supported for DDR3)
2311
        alt_u32 new_ac_mr;
2312
        alt_u32 ac_rom_entry = 0;
2313
        alt_u32 ac_rom_mask;
2314
 
2315
        switch (mr_cmd) {
2316
                case 1: {
2317
                        // USER MRS1 = RTT_NOM, RTT_DRV
2318
                        ac_rom_mask = DDR3_MR1_ODT_MASK;
2319
                        ac_rom_entry = mirr_on ? (0x1C00 | (__RW_MGR_ac_mrs1_mirr << 2))
2320
                                               : (0x1C00 | (__RW_MGR_ac_mrs1 << 2));
2321
                } break;
2322
                case 2: {
2323
                        // USER MRS2 = RTT_WR
2324
                        ac_rom_mask = DDR3_MR2_ODT_MASK;
2325
                        ac_rom_entry = mirr_on ? (0x1C00 | (__RW_MGR_ac_mrs2_mirr << 2))
2326
                                               : (0x1C00 | (__RW_MGR_ac_mrs2 << 2));
2327
                } break;
2328
        }
2329
 
2330
        // USER calculate new AC values and update ROM
2331
        new_ac_mr  = odt_ac_mr;
2332
        new_ac_mr |= (prev_ac_mr & ac_rom_mask);
2333
        if (mirr_on) {
2334
                new_ac_mr = ddr3_mirror_mrs_cmd(new_ac_mr);
2335
        }
2336
        IOWR_32DIRECT(BASE_RW_MGR, ac_rom_entry, new_ac_mr);
2337
}
2338
#endif //(ADVANCED_ODT_CONTROL || LRDIMM)
2339
 
2340
void rw_mgr_mem_initialize (void)
2341
{
2342
        alt_u32 r;
2343
 
2344
#if LRDIMM
2345
        alt_u32 rtt_nom;
2346
        alt_u32 rtt_drv;
2347
        alt_u32 rtt_wr;
2348
#endif // LRDIMM
2349
 
2350
        TRACE_FUNC();
2351
 
2352
        //USER The reset / cke part of initialization is broadcasted to all ranks
2353
        IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, RW_MGR_RANK_ALL);
2354
 
2355
        // Here's how you load register for a loop
2356
        //USER Counters are located @ 0x800
2357
        //USER Jump address are located @ 0xC00
2358
        //USER For both, registers 0 to 3 are selected using bits 3 and 2, like in
2359
        //USER 0x800, 0x804, 0x808, 0x80C and 0xC00, 0xC04, 0xC08, 0xC0C
2360
        // I know this ain't pretty, but Avalon bus throws away the 2 least significant bits
2361
 
2362
        //USER start with memory RESET activated
2363
 
2364
        //USER tINIT is typically 200us (but can be adjusted in the GUI)
2365
        //USER The total number of cycles required for this nested counter structure to
2366
        //USER complete is defined by:
2367
        //USER        num_cycles = (CTR2 + 1) * [(CTR1 + 1) * (2 * (CTR0 + 1) + 1) + 1] + 1
2368
 
2369
        //USER Load counters
2370
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TINIT_CNTR0_VAL));
2371
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TINIT_CNTR1_VAL));
2372
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TINIT_CNTR2_VAL));
2373
 
2374
        //USER Load jump address
2375
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_INIT_RESET_0_CKE_0);
2376
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_INIT_RESET_0_CKE_0);
2377
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_INIT_RESET_0_CKE_0);
2378
 
2379
        //USER Execute count instruction
2380
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_INIT_RESET_0_CKE_0);
2381
 
2382
        //USER indicate that memory is stable
2383
        IOWR_32DIRECT (PHY_MGR_RESET_MEM_STBL, 0, 1);
2384
 
2385
        //USER transition the RESET to high 
2386
        //USER Wait for 500us
2387
        //USER        num_cycles = (CTR2 + 1) * [(CTR1 + 1) * (2 * (CTR0 + 1) + 1) + 1] + 1
2388
        //USER Load counters
2389
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TRESET_CNTR0_VAL));
2390
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TRESET_CNTR1_VAL));
2391
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TRESET_CNTR2_VAL));
2392
 
2393
        //USER Load jump address
2394
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_INIT_RESET_1_CKE_0);
2395
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_INIT_RESET_1_CKE_0);
2396
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_INIT_RESET_1_CKE_0);
2397
 
2398
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_INIT_RESET_1_CKE_0);
2399
 
2400
        //USER bring up clock enable 
2401
 
2402
        //USER tXRP < 250 ck cycles
2403
        delay_for_n_mem_clocks(250);
2404
 
2405
#ifdef RDIMM
2406
        // USER initialize RDIMM buffer so MRS and RZQ Calibrate commands will be 
2407
        // USER propagated to discrete memory devices
2408
        rw_mgr_rdimm_initialize();
2409
#endif
2410
 
2411
#if LRDIMM
2412
        // USER initialize LRDIMM MB so MRS and RZQ Calibrate commands will be 
2413
        // USER propagated to all sub-ranks.  Per LRDIMM spec, all LRDIMM ranks must have
2414
        // USER RTT_WR set, but only physical ranks 0 and 1 should have RTT_NOM set.
2415
        // USER Therefore RTT_NOM=0 is broadcast to all ranks, and the non-zero value is 
2416
        // USER programmed directly into Ranks 0 and 1 using physical MRS targetting.
2417
        rw_mgr_rdimm_initialize();
2418
 
2419
        rtt_nom = LRDIMM_SPD_MR_RTT_NOM(LRDIMM_SPD_MR);
2420
        rtt_drv = LRDIMM_SPD_MR_RTT_DRV(LRDIMM_SPD_MR);
2421
        rtt_wr  = LRDIMM_SPD_MR_RTT_WR(LRDIMM_SPD_MR);
2422
 
2423
        // USER Configure LRDIMM to broadcast LRDIMM MRS commands to all ranks
2424
        rw_mgr_lrdimm_rc_program(0, 14, (((RDIMM_CONFIG_WORD_HIGH >> 24) & 0xF) & (~0x4)));
2425
 
2426
        // USER Update contents of AC ROM with new RTT WR, DRV values only (NOM = Off)
2427
        rtt_change_MRS1_MRS2_NOM_WR(__RW_MGR_CONTENT_ac_mrs1, rtt_drv, 0, 1);
2428
        rtt_change_MRS1_MRS2_NOM_WR(__RW_MGR_CONTENT_ac_mrs1, rtt_drv, 1, 1);
2429
        rtt_change_MRS1_MRS2_NOM_WR(__RW_MGR_CONTENT_ac_mrs2, rtt_wr,  0, 2);
2430
        rtt_change_MRS1_MRS2_NOM_WR(__RW_MGR_CONTENT_ac_mrs2, rtt_wr,  1, 2);
2431
#endif
2432
#if RDIMM
2433
        // USER initialize RDIMM buffer so MRS and RZQ Calibrate commands will be 
2434
        // USER propagated to discrete memory devices
2435
        rw_mgr_rdimm_initialize();
2436
#endif
2437
 
2438
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
2439
                if (param->skip_ranks[r]) {
2440
                        //USER request to skip the rank
2441
 
2442
                        continue;
2443
                }
2444
 
2445
#if ADVANCED_ODT_CONTROL
2446
                alt_u32 rtt_nom = 0;
2447
                alt_u32 rtt_wr  = 0;
2448
                alt_u32 rtt_drv = 0;
2449
 
2450
                switch (r) {
2451
                        case 0: {
2452
                                rtt_nom = MR1_RTT_RANK0;
2453
                                rtt_wr  = MR2_RTT_WR_RANK0;
2454
                                rtt_drv = MR1_RTT_DRV_RANK0;
2455
                        } break;
2456
                        case 1: {
2457
                                rtt_nom = MR1_RTT_RANK1;
2458
                                rtt_wr  = MR2_RTT_WR_RANK1;
2459
                                rtt_drv = MR1_RTT_DRV_RANK1;
2460
                        } break;
2461
                        case 2: {
2462
                                rtt_nom = MR1_RTT_RANK2;
2463
                                rtt_wr  = MR2_RTT_WR_RANK2;
2464
                                rtt_drv = MR1_RTT_DRV_RANK2;
2465
                        } break;
2466
                        case 3: {
2467
                                rtt_nom = MR1_RTT_RANK3;
2468
                                rtt_wr  = MR2_RTT_WR_RANK3;
2469
                                rtt_drv = MR1_RTT_DRV_RANK3;
2470
                        } break;
2471
                }
2472
                rtt_change_MRS1_MRS2_NOM_WR (__RW_MGR_CONTENT_ac_mrs1, (rtt_nom|rtt_drv),
2473
                                             ((RW_MGR_MEM_ADDRESS_MIRRORING>>r)&0x1), 1);
2474
                rtt_change_MRS1_MRS2_NOM_WR (__RW_MGR_CONTENT_ac_mrs2, rtt_wr,
2475
                                             ((RW_MGR_MEM_ADDRESS_MIRRORING>>r)&0x1), 2);
2476
#endif //ADVANCED_ODT_CONTROL
2477
 
2478
                //USER set rank 
2479
#if MRS_MIRROR_PING_PONG_ATSO
2480
                // Special case
2481
                // SIDE 0
2482
                set_rank_and_odt_mask_for_ping_pong_atso(0, RW_MGR_ODT_MODE_OFF);
2483
                set_jump_as_return();
2484
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS2);
2485
                delay_for_n_mem_clocks(4);
2486
                set_jump_as_return();
2487
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS3);
2488
                delay_for_n_mem_clocks(4);
2489
                set_jump_as_return();
2490
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1);
2491
                set_jump_as_return();
2492
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_DLL_RESET);
2493
 
2494
                // SIDE 1
2495
                set_rank_and_odt_mask_for_ping_pong_atso(1, RW_MGR_ODT_MODE_OFF);
2496
                set_jump_as_return();
2497
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS2_MIRR);
2498
                delay_for_n_mem_clocks(4);
2499
                set_jump_as_return();
2500
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS3_MIRR);
2501
                delay_for_n_mem_clocks(4);
2502
                set_jump_as_return();
2503
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1_MIRR);
2504
                delay_for_n_mem_clocks(4);
2505
                set_jump_as_return();
2506
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_DLL_RESET_MIRR);
2507
 
2508
                // Unmask all CS
2509
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
2510
#else
2511
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
2512
 
2513
                //USER Use Mirror-ed commands for odd ranks if address mirrorring is on
2514
                if((RW_MGR_MEM_ADDRESS_MIRRORING >> r) & 0x1) {
2515
                        set_jump_as_return();
2516
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS2_MIRR);
2517
                        delay_for_n_mem_clocks(4);
2518
                        set_jump_as_return();
2519
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS3_MIRR);
2520
                        delay_for_n_mem_clocks(4);
2521
                        set_jump_as_return();
2522
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1_MIRR);
2523
                        delay_for_n_mem_clocks(4);
2524
                        set_jump_as_return();
2525
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_DLL_RESET_MIRR);
2526
                } else {
2527
                        set_jump_as_return();
2528
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS2);
2529
                        delay_for_n_mem_clocks(4);
2530
                        set_jump_as_return();
2531
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS3);
2532
                        delay_for_n_mem_clocks(4);
2533
                        set_jump_as_return();
2534
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1);
2535
                        set_jump_as_return();
2536
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_DLL_RESET);
2537
                }
2538
#endif
2539
 
2540
                set_jump_as_return();
2541
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_ZQCL);
2542
 
2543
                //USER tZQinit = tDLLK = 512 ck cycles
2544
                delay_for_n_mem_clocks(512);
2545
        }
2546
#if LRDIMM
2547
        // USER Configure LRDIMM to target physical ranks decoded by RM bits only (ranks 0,1 only)
2548
        // USER Set bit F0RC14.DBA0 to '1' so MRS commands target physical ranks only
2549
        rw_mgr_lrdimm_rc_program(0, 14, (((RDIMM_CONFIG_WORD_HIGH >> 24) & 0xF) | 0x4));
2550
        // USER update AC ROM MR1 entry to include RTT_NOM
2551
        rtt_change_MRS1_MRS2_NOM_WR(__RW_MGR_CONTENT_ac_mrs1, (rtt_drv|rtt_nom), 0, 1);
2552
        rtt_change_MRS1_MRS2_NOM_WR(__RW_MGR_CONTENT_ac_mrs1, (rtt_drv|rtt_nom), 1, 1);
2553
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
2554
                if (param->skip_ranks[r]) {
2555
                        //USER request to skip the rank
2556
                        continue;
2557
                }
2558
 
2559
                //USER set rank 
2560
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
2561
 
2562
                //USER Use Mirror-ed commands for odd ranks if address mirrorring is on
2563
                if((RW_MGR_MEM_ADDRESS_MIRRORING >> r) & 0x1) {
2564
                        delay_for_n_mem_clocks(4);
2565
                        set_jump_as_return();
2566
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1_MIRR);
2567
                        delay_for_n_mem_clocks(4);
2568
                } else {
2569
                        delay_for_n_mem_clocks(4);
2570
                        set_jump_as_return();
2571
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1);
2572
                        delay_for_n_mem_clocks(4);
2573
                }
2574
        }
2575
 
2576
        // USER Initiate LRDIMM MB->Physical Rank training here
2577
        // USER -> Set minimum skew mode for levelling - F3RC6 = 0001
2578
        rw_mgr_lrdimm_rc_program(3, 6, 0x1);
2579
        // USER -> Set error status output in register F2RC3 for debugging purposes
2580
        rw_mgr_lrdimm_rc_program(2, 3, 0x8);
2581
 
2582
#ifdef LRDIMM_EXT_CONFIG_ARRAY
2583
        // USER Configure LRDIMM ODT/Drive parameters using SPD information
2584
        {
2585
                static const alt_u8 lrdimm_cfg_array[][3] = LRDIMM_EXT_CONFIG_ARRAY;
2586
                alt_u32 cfg_reg_ctr;
2587
 
2588
                for (cfg_reg_ctr = 0; cfg_reg_ctr < (sizeof(lrdimm_cfg_array)/sizeof(lrdimm_cfg_array[0])); cfg_reg_ctr++)
2589
                {
2590
                        alt_u32 lrdimm_fp  = (alt_u32)lrdimm_cfg_array[cfg_reg_ctr][0];
2591
                        alt_u32 lrdimm_rc  = (alt_u32)lrdimm_cfg_array[cfg_reg_ctr][1];
2592
                        alt_u32 lrdimm_val = (alt_u32)lrdimm_cfg_array[cfg_reg_ctr][2];
2593
 
2594
                        rw_mgr_lrdimm_rc_program(lrdimm_fp, lrdimm_rc, lrdimm_val);
2595
                }
2596
        }
2597
#endif // LRDIMM_EXT_CONFIG_ARRAY
2598
 
2599
        // USER -> Initiate MB->DIMM training on the LRDIMM
2600
        rw_mgr_lrdimm_rc_program(0, 12, 0x2);
2601
#if (!STATIC_SKIP_DELAY_LOOPS)
2602
        // USER Wait for max(tcal) * number of physical ranks. Tcal is approx. 10ms.
2603
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS * RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM; r++)
2604
        {
2605
                delay_for_n_ns(80000000UL);
2606
        }
2607
#endif // !STATIC_SKIP_DELAY_LOOPS
2608
        // USER Place MB back in normal operating mode
2609
        rw_mgr_lrdimm_rc_program(0, 12, 0x0);
2610
#endif // LRDIMM
2611
}
2612
 
2613
 
2614
#if (ENABLE_NON_DESTRUCTIVE_CALIB || ENABLE_NON_DES_CAL)
2615
void rw_mgr_mem_initialize_no_init (void)
2616
{
2617
        alt_u32 r;
2618
        alt_u32 mem_refresh_all_ranks(alt_u32 no_validate);
2619
        TRACE_FUNC();
2620
        rw_mgr_rdimm_initialize();
2621
        IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, RW_MGR_RANK_ALL);
2622
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_RETURN);
2623
        delay_for_n_mem_clocks(512);
2624
        mem_refresh_all_ranks(1);
2625
        IOWR_32DIRECT (PHY_MGR_RESET_MEM_STBL, 0, 1);
2626
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
2627
                if (param->skip_ranks[r]) {
2628
                        continue;
2629
                }
2630
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
2631
                set_jump_as_return();
2632
                if((RW_MGR_MEM_ADDRESS_MIRRORING >> r) & 0x1) {
2633
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_DLL_RESET_MIRR);
2634
                } else {
2635
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_DLL_RESET);
2636
                }
2637
 
2638
// Reprogramming these is not really required but....
2639
                        set_jump_as_return();
2640
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS2);
2641
                        delay_for_n_mem_clocks(4);
2642
                        set_jump_as_return();
2643
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS3);
2644
                        delay_for_n_mem_clocks(4);
2645
                        set_jump_as_return();
2646
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1);
2647
 
2648
 
2649
 
2650
                delay_for_n_mem_clocks(4);
2651
                set_jump_as_return();
2652
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_ZQCL);
2653
                delay_for_n_mem_clocks(512);
2654
        }
2655
 
2656
        IOWR_32DIRECT (RW_MGR_ENABLE_REFRESH, 0, 1);  // Enable refresh engine  
2657
 
2658
}
2659
#endif
2660
#endif // DDR3
2661
 
2662
#if DDR2
2663
void rw_mgr_mem_initialize (void)
2664
{
2665
        alt_u32 r;
2666
 
2667
        TRACE_FUNC();
2668
 
2669
        //USER *** NOTE ***
2670
        //USER The following STAGE (n) notation refers to the corresponding stage in the Micron datasheet
2671
 
2672
        // Here's how you load register for a loop
2673
        //USER Counters are located @ 0x800
2674
        //USER Jump address are located @ 0xC00
2675
        //USER For both, registers 0 to 3 are selected using bits 3 and 2, like in
2676
        //USER 0x800, 0x804, 0x808, 0x80C and 0xC00, 0xC04, 0xC08, 0xC0C
2677
        // I know this ain't pretty, but Avalon bus throws away the 2 least significant bits
2678
 
2679
        //USER *** STAGE (1, 2, 3) ***
2680
 
2681
        //USER start with CKE low 
2682
 
2683
        //USER tINIT is typically 200us (but can be adjusted in the GUI)
2684
        //USER The total number of cycles required for this nested counter structure to
2685
        //USER complete is defined by:
2686
        //USER        num_cycles = (CTR0 + 1) * [(CTR1 + 1) * (2 * (CTR2 + 1) + 1) + 1] + 1
2687
 
2688
        //TODO: Need to manage multi-rank
2689
 
2690
        //USER Load counters
2691
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TINIT_CNTR0_VAL));
2692
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TINIT_CNTR1_VAL));
2693
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TINIT_CNTR2_VAL));
2694
 
2695
        //USER Load jump address
2696
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_INIT_CKE_0);
2697
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_INIT_CKE_0);
2698
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_INIT_CKE_0);
2699
 
2700
        //USER Execute count instruction
2701
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_INIT_CKE_0);
2702
 
2703
        //USER indicate that memory is stable 
2704
        IOWR_32DIRECT (PHY_MGR_RESET_MEM_STBL, 0, 1);
2705
 
2706
        //USER Bring up CKE 
2707
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_NOP);
2708
 
2709
        //USER *** STAGE (4)
2710
 
2711
        //USER Wait for 400ns 
2712
        delay_for_n_ns(400);
2713
 
2714
        //USER Multi-rank section begins here
2715
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
2716
                if (param->skip_ranks[r]) {
2717
                        //USER request to skip the rank
2718
 
2719
                        continue;
2720
                }
2721
 
2722
                //USER set rank 
2723
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
2724
 
2725
                //USER * **** *
2726
                //USER * NOTE *
2727
                //USER * **** *
2728
                //USER The following commands must be spaced by tMRD or tRPA which are in the order
2729
                //USER of 2 to 4 full rate cycles. This is peanuts in the NIOS domain, so for now
2730
                //USER we can avoid redundant wait loops
2731
 
2732
                // Possible FIXME BEN: for HHP, we need to add delay loops to be sure
2733
                // although, the sequencer write interface by itself likely has enough delay
2734
 
2735
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_PRECHARGE_ALL);
2736
 
2737
                //USER *** STAGE (5)
2738
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_EMR2);
2739
 
2740
                //USER *** STAGE (6)
2741
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_EMR3);
2742
 
2743
                //USER *** STAGE (7)
2744
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_EMR);
2745
 
2746
                //USER *** STAGE (8)
2747
                //USER DLL reset
2748
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR_DLL_RESET);
2749
 
2750
                //USER *** STAGE (9)
2751
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_PRECHARGE_ALL);
2752
 
2753
                //USER *** STAGE (10)
2754
 
2755
                //USER Issue 2 refresh commands spaced by tREF 
2756
 
2757
                //USER First REFRESH
2758
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_REFRESH);
2759
 
2760
                //USER tREF = 200ns
2761
                delay_for_n_ns(200);
2762
 
2763
                //USER Second REFRESH
2764
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_REFRESH);
2765
 
2766
                //USER Second idle loop
2767
                delay_for_n_ns(200);
2768
 
2769
                //USER *** STAGE (11)
2770
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR_CALIB);
2771
 
2772
                //USER *** STAGE (12)
2773
                //USER OCD defaults
2774
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_EMR_OCD_ENABLE);
2775
 
2776
                //USER *** STAGE (13)
2777
                //USER OCD exit
2778
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_EMR);
2779
 
2780
                //USER *** STAGE (14)
2781
 
2782
                //USER The memory is now initialized. Before being able to use it, we must still
2783
                //USER wait for the DLL to lock, 200 clock cycles after it was reset @ STAGE (8).
2784
                //USER Since we cannot keep track of time in any other way, let's start counting from now
2785
                delay_for_n_mem_clocks(200);
2786
        }
2787
}
2788
#endif // DDR2 
2789
 
2790
#if LPDDR2
2791
void rw_mgr_mem_initialize (void)
2792
{
2793
        alt_u32 r;
2794
 
2795
        //USER *** NOTE ***
2796
        //USER The following STAGE (n) notation refers to the corresponding stage in the Micron datasheet
2797
 
2798
        // Here's how you load register for a loop
2799
        //USER Counters are located @ 0x800
2800
        //USER Jump address are located @ 0xC00
2801
        //USER For both, registers 0 to 3 are selected using bits 3 and 2, like in
2802
        //USER 0x800, 0x804, 0x808, 0x80C and 0xC00, 0xC04, 0xC08, 0xC0C
2803
        // I know this ain't pretty, but Avalon bus throws away the 2 least significant bits
2804
 
2805
        //USER *** STAGE (1, 2, 3) ***
2806
 
2807
        //USER start with CKE low 
2808
 
2809
        //USER tINIT1 = 100ns
2810
 
2811
        //USER 100ns @ 300MHz (3.333 ns) ~ 30 cycles
2812
        //USER If a is the number of iteration in a loop
2813
        //USER it takes the following number of cycles to complete the operation:
2814
        //USER number_of_cycles = (2 + n) * a
2815
        //USER where n is the number of instruction in the inner loop
2816
        //USER One possible solution is n = 0 , a = 15 => a = 0x10
2817
 
2818
        //USER Load counter
2819
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(0x10));
2820
 
2821
        //USER Load jump address
2822
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_INIT_CKE_0);
2823
 
2824
        //USER Execute count instruction
2825
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_INIT_CKE_0);
2826
 
2827
        //USER tINIT3 = 200us
2828
        delay_for_n_ns(200000);
2829
 
2830
        //USER indicate that memory is stable 
2831
        IOWR_32DIRECT (PHY_MGR_RESET_MEM_STBL, 0, 1);
2832
 
2833
        //USER Multi-rank section begins here
2834
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
2835
                if (param->skip_ranks[r]) {
2836
                        //USER request to skip the rank
2837
 
2838
                        continue;
2839
                }
2840
 
2841
                //USER set rank 
2842
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
2843
 
2844
                //USER MRW RESET
2845
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR63_RESET);
2846
        }
2847
 
2848
        //USER tINIT5 = 10us
2849
        delay_for_n_ns(10000);
2850
 
2851
        //USER Multi-rank section begins here
2852
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
2853
                if (param->skip_ranks[r]) {
2854
                        //USER request to skip the rank
2855
 
2856
                        continue;
2857
                }
2858
 
2859
                //USER set rank 
2860
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
2861
 
2862
                //USER MRW ZQC
2863
                // Note: We cannot calibrate other ranks when the current rank is calibrating for tZQINIT
2864
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR10_ZQC);
2865
 
2866
                //USER tZQINIT = 1us
2867
                delay_for_n_ns(1000);
2868
 
2869
                //USER * **** *
2870
                //USER * NOTE *
2871
                //USER * **** *
2872
                //USER The following commands must be spaced by tMRW which is in the order
2873
                //USER of 3 to 5 full rate cycles. This is peanuts in the NIOS domain, so for now
2874
                //USER we can avoid redundant wait loops
2875
 
2876
                //USER MRW MR1
2877
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR1_CALIB);
2878
 
2879
                //USER MRW MR2
2880
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR2);
2881
 
2882
                //USER MRW MR3
2883
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR3);
2884
        }
2885
}
2886
#endif // LPDDR2 
2887
 
2888
#if LPDDR1
2889
void rw_mgr_mem_initialize (void)
2890
{
2891
        alt_u32 r;
2892
 
2893
        TRACE_FUNC();
2894
 
2895
        //USER *** NOTE ***
2896
        //USER The following STAGE (n) notation refers to the corresponding stage in the Micron datasheet
2897
 
2898
        // Here's how you load register for a loop
2899
        //USER Counters are located @ 0x800
2900
        //USER Jump address are located @ 0xC00
2901
        //USER For both, registers 0 to 3 are selected using bits 3 and 2, like in
2902
        //USER 0x800, 0x804, 0x808, 0x80C and 0xC00, 0xC04, 0xC08, 0xC0C
2903
        // I know this ain't pretty, but Avalon bus throws away the 2 least significant bits
2904
 
2905
        //USER *** STAGE (1, 2, 3) ***
2906
 
2907
        //USER start with CKE high 
2908
 
2909
        //USER tINIT = 200us
2910
 
2911
        //USER 200us @ 300MHz (3.33 ns) ~ 60000 clock cycles
2912
        //USER If a and b are the number of iteration in 2 nested loops
2913
        //USER it takes the following number of cycles to complete the operation:
2914
        //USER number_of_cycles = ((2 + n) * b + 2) * a
2915
        //USER where n is the number of instruction in the inner loop
2916
        //USER One possible solution is n = 0 , a = 256 , b = 118 => a = FF, b = 76
2917
 
2918
        //TODO: Need to manage multi-rank
2919
 
2920
        //USER Load counters
2921
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(0xFF));
2922
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(0x76));
2923
 
2924
        //USER Load jump address
2925
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_INIT_CKE_1);
2926
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_INIT_CKE_1_inloop);
2927
 
2928
        //USER Execute count instruction and bring up CKE
2929
        //USER IOWR_32DIRECT (BASE_RW_MGR, 0, __RW_MGR_COUNT_REG_0);
2930
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_INIT_CKE_1);
2931
 
2932
        //USER indicate that memory is stable 
2933
        IOWR_32DIRECT (PHY_MGR_RESET_MEM_STBL, 0, 1);
2934
 
2935
        //USER Multi-rank section begins here
2936
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
2937
                if (param->skip_ranks[r]) {
2938
                        //USER request to skip the rank
2939
 
2940
                        continue;
2941
                }
2942
 
2943
                //USER set rank 
2944
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
2945
 
2946
                //USER * **** *
2947
                //USER * NOTE *
2948
                //USER * **** *
2949
                //USER The following commands must be spaced by tMRD or tRPA which are in the order
2950
                //USER of 2 to 4 full rate cycles. This is peanuts in the NIOS domain, so for now
2951
                //USER we can avoid redundant wait loops
2952
 
2953
                // Possible FIXME BEN: for HHP, we need to add delay loops to be sure
2954
                // although, the sequencer write interface by itself likely has enough delay
2955
 
2956
                //USER *** STAGE (9)
2957
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_PRECHARGE_ALL);
2958
 
2959
                //USER *** STAGE (10)
2960
 
2961
                //USER Issue 2 refresh commands spaced by tREF 
2962
 
2963
                //USER First REFRESH
2964
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_REFRESH);
2965
 
2966
                //USER tREF = 200ns
2967
                delay_for_n_ns(200);
2968
 
2969
                //USER Second REFRESH
2970
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_REFRESH);
2971
 
2972
                //USER Second idle loop
2973
                delay_for_n_ns(200);
2974
 
2975
                //USER *** STAGE (11)
2976
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR_CALIB);
2977
 
2978
                //USER *** STAGE (13)
2979
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_EMR);
2980
 
2981
        }
2982
}
2983
#endif // LPDDR1
2984
 
2985
#if QDRII
2986
void rw_mgr_mem_initialize (void)
2987
{
2988
        TRACE_FUNC();
2989
 
2990
        //USER Turn off QDRII DLL to reset it
2991
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_IDLE);
2992
 
2993
        //USER Turn on QDRII DLL and wait 25us for it to lock
2994
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_NOP);
2995
        delay_for_n_ns(25000);
2996
 
2997
        //USER indicate that memory is stable
2998
        IOWR_32DIRECT (PHY_MGR_RESET_MEM_STBL, 0, 1);
2999
}
3000
#endif
3001
 
3002
#if QDRII
3003
void rw_mgr_mem_dll_lock_wait (void)
3004
{
3005
        //USER The DLL in QDR requires 25us to lock
3006
        delay_for_n_ns(25000);
3007
}
3008
#else
3009
void rw_mgr_mem_dll_lock_wait (void) { }
3010
#endif
3011
 
3012
#if RLDRAMII
3013
void rw_mgr_mem_initialize (void)
3014
{
3015
        TRACE_FUNC();
3016
 
3017
        //USER start with memory RESET activated
3018
 
3019
        //USER tINIT = 200us
3020
        delay_for_n_ns(200000);
3021
 
3022
        //USER indicate that memory is stable 
3023
        IOWR_32DIRECT (PHY_MGR_RESET_MEM_STBL, 0, 1);
3024
 
3025
        //USER Dummy MRS, followed by valid MRS commands to reset the DLL on memory device
3026
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS_INIT);
3027
 
3028
        //USER 8192 memory cycles for DLL to lock. 
3029
        // 8192 cycles are required by Renesas LLDRAM-II, though we don't officially support it
3030
        delay_for_n_mem_clocks(8192);
3031
 
3032
        //USER Refresh all banks
3033
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_REF_X8);
3034
 
3035
        //USER 1024 memory cycles
3036
        delay_for_n_mem_clocks(1024);
3037
}
3038
#endif
3039
 
3040
#if RLDRAM3
3041
void rw_mgr_mem_initialize (void)
3042
{
3043
        TRACE_FUNC();
3044
        alt_u32 r;
3045
 
3046
        // Here's how you load register for a loop
3047
        //USER Counters are located @ 0x800
3048
        //USER Jump address are located @ 0xC00
3049
        //USER For both, registers 0 to 3 are selected using bits 3 and 2, like in
3050
        //USER 0x800, 0x804, 0x808, 0x80C and 0xC00, 0xC04, 0xC08, 0xC0C
3051
        // I know this ain't pretty, but Avalon bus throws away the 2 least significant bits
3052
 
3053
        //USER start with memory RESET activated
3054
 
3055
        //USER tINIT = 200us
3056
 
3057
        //USER 200us @ 266MHz (3.75 ns) ~ 54000 clock cycles
3058
        //USER If a and b are the number of iteration in 2 nested loops
3059
        //USER it takes the following number of cycles to complete the operation:
3060
        //USER number_of_cycles = ((2 + n) * a + 2) * b
3061
        //USER where n is the number of instruction in the inner loop
3062
        //USER One possible solution is n = 0 , a = 256 , b = 106 => a = FF, b = 6A
3063
 
3064
        //USER Load counters
3065
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(0xFF));
3066
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, SKIP_DELAY_LOOP_VALUE_OR_ZERO(0x6A));
3067
 
3068
        //USER Load jump address
3069
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_INIT_RESET_0);
3070
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_INIT_RESET_0_inloop);
3071
 
3072
        //USER Execute count instruction
3073
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_INIT_RESET_0);
3074
 
3075
        //USER indicate that memory is stable
3076
        IOWR_32DIRECT (PHY_MGR_RESET_MEM_STBL, 0, 1);
3077
 
3078
        //USER transition the RESET to high 
3079
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_NOP);
3080
 
3081
        //USER Wait for 10000 cycles
3082
        delay_for_n_mem_clocks(10000);
3083
 
3084
        //USER Load MR0
3085
        if ( RW_MGR_MEM_NUMBER_OF_RANKS == 1 ) {
3086
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFE);
3087
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0);
3088
        } else if ( RW_MGR_MEM_NUMBER_OF_RANKS == 2 ) {
3089
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFC);
3090
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0);
3091
        } else if ( RW_MGR_MEM_NUMBER_OF_RANKS == 4 ) {
3092
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFC);
3093
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0);
3094
                //USER Wait MRSC
3095
                delay_for_n_mem_clocks(12);
3096
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xF3);
3097
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_QUAD_RANK);
3098
        }
3099
        else {
3100
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFE);
3101
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0);
3102
        }
3103
 
3104
 
3105
        //USER Wait MRSC
3106
        delay_for_n_mem_clocks(12);
3107
 
3108
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
3109
                if (param->skip_ranks[r]) {
3110
                        //USER request to skip the rank
3111
                        continue;
3112
                }
3113
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
3114
                //USER Load MR1 (reset DLL reset and kick off long ZQ calibration)
3115
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1_CALIB);
3116
 
3117
      //USER Wait 512 cycles for DLL to reset and for ZQ calibration to complete
3118
      delay_for_n_mem_clocks(512);
3119
        }
3120
 
3121
        //USER Load MR2 (set write protocol to Single Bank)
3122
        if ( RW_MGR_MEM_NUMBER_OF_RANKS == 1 ) {
3123
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFE);
3124
        } else if ( RW_MGR_MEM_NUMBER_OF_RANKS == 2 ) {
3125
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFC);
3126
        } else if ( RW_MGR_MEM_NUMBER_OF_RANKS == 4 ) {
3127
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xF0);
3128
        }
3129
        else {
3130
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFE);
3131
        }
3132
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS2_CALIB);
3133
 
3134
        //USER Wait MRSC and a bit more
3135
        delay_for_n_mem_clocks(64);
3136
}
3137
#endif
3138
 
3139
//USER  At the end of calibration we have to program the user settings in, and
3140
//USER  hand off the memory to the user.
3141
 
3142
#if DDR3
3143
void rw_mgr_mem_handoff (void)
3144
{
3145
        alt_u32 r;
3146
#if LRDIMM
3147
        alt_u32 rtt_nom;
3148
        alt_u32 rtt_drv;
3149
        alt_u32 rtt_wr;
3150
#endif // LRDIMM
3151
 
3152
        TRACE_FUNC();
3153
 
3154
#if LRDIMM
3155
        rtt_nom = LRDIMM_SPD_MR_RTT_NOM(LRDIMM_SPD_MR);
3156
        rtt_drv = LRDIMM_SPD_MR_RTT_DRV(LRDIMM_SPD_MR);
3157
        rtt_wr  = LRDIMM_SPD_MR_RTT_WR(LRDIMM_SPD_MR);
3158
 
3159
        // USER Configure LRDIMM to broadcast LRDIMM MRS commands to all ranks
3160
        // USER Set bit F0RC14.DBA0 to '0' so MRS commands target all physical ranks in a logical rank
3161
        rw_mgr_lrdimm_rc_program(0, 14, (((RDIMM_CONFIG_WORD_HIGH >> 24) & 0xF) & (~0x4)));
3162
 
3163
        // USER Update contents of AC ROM with new RTT WR, DRV values
3164
        rtt_change_MRS1_MRS2_NOM_WR (__RW_MGR_CONTENT_ac_mrs1, rtt_drv, 0, 1);
3165
        rtt_change_MRS1_MRS2_NOM_WR (__RW_MGR_CONTENT_ac_mrs1, rtt_drv, 1, 1);
3166
        rtt_change_MRS1_MRS2_NOM_WR (__RW_MGR_CONTENT_ac_mrs2, rtt_wr,  0, 2);
3167
        rtt_change_MRS1_MRS2_NOM_WR (__RW_MGR_CONTENT_ac_mrs2, rtt_wr,  1, 2);
3168
#endif // LRDIMM
3169
 
3170
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
3171
                if (param->skip_ranks[r]) {
3172
                        //USER request to skip the rank
3173
 
3174
                        continue;
3175
                }
3176
 
3177
#if MRS_MIRROR_PING_PONG_ATSO
3178
                // Side 0
3179
                set_rank_and_odt_mask_for_ping_pong_atso(0, RW_MGR_ODT_MODE_OFF);
3180
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_PRECHARGE_ALL);
3181
                set_jump_as_return();
3182
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS2);
3183
                delay_for_n_mem_clocks(4);
3184
                set_jump_as_return();
3185
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS3);
3186
                delay_for_n_mem_clocks(4);
3187
                set_jump_as_return();
3188
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1);
3189
                delay_for_n_mem_clocks(4);
3190
                set_jump_as_return();
3191
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_USER);
3192
 
3193
                // Side 1
3194
                set_rank_and_odt_mask_for_ping_pong_atso(1, RW_MGR_ODT_MODE_OFF);
3195
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_PRECHARGE_ALL);
3196
                set_jump_as_return();
3197
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS2_MIRR);
3198
                delay_for_n_mem_clocks(4);
3199
                set_jump_as_return();
3200
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS3_MIRR);
3201
                delay_for_n_mem_clocks(4);
3202
                set_jump_as_return();
3203
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1_MIRR);
3204
                delay_for_n_mem_clocks(4);
3205
                set_jump_as_return();
3206
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_USER_MIRR);
3207
 
3208
                // Unmask all CS
3209
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
3210
#else
3211
                //USER set rank
3212
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
3213
 
3214
                //USER precharge all banks ... 
3215
 
3216
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_PRECHARGE_ALL);
3217
 
3218
                //USER load up MR settings specified by user 
3219
 
3220
                //USER Use Mirror-ed commands for odd ranks if address mirrorring is on
3221
                if((RW_MGR_MEM_ADDRESS_MIRRORING >> r) & 0x1) {
3222
                        set_jump_as_return();
3223
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS2_MIRR);
3224
                        delay_for_n_mem_clocks(4);
3225
                        set_jump_as_return();
3226
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS3_MIRR);
3227
                        delay_for_n_mem_clocks(4);
3228
                        set_jump_as_return();
3229
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1_MIRR);
3230
                        delay_for_n_mem_clocks(4);
3231
                        set_jump_as_return();
3232
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_USER_MIRR);
3233
                } else {
3234
                        set_jump_as_return();
3235
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS2);
3236
                        delay_for_n_mem_clocks(4);
3237
                        set_jump_as_return();
3238
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS3);
3239
                        delay_for_n_mem_clocks(4);
3240
                        set_jump_as_return();
3241
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1);
3242
                        delay_for_n_mem_clocks(4);
3243
                        set_jump_as_return();
3244
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS0_USER);
3245
                }
3246
#endif
3247
                //USER  need to wait tMOD (12CK or 15ns) time before issuing other commands,
3248
                //USER  but we will have plenty of NIOS cycles before actual handoff so its okay.
3249
        }
3250
 
3251
 
3252
#if LRDIMM      
3253
        delay_for_n_mem_clocks(12);
3254
        // USER Set up targetted MRS commands
3255
        rw_mgr_lrdimm_rc_program(0, 14, (((RDIMM_CONFIG_WORD_HIGH >> 24) & 0xF) | 0x4));
3256
        // USER update AC ROM MR1 entry to include RTT_NOM for physical ranks 0,1 only
3257
        rtt_change_MRS1_MRS2_NOM_WR (__RW_MGR_CONTENT_ac_mrs1, (rtt_drv|rtt_nom), 0, 1);
3258
        rtt_change_MRS1_MRS2_NOM_WR (__RW_MGR_CONTENT_ac_mrs1, (rtt_drv|rtt_nom), 1, 1);
3259
 
3260
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
3261
                if (param->skip_ranks[r]) {
3262
                        //USER request to skip the rank
3263
                        continue;
3264
                }
3265
 
3266
                //USER set rank
3267
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
3268
 
3269
                //USER Use Mirror-ed commands for odd ranks if address mirrorring is on
3270
                if((RW_MGR_MEM_ADDRESS_MIRRORING >> r) & 0x1) {
3271
                        delay_for_n_mem_clocks(4);
3272
                        set_jump_as_return();
3273
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1_MIRR);
3274
                        delay_for_n_mem_clocks(4);
3275
                } else {
3276
                        delay_for_n_mem_clocks(4);
3277
                        set_jump_as_return();
3278
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1);
3279
                        delay_for_n_mem_clocks(4);
3280
                }
3281
        }
3282
#endif // LRDIMM
3283
}
3284
#endif // DDR3
3285
 
3286
#if DDR2
3287
void rw_mgr_mem_handoff (void)
3288
{
3289
        alt_u32 r;
3290
 
3291
        TRACE_FUNC();
3292
 
3293
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
3294
                if (param->skip_ranks[r]) {
3295
                        //USER request to skip the rank
3296
 
3297
                        continue;
3298
                }
3299
 
3300
                //USER set rank
3301
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
3302
 
3303
                //USER precharge all banks ... 
3304
 
3305
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_PRECHARGE_ALL);
3306
 
3307
                //USER load up MR settings specified by user 
3308
 
3309
                // FIXME BEN: for HHP, we need to add delay loops to be sure
3310
                // We can check this with BFM perhaps
3311
                // Likely enough delay in RW_MGR though
3312
 
3313
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_EMR2);
3314
 
3315
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_EMR3);
3316
 
3317
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_EMR);
3318
 
3319
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR_USER);
3320
 
3321
                //USER need to wait tMOD (12CK or 15ns) time before issuing other commands,
3322
                //USER but we will have plenty of NIOS cycles before actual handoff so its okay.
3323
        }
3324
}
3325
#endif //USER DDR2
3326
 
3327
#if LPDDR2
3328
void rw_mgr_mem_handoff (void)
3329
{
3330
        alt_u32 r;
3331
 
3332
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
3333
                if (param->skip_ranks[r]) {
3334
                        //USER request to skip the rank
3335
 
3336
                        continue;
3337
                }
3338
 
3339
                //USER set rank
3340
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
3341
 
3342
                //USER precharge all banks...
3343
 
3344
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_PRECHARGE_ALL);
3345
 
3346
                //USER load up MR settings specified by user
3347
 
3348
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR1_USER);
3349
 
3350
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR2);
3351
 
3352
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR3);
3353
        }
3354
}
3355
#endif //USER LPDDR2
3356
 
3357
#if LPDDR1
3358
void rw_mgr_mem_handoff (void)
3359
{
3360
        alt_u32 r;
3361
 
3362
        TRACE_FUNC();
3363
 
3364
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
3365
                if (param->skip_ranks[r]) {
3366
                        //USER request to skip the rank
3367
 
3368
                        continue;
3369
                }
3370
 
3371
                //USER set rank
3372
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
3373
 
3374
                //USER precharge all banks ... 
3375
 
3376
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_PRECHARGE_ALL);
3377
 
3378
                //USER load up MR settings specified by user 
3379
 
3380
                // FIXME BEN: for HHP, we need to add delay loops to be sure
3381
                // We can check this with BFM perhaps
3382
                // Likely enough delay in RW_MGR though
3383
 
3384
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_EMR);
3385
 
3386
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MR_USER);
3387
 
3388
                //USER need to wait tMOD (12CK or 15ns) time before issuing other commands,
3389
                //USER but we will have plenty of NIOS cycles before actual handoff so its okay.
3390
        }
3391
}
3392
#endif //USER LPDDR1
3393
 
3394
#if RLDRAMII
3395
void rw_mgr_mem_handoff (void)
3396
{
3397
        TRACE_FUNC();
3398
 
3399
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS);
3400
}
3401
#endif
3402
 
3403
#if RLDRAM3
3404
void rw_mgr_mem_handoff (void)
3405
{
3406
        TRACE_FUNC();
3407
        alt_u32 r;
3408
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
3409
                if (param->skip_ranks[r]) {
3410
                        //USER request to skip the rank
3411
                        continue;
3412
                }
3413
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
3414
 
3415
                //USER Load user requested MR1
3416
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS1);
3417
        }
3418
 
3419
        if ( RW_MGR_MEM_NUMBER_OF_RANKS == 1 ) {
3420
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFE);
3421
        } else if ( RW_MGR_MEM_NUMBER_OF_RANKS == 2 ) {
3422
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFC);
3423
        } else if ( RW_MGR_MEM_NUMBER_OF_RANKS == 4 ) {
3424
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xF0);
3425
        }
3426
        else {
3427
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, 0xFE);
3428
        }
3429
        //USER Load user requested MR2
3430
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_MRS2);
3431
 
3432
        //USER Wait MRSC and a bit more
3433
        delay_for_n_mem_clocks(64);
3434
}
3435
#endif
3436
 
3437
#if QDRII
3438
void rw_mgr_mem_handoff (void)
3439
{
3440
        TRACE_FUNC();
3441
}
3442
#endif
3443
 
3444
#if DDRX
3445
//USER performs a guaranteed read on the patterns we are going to use during a read test to ensure memory works
3446
alt_u32 rw_mgr_mem_calibrate_read_test_patterns (alt_u32 rank_bgn, alt_u32 group, alt_u32 num_tries, t_btfld *bit_chk, alt_u32 all_ranks)
3447
{
3448
        alt_u32 r, vg;
3449
        t_btfld correct_mask_vg;
3450
        t_btfld tmp_bit_chk;
3451
        alt_u32 rank_end = all_ranks ? RW_MGR_MEM_NUMBER_OF_RANKS : (rank_bgn + NUM_RANKS_PER_SHADOW_REG);
3452
 
3453
        *bit_chk = param->read_correct_mask;
3454
        correct_mask_vg = param->read_correct_mask_vg;
3455
 
3456
        for (r = rank_bgn; r < rank_end; r++) {
3457
                if (param->skip_ranks[r]) {
3458
                        //USER request to skip the rank
3459
 
3460
                        continue;
3461
                }
3462
 
3463
                //USER set rank
3464
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_READ_WRITE);
3465
 
3466
                //USER Load up a constant bursts of read commands
3467
 
3468
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x20);
3469
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_GUARANTEED_READ);
3470
 
3471
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x20);
3472
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_GUARANTEED_READ_CONT);
3473
 
3474
                tmp_bit_chk = 0;
3475
                for (vg = RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS-1; ; vg--)
3476
                {
3477
                        //USER reset the fifos to get pointers to known state
3478
 
3479
                        IOWR_32DIRECT (PHY_MGR_CMD_FIFO_RESET, 0, 0);
3480
                        IOWR_32DIRECT (RW_MGR_RESET_READ_DATAPATH, 0, 0);
3481
 
3482
                        tmp_bit_chk = tmp_bit_chk << (RW_MGR_MEM_DQ_PER_READ_DQS / RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS);
3483
 
3484
                        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, ((group*RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS+vg) << 2), __RW_MGR_GUARANTEED_READ);
3485
                        tmp_bit_chk = tmp_bit_chk | (correct_mask_vg & ~(IORD_32DIRECT(BASE_RW_MGR, 0)));
3486
 
3487
                        if (vg == 0) {
3488
                                break;
3489
                        }
3490
                }
3491
                *bit_chk &= tmp_bit_chk;
3492
        }
3493
 
3494
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, (group << 2), __RW_MGR_CLEAR_DQS_ENABLE);
3495
 
3496
        set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
3497
        DPRINT(2, "test_load_patterns(%lu,ALL) => (%lu == %lu) => %lu", group, *bit_chk, param->read_correct_mask, (long unsigned int)(*bit_chk == param->read_correct_mask));
3498
        return (*bit_chk == param->read_correct_mask);
3499
}
3500
 
3501
alt_u32 rw_mgr_mem_calibrate_read_test_patterns_all_ranks (alt_u32 group, alt_u32 num_tries, t_btfld *bit_chk)
3502
{
3503
        if (rw_mgr_mem_calibrate_read_test_patterns (0, group, num_tries, bit_chk, 1))
3504
        {
3505
                return 1;
3506
        }
3507
        else
3508
        {
3509
                // case:139851 - if guaranteed read fails, we can retry using different dqs enable phases.
3510
                // It is possible that with the initial phase, dqs enable is asserted/deasserted too close 
3511
                // to an dqs edge, truncating the read burst.
3512
                alt_u32 p;
3513
                for (p = 0; p <= IO_DQS_EN_PHASE_MAX; p++) {
3514
                        scc_mgr_set_dqs_en_phase_all_ranks (group, p);
3515
                        if (rw_mgr_mem_calibrate_read_test_patterns (0, group, num_tries, bit_chk, 1))
3516
                        {
3517
                                return 1;
3518
                        }
3519
                }
3520
                return 0;
3521
        }
3522
}
3523
#endif
3524
 
3525
//USER load up the patterns we are going to use during a read test 
3526
#if DDRX
3527
void rw_mgr_mem_calibrate_read_load_patterns (alt_u32 rank_bgn, alt_u32 all_ranks)
3528
{
3529
        alt_u32 r;
3530
        alt_u32 rank_end = all_ranks ? RW_MGR_MEM_NUMBER_OF_RANKS : (rank_bgn + NUM_RANKS_PER_SHADOW_REG);
3531
 
3532
        TRACE_FUNC();
3533
 
3534
        for (r = rank_bgn; r < rank_end; r++) {
3535
                if (param->skip_ranks[r]) {
3536
                        //USER request to skip the rank
3537
 
3538
                        continue;
3539
                }
3540
 
3541
                //USER set rank
3542
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_READ_WRITE);
3543
 
3544
                //USER Load up a constant bursts
3545
 
3546
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x20);
3547
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_GUARANTEED_WRITE_WAIT0);
3548
 
3549
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x20);
3550
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_GUARANTEED_WRITE_WAIT1);
3551
 
3552
#if QUARTER_RATE
3553
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0x01);
3554
#endif          
3555
#if HALF_RATE
3556
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0x02);
3557
#endif          
3558
#if FULL_RATE
3559
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0x04);
3560
#endif
3561
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_GUARANTEED_WRITE_WAIT2);
3562
 
3563
#if QUARTER_RATE
3564
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_3, 0, 0x01);
3565
#endif          
3566
#if HALF_RATE
3567
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_3, 0, 0x02);
3568
#endif          
3569
#if FULL_RATE
3570
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_3, 0, 0x04);
3571
#endif
3572
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_3, 0, __RW_MGR_GUARANTEED_WRITE_WAIT3);
3573
 
3574
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_GUARANTEED_WRITE);
3575
        }
3576
 
3577
        set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
3578
}
3579
#endif
3580
 
3581
#if QDRII
3582
void rw_mgr_mem_calibrate_read_load_patterns (alt_u32 rank_bgn, alt_u32 all_ranks)
3583
{
3584
        TRACE_FUNC();
3585
 
3586
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x20);
3587
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_GUARANTEED_WRITE_WAIT0);
3588
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x20);
3589
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_GUARANTEED_WRITE_WAIT1);
3590
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_GUARANTEED_WRITE);
3591
}
3592
#endif
3593
 
3594
#if RLDRAMX
3595
void rw_mgr_mem_calibrate_read_load_patterns (alt_u32 rank_bgn, alt_u32 all_ranks)
3596
{
3597
        TRACE_FUNC();
3598
        alt_u32 r;
3599
        alt_u32 rank_end = RW_MGR_MEM_NUMBER_OF_RANKS;//all_ranks ? RW_MGR_MEM_NUMBER_OF_RANKS : (rank_bgn + NUM_RANKS_PER_SHADOW_REG);
3600
#if QUARTER_RATE        
3601
        alt_u32 write_data_cycles = 0x10;
3602
#else
3603
        alt_u32 write_data_cycles = 0x20;
3604
#endif
3605
 
3606
        for (r = rank_bgn; r < rank_end; r++) {
3607
        if (param->skip_ranks[r]) {
3608
                //USER request to skip the rank
3609
 
3610
                continue;
3611
        }
3612
 
3613
                //USER set rank
3614
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_READ_WRITE);
3615
 
3616
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, write_data_cycles);
3617
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_GUARANTEED_WRITE_WAIT0);
3618
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, write_data_cycles);
3619
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_GUARANTEED_WRITE_WAIT1);
3620
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, write_data_cycles);
3621
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_GUARANTEED_WRITE_WAIT2);
3622
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_3, 0, write_data_cycles);
3623
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_3, 0, __RW_MGR_GUARANTEED_WRITE_WAIT3);
3624
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_GUARANTEED_WRITE);
3625
        }
3626
        set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
3627
}
3628
#endif
3629
 
3630
static inline void rw_mgr_mem_calibrate_read_load_patterns_all_ranks (void)
3631
{
3632
        rw_mgr_mem_calibrate_read_load_patterns (0, 1);
3633
}
3634
 
3635
 
3636
// pe checkout pattern for harden managers
3637
//void pe_checkout_pattern (void)
3638
//{
3639
//    // test RW manager
3640
//    
3641
//    // do some reads to check load buffer
3642
//      IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x0);
3643
//      IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_READ_B2B_WAIT1);
3644
//
3645
//      IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0x0);
3646
//      IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_READ_B2B_WAIT2);
3647
//              
3648
//      IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x0);
3649
//      IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_READ_B2B);
3650
//      
3651
//      IOWR_32DIRECT (RW_MGR_LOAD_CNTR_3, 0, 0x0);
3652
//      IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_3, 0, __RW_MGR_READ_B2B);
3653
//      
3654
//      // clear error word
3655
//      IOWR_32DIRECT (RW_MGR_RESET_READ_DATAPATH, 0, 0);
3656
//      
3657
//      IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_READ_B2B);
3658
//      
3659
//      alt_u32 readdata;
3660
//      
3661
//      // read error word
3662
//      readdata = IORD_32DIRECT(BASE_RW_MGR, 0);
3663
//      
3664
//      // read DI buffer
3665
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 0*4, 0);
3666
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 1*4, 0);
3667
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 2*4, 0);
3668
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 3*4, 0);
3669
//      
3670
//      IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x0);
3671
//      IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_READ_B2B_WAIT1);
3672
//
3673
//      IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0x0);
3674
//      IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_READ_B2B_WAIT2);
3675
//              
3676
//      IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x0);
3677
//      IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_READ_B2B);
3678
//      
3679
//      IOWR_32DIRECT (RW_MGR_LOAD_CNTR_3, 0, 0x0);
3680
//      IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_3, 0, __RW_MGR_READ_B2B);
3681
//      
3682
//      // clear error word
3683
//      IOWR_32DIRECT (RW_MGR_RESET_READ_DATAPATH, 0, 0);
3684
//      
3685
//      // do read
3686
//      IOWR_32DIRECT (RW_MGR_LOOPBACK_MODE, 0, __RW_MGR_READ_B2B);
3687
//      
3688
//      // read error word
3689
//      readdata = IORD_32DIRECT(BASE_RW_MGR, 0);
3690
//      
3691
//      // error word should be 0x00
3692
//      
3693
//      // read DI buffer
3694
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 0*4, 0);
3695
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 1*4, 0);
3696
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 2*4, 0);
3697
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 3*4, 0);
3698
//      
3699
//      // clear error word
3700
//      IOWR_32DIRECT (RW_MGR_RESET_READ_DATAPATH, 0, 0);
3701
//      
3702
//      // do dm read   
3703
//      IOWR_32DIRECT (RW_MGR_LOOPBACK_MODE, 0, __RW_MGR_LFSR_WR_RD_DM_BANK_0_WL_1);
3704
//      
3705
//      // read error word
3706
//      readdata = IORD_32DIRECT(BASE_RW_MGR, 0);
3707
//      
3708
//      // error word should be ff
3709
//      
3710
//      // read DI buffer
3711
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 0*4, 0);
3712
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 1*4, 0);
3713
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 2*4, 0);
3714
//      readdata = IORD_32DIRECT(RW_MGR_DI_BASE + 3*4, 0);
3715
//      
3716
//      // exit loopback mode
3717
//      IOWR_32DIRECT (BASE_RW_MGR, 0, __RW_MGR_IDLE_LOOP2);
3718
//      
3719
//      // start of phy manager access
3720
//      
3721
//      readdata = IORD_32DIRECT (PHY_MGR_MAX_RLAT_WIDTH, 0);
3722
//      readdata = IORD_32DIRECT (PHY_MGR_MAX_AFI_WLAT_WIDTH, 0);
3723
//      readdata = IORD_32DIRECT (PHY_MGR_MAX_AFI_RLAT_WIDTH, 0);
3724
//      readdata = IORD_32DIRECT (PHY_MGR_CALIB_SKIP_STEPS, 0);
3725
//      readdata = IORD_32DIRECT (PHY_MGR_CALIB_VFIFO_OFFSET, 0);       
3726
//      readdata = IORD_32DIRECT (PHY_MGR_CALIB_LFIFO_OFFSET, 0);
3727
//      
3728
//      // start of data manager test
3729
//      
3730
//      readdata = IORD_32DIRECT (DATA_MGR_DRAM_CFG         , 0);
3731
//      readdata = IORD_32DIRECT (DATA_MGR_MEM_T_WL         , 0);
3732
//      readdata = IORD_32DIRECT (DATA_MGR_MEM_T_ADD    , 0);
3733
//      readdata = IORD_32DIRECT (DATA_MGR_MEM_T_RL         , 0);
3734
//      readdata = IORD_32DIRECT (DATA_MGR_MEM_T_RFC    , 0);
3735
//      readdata = IORD_32DIRECT (DATA_MGR_MEM_T_REFI   , 0);
3736
//      readdata = IORD_32DIRECT (DATA_MGR_MEM_T_WR         , 0);
3737
//      readdata = IORD_32DIRECT (DATA_MGR_MEM_T_MRD    , 0);
3738
//      readdata = IORD_32DIRECT (DATA_MGR_COL_WIDTH    , 0);
3739
//      readdata = IORD_32DIRECT (DATA_MGR_ROW_WIDTH    , 0);
3740
//      readdata = IORD_32DIRECT (DATA_MGR_BANK_WIDTH   , 0);
3741
//      readdata = IORD_32DIRECT (DATA_MGR_CS_WIDTH         , 0);
3742
//      readdata = IORD_32DIRECT (DATA_MGR_ITF_WIDTH    , 0);
3743
//      readdata = IORD_32DIRECT (DATA_MGR_DVC_WIDTH    , 0);
3744
//      
3745
//}
3746
 
3747
//USER  try a read and see if it returns correct data back. has dummy reads inserted into the mix
3748
//USER  used to align dqs enable. has more thorough checks than the regular read test.
3749
 
3750
alt_u32 rw_mgr_mem_calibrate_read_test (alt_u32 rank_bgn, alt_u32 group, alt_u32 num_tries, alt_u32 all_correct, t_btfld *bit_chk, alt_u32 all_groups, alt_u32 all_ranks)
3751
{
3752
        alt_u32 r, vg;
3753
        t_btfld correct_mask_vg;
3754
        t_btfld tmp_bit_chk;
3755
        alt_u32 rank_end = all_ranks ? RW_MGR_MEM_NUMBER_OF_RANKS : (rank_bgn + NUM_RANKS_PER_SHADOW_REG);
3756
 
3757
#if LRDIMM
3758
        // USER Disable MB Write-levelling mode and enter normal operation
3759
        rw_mgr_lrdimm_rc_program(0,12,0x0);
3760
#endif
3761
 
3762
        *bit_chk = param->read_correct_mask;
3763
        correct_mask_vg = param->read_correct_mask_vg;
3764
 
3765
        alt_u32 quick_read_mode = (((STATIC_CALIB_STEPS) & CALIB_SKIP_DELAY_SWEEPS) && ENABLE_SUPER_QUICK_CALIBRATION) || BFM_MODE;
3766
 
3767
        for (r = rank_bgn; r < rank_end; r++) {
3768
                if (param->skip_ranks[r]) {
3769
                        //USER request to skip the rank
3770
 
3771
                        continue;
3772
                }
3773
 
3774
                //USER set rank
3775
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_READ_WRITE);
3776
 
3777
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x10);
3778
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_READ_B2B_WAIT1);
3779
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0x10);
3780
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_READ_B2B_WAIT2);
3781
 
3782
                if(quick_read_mode) {
3783
                        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x1); /* need at least two (1+1) reads to capture failures */
3784
                } else if (all_groups) {
3785
                        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x06);
3786
                } else {
3787
                        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x32);
3788
                }
3789
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_READ_B2B);
3790
                if(all_groups) {
3791
                        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_3, 0, RW_MGR_MEM_IF_READ_DQS_WIDTH * RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS - 1);
3792
                } else {
3793
                        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_3, 0, 0x0);
3794
                }
3795
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_3, 0, __RW_MGR_READ_B2B);
3796
 
3797
                tmp_bit_chk = 0;
3798
                for (vg = RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS-1; ; vg--)
3799
                {
3800
                        //USER reset the fifos to get pointers to known state 
3801
 
3802
                        IOWR_32DIRECT (PHY_MGR_CMD_FIFO_RESET, 0, 0);
3803
                        IOWR_32DIRECT (RW_MGR_RESET_READ_DATAPATH, 0, 0);
3804
 
3805
                        tmp_bit_chk = tmp_bit_chk << (RW_MGR_MEM_DQ_PER_READ_DQS / RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS);
3806
 
3807
                        IOWR_32DIRECT (all_groups ? RW_MGR_RUN_ALL_GROUPS : RW_MGR_RUN_SINGLE_GROUP, ((group*RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS+vg) << 2), __RW_MGR_READ_B2B);
3808
                        tmp_bit_chk = tmp_bit_chk | (correct_mask_vg & ~(IORD_32DIRECT(BASE_RW_MGR, 0)));
3809
 
3810
                        if (vg == 0) {
3811
                                break;
3812
                        }
3813
                }
3814
                *bit_chk &= tmp_bit_chk;
3815
        }
3816
 
3817
#if ENABLE_BRINGUP_DEBUGGING
3818
        load_di_buf_gbl();
3819
#endif
3820
 
3821
        #if DDRX
3822
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, (group << 2), __RW_MGR_CLEAR_DQS_ENABLE);
3823
        #endif
3824
 
3825
        if (all_correct)
3826
        {
3827
                set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
3828
                DPRINT(2, "read_test(%lu,ALL,%lu) => (%lu == %lu) => %lu", group, all_groups, *bit_chk, param->read_correct_mask, (long unsigned int)(*bit_chk == param->read_correct_mask));
3829
                return (*bit_chk == param->read_correct_mask);
3830
        }
3831
        else
3832
        {
3833
                set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
3834
                DPRINT(2, "read_test(%lu,ONE,%lu) => (%lu != %lu) => %lu", group, all_groups, *bit_chk, (long unsigned int)0, (long unsigned int)(*bit_chk != 0x00));
3835
                return (*bit_chk != 0x00);
3836
        }
3837
}
3838
 
3839
static inline alt_u32 rw_mgr_mem_calibrate_read_test_all_ranks (alt_u32 group, alt_u32 num_tries, alt_u32 all_correct, t_btfld *bit_chk, alt_u32 all_groups)
3840
{
3841
    alt_u32 success = 1;
3842
    alt_u32 one_test_success;
3843
    alt_u32 i = 0;
3844
    if (num_tries <= 0) num_tries = 1;
3845
    for (i = 0; i < num_tries; i++)
3846
    {
3847
        one_test_success = rw_mgr_mem_calibrate_read_test (0, group, 1, all_correct, bit_chk, all_groups, 1);
3848
        success = success & one_test_success;
3849
        if (success == 0)
3850
        {
3851
            break;
3852
        }
3853
    }
3854
 
3855
    return success;
3856
}
3857
 
3858
#if ENABLE_DELAY_CHAIN_WRITE
3859
void rw_mgr_incr_vfifo_auto(alt_u32 grp) {
3860
        alt_u32 v;
3861
        v = vfifo_settings[grp]%VFIFO_SIZE;
3862
        rw_mgr_incr_vfifo(grp, &v);
3863
        vfifo_settings[grp] = v;
3864
}
3865
 
3866
void rw_mgr_decr_vfifo_auto(alt_u32 grp) {
3867
        alt_u32 v;
3868
        v = vfifo_settings[grp]%VFIFO_SIZE;
3869
        rw_mgr_decr_vfifo(grp, &v);
3870
        vfifo_settings[grp] = v;
3871
}
3872
#endif // ENABLE_DELAY_CHAIN_WRITE
3873
 
3874
void rw_mgr_incr_vfifo(alt_u32 grp, alt_u32 *v) {
3875
        //USER fiddle with FIFO 
3876
        if(HARD_PHY) {
3877
                IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_HARD_PHY, 0, grp);
3878
        } else if (QUARTER_RATE_MODE && !HARD_VFIFO) {
3879
                if ((*v & 3) == 3) {
3880
                        IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_QR, 0, grp);
3881
                } else if ((*v & 2) == 2) {
3882
                        IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_FR_HR, 0, grp);
3883
                } else if ((*v & 1) == 1) {
3884
                        IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_HR, 0, grp);
3885
                } else {
3886
                        IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_FR, 0, grp);
3887
                }
3888
        } else if (HARD_VFIFO) {
3889
                // Arria V & Cyclone V have a hard full-rate VFIFO that only has a single incr signal
3890
                IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_FR, 0, grp);
3891
        }
3892
        else {
3893
                if (!HALF_RATE_MODE || (*v & 1) == 1) {
3894
                        IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_HR, 0, grp);
3895
                } else {
3896
                        IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_FR, 0, grp);
3897
                }
3898
        }
3899
 
3900
        (*v)++;
3901
#if USE_DQS_TRACKING && !HHP_HPS
3902
        IOWR_32DIRECT (TRK_V_POINTER, (grp << 2), *v);
3903
#endif
3904
        BFM_INC_VFIFO;
3905
}
3906
 
3907
//Used in quick cal to properly loop through the duplicated VFIFOs in AV QDRII/RLDRAM
3908
static inline void rw_mgr_incr_vfifo_all(alt_u32 grp, alt_u32 *v) {
3909
#if VFIFO_CONTROL_WIDTH_PER_DQS == 1    
3910
        rw_mgr_incr_vfifo(grp, v);
3911
#else
3912
        alt_u32 i;
3913
        for(i = 0; i < VFIFO_CONTROL_WIDTH_PER_DQS; i++) {
3914
                rw_mgr_incr_vfifo(grp*VFIFO_CONTROL_WIDTH_PER_DQS+i, v);
3915
                if(i != 0) {
3916
                        (*v)--;
3917
                }
3918
        }
3919
#endif
3920
}
3921
 
3922
void rw_mgr_decr_vfifo(alt_u32 grp, alt_u32 *v) {
3923
 
3924
        alt_u32 i;
3925
 
3926
        for (i = 0; i < VFIFO_SIZE-1; i++) {
3927
                rw_mgr_incr_vfifo(grp, v);
3928
        }
3929
}
3930
 
3931
//USER find a good dqs enable to use 
3932
 
3933
#if QDRII || RLDRAMX
3934
alt_u32 rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase (alt_u32 grp)
3935
{
3936
        alt_u32 v;
3937
        alt_u32 found;
3938
    alt_u32 dtaps_per_ptap, tmp_delay;
3939
        t_btfld bit_chk;
3940
 
3941
        TRACE_FUNC("%lu", grp);
3942
 
3943
        reg_file_set_sub_stage(CAL_SUBSTAGE_DQS_EN_PHASE);
3944
 
3945
        found = 0;
3946
 
3947
        //USER first push vfifo until we get a passing read 
3948
        for (v = 0; v < VFIFO_SIZE && found == 0;) {
3949
                DPRINT(2, "find_dqs_en_phase: vfifo %lu", BFM_GBL_GET(vfifo_idx));
3950
                if (rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
3951
                        found = 1;
3952
                }
3953
 
3954
                if (!found) {
3955
                        //USER fiddle with FIFO
3956
#if (VFIFO_CONTROL_WIDTH_PER_DQS != 1)
3957
                        alt_u32 i;
3958
                        for (i = 0; i < VFIFO_CONTROL_WIDTH_PER_DQS; i++) {
3959
                                rw_mgr_incr_vfifo(grp*VFIFO_CONTROL_WIDTH_PER_DQS+i, &v);
3960
                                v--; // undo increment of v in rw_mgr_incr_vfifo
3961
                        }
3962
                        v++;    // add back single increment
3963
#else
3964
                        rw_mgr_incr_vfifo(grp, &v);
3965
#endif
3966
                }
3967
        }
3968
 
3969
#if (VFIFO_CONTROL_WIDTH_PER_DQS != 1)
3970
        if (found) {
3971
                // we found a vfifo setting that works for at least one vfifo "group"
3972
                // Some groups may need next vfifo setting, so check each one to
3973
                // see if we get new bits passing by increment the vfifo
3974
                alt_u32 i;
3975
                t_btfld best_bit_chk_inv;
3976
                alt_u8 found_on_first_check = (v == 1);
3977
 
3978
                best_bit_chk_inv = ~bit_chk;
3979
 
3980
                for (i = 0; i < VFIFO_CONTROL_WIDTH_PER_DQS; i++) {
3981
                        rw_mgr_incr_vfifo(grp*VFIFO_CONTROL_WIDTH_PER_DQS+i, &v);
3982
                        v--; // undo increment of v in rw_mgr_incr_vfifo, just in case it matters for next check
3983
                        rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0);
3984
                        if ((bit_chk & best_bit_chk_inv) != 0) {
3985
                                // found some new bits
3986
                                best_bit_chk_inv = ~bit_chk;
3987
                        } else {
3988
                                // no improvement, so put back
3989
                                rw_mgr_decr_vfifo(grp*VFIFO_CONTROL_WIDTH_PER_DQS+i, &v);
3990
                                v++;
3991
                                if (found_on_first_check) {
3992
                                        // found on first vfifo check, so we also need to check earlier vfifo values
3993
                                        rw_mgr_decr_vfifo(grp*VFIFO_CONTROL_WIDTH_PER_DQS+i, &v);
3994
                                        v++; // undo decrement of v in rw_mgr_incr_vfifo, just in case it matters for next check
3995
                                        rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0);
3996
                                        if ((bit_chk & best_bit_chk_inv) != 0) {
3997
                                                // found some new bits
3998
                                                best_bit_chk_inv = ~bit_chk;
3999
                                        } else {
4000
                                                // no improvement, so put back
4001
                                                rw_mgr_incr_vfifo(grp*VFIFO_CONTROL_WIDTH_PER_DQS+i, &v);
4002
                                                v--;
4003
                                        }
4004
                                } // found_on_first_check
4005
                        } // check for new bits
4006
                } // loop over all vfifo control bits
4007
        }
4008
#endif  
4009
 
4010
        if (found) {
4011
                DPRINT(2, "find_dqs_en_phase: found vfifo=%lu", BFM_GBL_GET(vfifo_idx));
4012
                // Not really dqs_enable left/right edge, but close enough for testing purposes
4013
                BFM_GBL_SET(dqs_enable_left_edge[grp].v,BFM_GBL_GET(vfifo_idx));
4014
                BFM_GBL_SET(dqs_enable_right_edge[grp].v,BFM_GBL_GET(vfifo_idx));
4015
                BFM_GBL_SET(dqs_enable_mid[grp].v,BFM_GBL_GET(vfifo_idx));
4016
        } else {
4017
                DPRINT(2, "find_dqs_en_phase: no valid vfifo found");
4018
        }
4019
 
4020
#if ENABLE_TCL_DEBUG
4021
        // FIXME: Not a dynamically calculated value for dtaps_per_ptap
4022
        dtaps_per_ptap = 0;
4023
        tmp_delay = 0;
4024
        while (tmp_delay < IO_DELAY_PER_OPA_TAP) {
4025
                dtaps_per_ptap++;
4026
                tmp_delay += IO_DELAY_PER_DQS_EN_DCHAIN_TAP;
4027
        }
4028
        dtaps_per_ptap--;
4029
        ALTERA_ASSERT(dtaps_per_ptap <= IO_DQS_EN_DELAY_MAX);
4030
 
4031
    TCLRPT_SET(debug_summary_report->computed_dtap_per_ptap, dtaps_per_ptap);
4032
#endif
4033
 
4034
        return found;
4035
}
4036
#endif
4037
 
4038
#if DDRX
4039
#if NEWVERSION_DQSEN
4040
 
4041
// Navid's version 
4042
 
4043
alt_u32 rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase (alt_u32 grp)
4044
{
4045
        alt_u32 i, d, v, p, sr, j;
4046
        alt_u32 max_working_cnt;
4047
        alt_u32 fail_cnt;
4048
        t_btfld bit_chk;
4049
        alt_u32 dtaps_per_ptap;
4050
        alt_u32 found_begin, found_end;
4051
        alt_u32 work_bgn, work_mid, work_end, tmp_delay;
4052
        alt_u32 test_status;
4053
        alt_u32 found_passing_read, found_failing_read, initial_failing_dtap;
4054
#if RUNTIME_CAL_REPORT
4055
        alt_u32 start_v[NUM_SHADOW_REGS], start_p[NUM_SHADOW_REGS], start_d[NUM_SHADOW_REGS];
4056
        alt_u32 end_v[NUM_SHADOW_REGS], end_p[NUM_SHADOW_REGS], end_d[NUM_SHADOW_REGS];
4057
        for(sr = 0; sr < NUM_SHADOW_REGS; sr++)  {
4058
                start_v[sr] = 0;
4059
                start_p[sr] = 0;
4060
                start_d[sr] = 0;
4061
        }
4062
#endif  
4063
 
4064
        TRACE_FUNC("%lu", grp);
4065
        BFM_STAGE("find_dqs_en_phase");
4066
        ALTERA_ASSERT(grp < RW_MGR_MEM_IF_READ_DQS_WIDTH);
4067
 
4068
        reg_file_set_sub_stage(CAL_SUBSTAGE_VFIFO_CENTER);
4069
 
4070
        scc_mgr_set_dqs_en_delay_all_ranks(grp, 0);
4071
#if SKIP_PTAP_0_DQS_EN_CAL
4072
        scc_mgr_set_dqs_en_phase_all_ranks(grp, 1);
4073
#else
4074
        scc_mgr_set_dqs_en_phase_all_ranks(grp, 0);
4075
#endif
4076
 
4077
        fail_cnt = 0;
4078
 
4079
        //USER **************************************************************
4080
        //USER * Step 0 : Determine number of delay taps for each phase tap *
4081
 
4082
        dtaps_per_ptap = 0;
4083
        tmp_delay = 0;
4084
        while (tmp_delay < IO_DELAY_PER_OPA_TAP) {
4085
                dtaps_per_ptap++;
4086
                tmp_delay += IO_DELAY_PER_DQS_EN_DCHAIN_TAP;
4087
        }
4088
        dtaps_per_ptap--;
4089
        ALTERA_ASSERT(dtaps_per_ptap <= IO_DQS_EN_DELAY_MAX);
4090
        tmp_delay = 0;
4091
        TCLRPT_SET(debug_summary_report->computed_dtap_per_ptap, dtaps_per_ptap);
4092
 
4093
        // VFIFO sweep
4094
#if ENABLE_DQSEN_SWEEP
4095
        init_di_buffer();
4096
        work_bgn = 0;
4097
        for (d = 0; d <= dtaps_per_ptap; d++, tmp_delay += IO_DELAY_PER_DQS_EN_DCHAIN_TAP) {
4098
                work_bgn = tmp_delay;
4099
                scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4100
 
4101
                for (i = 0; i < VFIFO_SIZE; i++) {
4102
                        for (p = 0; p <= IO_DQS_EN_PHASE_MAX; p++, work_bgn += IO_DELAY_PER_OPA_TAP) {
4103
                                DPRINT(2, "find_dqs_en_phase: begin: vfifo=%lu ptap=%lu dtap=%lu", BFM_GBL_GET(vfifo_idx), p, d);
4104
                                scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
4105
 
4106
                                test_status = rw_mgr_mem_calibrate_read_test_all_ranks (grp, 5, PASS_ONE_BIT, &bit_chk, 0);
4107
 
4108
                                //if (p ==0 && d == 0)
4109
                                sample_di_data(bit_chk, work_bgn, d, i, p);
4110
                        }
4111
                        //Increment FIFO
4112
                        rw_mgr_incr_vfifo(grp, &v);
4113
                }
4114
 
4115
                work_bgn++;
4116
        }
4117
        flag_di_buffer_done();
4118
#endif
4119
 
4120
        //USER *********************************************************
4121
        //USER * Step 1 : First push vfifo until we get a failing read *
4122
        for (v = 0; v < VFIFO_SIZE; ) {
4123
                DPRINT(2, "find_dqs_en_phase: vfifo %lu", BFM_GBL_GET(vfifo_idx));
4124
                test_status = rw_mgr_mem_calibrate_read_test_all_ranks (grp, 5, PASS_ONE_BIT, &bit_chk, 0);
4125
                if (!test_status) {
4126
                        fail_cnt++;
4127
 
4128
                        if (fail_cnt == 2) {
4129
                                break;
4130
                        }
4131
                }
4132
 
4133
                //USER fiddle with FIFO
4134
                rw_mgr_incr_vfifo(grp, &v);
4135
        }
4136
 
4137
        if (v >= VFIFO_SIZE) {
4138
                //USER no failing read found!! Something must have gone wrong
4139
                DPRINT(2, "find_dqs_en_phase: vfifo failed");
4140
                return 0;
4141
        }
4142
 
4143
        max_working_cnt = 0;
4144
 
4145
        //USER ********************************************************
4146
        //USER * step 2: find first working phase, increment in ptaps *
4147
        found_begin = 0;
4148
        work_bgn = 0;
4149
        for (d = 0; d <= dtaps_per_ptap; d++, tmp_delay += IO_DELAY_PER_DQS_EN_DCHAIN_TAP) {
4150
                work_bgn = tmp_delay;
4151
                scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4152
 
4153
                for (i = 0; i < VFIFO_SIZE; i++) {
4154
                        for (p = 0; p <= IO_DQS_EN_PHASE_MAX; p++, work_bgn += IO_DELAY_PER_OPA_TAP) {
4155
#if SKIP_PTAP_0_DQS_EN_CAL
4156
                                // Skip p == 0 setting for HARD PHY
4157
                                if (p == 0) {
4158
                                        continue;
4159
                                }
4160
#endif                          
4161
                                DPRINT(2, "find_dqs_en_phase: begin: vfifo=%lu ptap=%lu dtap=%lu", BFM_GBL_GET(vfifo_idx), p, d);
4162
                                scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
4163
 
4164
                                test_status = rw_mgr_mem_calibrate_read_test_all_ranks (grp, 5, PASS_ONE_BIT, &bit_chk, 0);
4165
 
4166
                                if (test_status) {
4167
                                        max_working_cnt = 1;
4168
                                        found_begin = 1;
4169
                                        break;
4170
                                }
4171
                        }
4172
 
4173
                        if (found_begin) {
4174
                                break;
4175
                        }
4176
 
4177
                        if (p > IO_DQS_EN_PHASE_MAX) {
4178
                                //USER fiddle with FIFO
4179
                                rw_mgr_incr_vfifo(grp, &v);
4180
                        }
4181
                }
4182
 
4183
                if (found_begin) {
4184
                        break;
4185
                }
4186
        }
4187
 
4188
        if (i >= VFIFO_SIZE) {
4189
                //USER cannot find working solution 
4190
                DPRINT(2, "find_dqs_en_phase: no vfifo/ptap/dtap");
4191
                return 0;
4192
        }
4193
 
4194
        work_end = work_bgn;
4195
 
4196
        //USER  If d is 0 then the working window covers a phase tap and we can follow the old procedure
4197
        //USER  otherwise, we've found the beginning, and we need to increment the dtaps until we find the end 
4198
        if (d == 0) {
4199
                //USER ********************************************************************
4200
                //USER * step 3a: if we have room, back off by one and increment in dtaps *
4201
                COV(EN_PHASE_PTAP_OVERLAP);
4202
 
4203
                //USER Special case code for backing up a phase 
4204
                if (p == 0) {
4205
                        p = IO_DQS_EN_PHASE_MAX ;
4206
                        rw_mgr_decr_vfifo(grp, &v);
4207
                } else {
4208
                        p = p - 1;
4209
                }
4210
                tmp_delay = work_bgn - IO_DELAY_PER_OPA_TAP;
4211
 
4212
                // For HARD EMIF we increase the phase if p == 0 as we can't set that value
4213
#if SKIP_PTAP_0_DQS_EN_CAL      
4214
                if (p == 0) {
4215
                        p = 1;
4216
                        tmp_delay = work_bgn;
4217
                }
4218
#endif
4219
                scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
4220
 
4221
                found_begin = 0;
4222
                for (d = 0; d <= IO_DQS_EN_DELAY_MAX && tmp_delay < work_bgn; d++, tmp_delay += IO_DELAY_PER_DQS_EN_DCHAIN_TAP) {
4223
 
4224
                        DPRINT(2, "find_dqs_en_phase: begin-2: vfifo=%lu ptap=%lu dtap=%lu", BFM_GBL_GET(vfifo_idx), p, d);
4225
 
4226
                        scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4227
 
4228
                        if (rw_mgr_mem_calibrate_read_test_all_ranks (grp, 5, PASS_ONE_BIT, &bit_chk, 0)) {
4229
                                found_begin = 1;
4230
                                work_bgn = tmp_delay;
4231
                                break;
4232
                        }
4233
                }
4234
 
4235
#if BFM_MODE
4236
                {
4237
                        alt_32 p2, v2, d2;
4238
 
4239
                        // print out where the actual beginning is
4240
                        if (found_begin) {
4241
                                v2 = BFM_GBL_GET(vfifo_idx);
4242
                                p2 = p;
4243
                                d2 = d;
4244
                        } else if (p == IO_DQS_EN_PHASE_MAX) {
4245
                                v2 = (BFM_GBL_GET(vfifo_idx) + 1) % VFIFO_SIZE;
4246
#if SKIP_PTAP_0_DQS_EN_CAL
4247
                                p2 = 1;
4248
#else
4249
                                p2 = 0;
4250
#endif
4251
                                d2 = 0;
4252
                        } else {
4253
                                v2 = BFM_GBL_GET(vfifo_idx);
4254
                                p2 = p + 1;
4255
                                d2 = 0;
4256
                        }
4257
 
4258
                        DPRINT(2, "find_dqs_en_phase: begin found: vfifo=%lu ptap=%lu dtap=%lu begin=%lu",
4259
                               v2, p2, d2, work_bgn);
4260
                        BFM_GBL_SET(dqs_enable_left_edge[grp].v,v2);
4261
                        BFM_GBL_SET(dqs_enable_left_edge[grp].p,p2);
4262
                        BFM_GBL_SET(dqs_enable_left_edge[grp].d,d2);
4263
                        BFM_GBL_SET(dqs_enable_left_edge[grp].ps,work_bgn);
4264
                }
4265
#endif
4266
                // Record the debug data
4267
                // Currently dqsen is the same for all ranks
4268
                for (sr = 0; sr < NUM_SHADOW_REGS; sr++)
4269
                {
4270
                        TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].work_begin, work_bgn);
4271
                if (found_begin)
4272
                {
4273
                                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].phase_begin, p);
4274
                                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].delay_begin, d);
4275
                                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].vfifo_begin, v % VFIFO_SIZE);
4276
#if RUNTIME_CAL_REPORT
4277
                                start_v[sr] = v % VFIFO_SIZE;
4278
                                start_p[sr] = p;
4279
                                start_d[sr] = d;
4280
#endif
4281
                }
4282
                else if (p == IO_DQS_EN_PHASE_MAX)
4283
                {
4284
                                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].phase_begin, 0);
4285
                                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].delay_begin, 0);
4286
                                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].vfifo_begin, (v+1) % VFIFO_SIZE);
4287
#if RUNTIME_CAL_REPORT
4288
                                start_v[sr] = (v+1) % VFIFO_SIZE;
4289
                                start_p[sr] = p;
4290
                                start_d[sr] = d;
4291
#endif
4292
                }
4293
                else
4294
                {
4295
                                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].phase_begin, p+1);
4296
                                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].delay_begin, 0);
4297
                                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].vfifo_begin, v % VFIFO_SIZE);
4298
#if RUNTIME_CAL_REPORT
4299
                                start_v[sr] = v % VFIFO_SIZE;
4300
                                start_p[sr] = p+1;
4301
                                start_d[sr] = d;
4302
#endif
4303
                        }
4304
                }
4305
 
4306
                //USER We have found a working dtap before the ptap found above 
4307
                if (found_begin == 1) {
4308
                        max_working_cnt++;
4309
                }
4310
 
4311
                //USER Restore VFIFO to old state before we decremented it (if needed)
4312
                p = p + 1;
4313
                if (p > IO_DQS_EN_PHASE_MAX) {
4314
                        p = 0;
4315
                        rw_mgr_incr_vfifo(grp, &v);
4316
                }
4317
 
4318
                scc_mgr_set_dqs_en_delay_all_ranks(grp, 0);
4319
 
4320
                //USER ***********************************************************************************
4321
                //USER * step 4a: go forward from working phase to non working phase, increment in ptaps *
4322
                p = p + 1;
4323
                work_end += IO_DELAY_PER_OPA_TAP;
4324
                if (p > IO_DQS_EN_PHASE_MAX) {
4325
                        //USER fiddle with FIFO
4326
                        p = 0;
4327
                        rw_mgr_incr_vfifo(grp, &v);
4328
                }
4329
 
4330
                j = 0;
4331
 
4332
                found_end = 0;
4333
                for (; i < VFIFO_SIZE + 1; i++) {
4334
                        for (; p <= IO_DQS_EN_PHASE_MAX; p++, work_end += IO_DELAY_PER_OPA_TAP) {
4335
                                DPRINT(2, "find_dqs_en_phase: end: vfifo=%lu ptap=%lu dtap=%lu", BFM_GBL_GET(vfifo_idx), p, (long unsigned int)0);
4336
                                j++;
4337
#if SKIP_PTAP_0_DQS_EN_CAL
4338
                                if ( p == 0 ) {
4339
                                        max_working_cnt++;
4340
                                        continue;
4341
                                }
4342
#endif
4343
                                scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
4344
 
4345
                                test_status = rw_mgr_mem_calibrate_read_test_all_ranks (grp, 5, PASS_ONE_BIT, &bit_chk, 0);
4346
 
4347
                                // Check if the first edge we try fails
4348
                                // This indicates that the begin edge that we found was fuzzy, so we adjust the begin edge
4349
                                if (!test_status && (j == 1))
4350
                                {
4351
                                        work_bgn = work_end;
4352
                                }
4353
                                else if (!test_status)
4354
                                {
4355
                                        found_end = 1;
4356
                                        break;
4357
                                } else {
4358
                                        max_working_cnt++;
4359
                                }
4360
                        }
4361
 
4362
                        if (found_end) {
4363
                                break;
4364
                        }
4365
 
4366
                        if (p > IO_DQS_EN_PHASE_MAX) {
4367
                                //USER fiddle with FIFO
4368
                                rw_mgr_incr_vfifo(grp, &v);
4369
                                p = 0;
4370
                        }
4371
                }
4372
 
4373
                if (i >= VFIFO_SIZE + 1) {
4374
                        //USER cannot see edge of failing read 
4375
                        DPRINT(2, "find_dqs_en_phase: end: failed");
4376
                        return 0;
4377
                }
4378
 
4379
                //USER *********************************************************
4380
                //USER * step 5a:  back off one from last, increment in dtaps  *
4381
 
4382
                //USER Special case code for backing up a phase 
4383
#if SKIP_PTAP_0_DQS_EN_CAL      
4384
                if (p == 1) {
4385
                        p = 0;
4386
                        work_end -= IO_DELAY_PER_OPA_TAP;
4387
                        max_working_cnt--;
4388
                }
4389
#endif
4390
                if (p == 0) {
4391
                        p = IO_DQS_EN_PHASE_MAX;
4392
                        rw_mgr_decr_vfifo(grp, &v);
4393
                } else {
4394
                        p = p - 1;
4395
                }
4396
 
4397
                work_end -= IO_DELAY_PER_OPA_TAP;
4398
                scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
4399
 
4400
                //USER * The actual increment of dtaps is done outside of the if/else loop to share code
4401
                d = 0;
4402
 
4403
                DPRINT(2, "find_dqs_en_phase: found end v/p: vfifo=%lu ptap=%lu", BFM_GBL_GET(vfifo_idx), p);
4404
        } else {
4405
 
4406
                // We should not be hitting this case as the window should be around one clock cycle wide
4407
 
4408
                //USER ********************************************************************
4409
                //USER * step 3-5b:  Find the right edge of the window using delay taps   *             
4410
                COV(EN_PHASE_PTAP_NO_OVERLAP);
4411
 
4412
                DPRINT(2, "find_dqs_en_phase: begin found: vfifo=%lu ptap=%lu dtap=%lu begin=%lu", BFM_GBL_GET(vfifo_idx), p, d, work_bgn);
4413
                BFM_GBL_SET(dqs_enable_left_edge[grp].v,BFM_GBL_GET(vfifo_idx));
4414
                BFM_GBL_SET(dqs_enable_left_edge[grp].p,p);
4415
                BFM_GBL_SET(dqs_enable_left_edge[grp].d,d);
4416
                BFM_GBL_SET(dqs_enable_left_edge[grp].ps,work_bgn);
4417
 
4418
                work_end = work_bgn;
4419
 
4420
                //USER * The actual increment of dtaps is done outside of the if/else loop to share code
4421
 
4422
                //USER Only here to counterbalance a subtract later on which is not needed if this branch
4423
                //USER  of the algorithm is taken 
4424
                max_working_cnt++;
4425
        }
4426
 
4427
        //USER The dtap increment to find the failing edge is done here
4428
        for (; d <= IO_DQS_EN_DELAY_MAX; d++, work_end += IO_DELAY_PER_DQS_EN_DCHAIN_TAP) {
4429
 
4430
                        DPRINT(2, "find_dqs_en_phase: end-2: dtap=%lu", d);
4431
                        scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4432
 
4433
                        if (!rw_mgr_mem_calibrate_read_test_all_ranks (grp, 5, PASS_ONE_BIT, &bit_chk, 0)) {
4434
                                break;
4435
                        }
4436
                }
4437
 
4438
        //USER Go back to working dtap 
4439
        if (d != 0) {
4440
                work_end -= IO_DELAY_PER_DQS_EN_DCHAIN_TAP;
4441
        }
4442
 
4443
        DPRINT(2, "find_dqs_en_phase: found end v/p/d: vfifo=%lu ptap=%lu dtap=%lu end=%lu", BFM_GBL_GET(vfifo_idx), p, d-1, work_end);
4444
        BFM_GBL_SET(dqs_enable_right_edge[grp].v,BFM_GBL_GET(vfifo_idx));
4445
        BFM_GBL_SET(dqs_enable_right_edge[grp].p,p);
4446
        BFM_GBL_SET(dqs_enable_right_edge[grp].d,d-1);
4447
        BFM_GBL_SET(dqs_enable_right_edge[grp].ps,work_end);
4448
 
4449
        // Record the debug data
4450
        for (sr = 0; sr < NUM_SHADOW_REGS; sr++)
4451
        {
4452
                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].work_end, work_end);
4453
                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].phase_end, p);
4454
                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].delay_end, d-1);
4455
                TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].vfifo_end, v % VFIFO_SIZE);
4456
#if RUNTIME_CAL_REPORT
4457
                end_v[sr] = v % VFIFO_SIZE;
4458
                end_p[sr] = p;
4459
                end_d[sr] = d-1;
4460
#endif
4461
        }
4462
 
4463
        if (work_end >= work_bgn) {
4464
                //USER we have a working range 
4465
        } else {
4466
                //USER nil range 
4467
                DPRINT(2, "find_dqs_en_phase: end-2: failed");
4468
                return 0;
4469
        }
4470
 
4471
        DPRINT(2, "find_dqs_en_phase: found range [%lu,%lu]", work_bgn, work_end);
4472
 
4473
#if USE_DQS_TRACKING
4474
        // ***************************************************************
4475
        //USER * We need to calculate the number of dtaps that equal a ptap
4476
        //USER * To do that we'll back up a ptap and re-find the edge of the 
4477
        //USER * window using dtaps
4478
 
4479
        DPRINT(2, "find_dqs_en_phase: calculate dtaps_per_ptap for tracking");
4480
 
4481
        //USER Special case code for backing up a phase 
4482
 
4483
#if SKIP_PTAP_0_DQS_EN_CAL      
4484
        if (p == 0 || p == 1) {
4485
#else
4486
        if (p == 0) {
4487
#endif
4488
                p = IO_DQS_EN_PHASE_MAX;
4489
                rw_mgr_decr_vfifo(grp, &v);
4490
                DPRINT(2, "find_dqs_en_phase: backed up cycle/phase: v=%lu p=%lu", BFM_GBL_GET(vfifo_idx), p);
4491
        } else {
4492
                p = p - 1;
4493
                DPRINT(2, "find_dqs_en_phase: backed up phase only: v=%lu p=%lu", BFM_GBL_GET(vfifo_idx), p);
4494
        }
4495
 
4496
        scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
4497
 
4498
        //USER Increase dtap until we first see a passing read (in case the window is smaller than a ptap),
4499
        //USER and then a failing read to mark the edge of the window again
4500
 
4501
        //USER Find a passing read
4502
        DPRINT(2, "find_dqs_en_phase: find passing read");
4503
        found_passing_read = 0;
4504
        found_failing_read = 0;
4505
        initial_failing_dtap = d;
4506
        for (; d <= IO_DQS_EN_DELAY_MAX; d++) {
4507
                DPRINT(2, "find_dqs_en_phase: testing read d=%lu", d);
4508
                scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4509
 
4510
                if (rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4511
                        found_passing_read = 1;
4512
                        break;
4513
                }
4514
        }
4515
 
4516
        if (found_passing_read) {
4517
           //USER Find a failing read 
4518
           DPRINT(2, "find_dqs_en_phase: find failing read");
4519
           for (d = d + 1; d <= IO_DQS_EN_DELAY_MAX; d++) {
4520
                DPRINT(2, "find_dqs_en_phase: testing read d=%lu", d);
4521
                scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4522
 
4523
                if (!rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4524
                        found_failing_read = 1;
4525
                        break;
4526
                }
4527
           }
4528
   } else {
4529
      DPRINT(1, "find_dqs_en_phase: failed to calculate dtaps per ptap. Fall back on static value");
4530
        }
4531
 
4532
        //USER The dynamically calculated dtaps_per_ptap is only valid if we found a passing/failing read
4533
        //USER If we didn't, it means d hit the max (IO_DQS_EN_DELAY_MAX).
4534
   //USER Otherwise, dtaps_per_ptap retains its statically calculated value.
4535
        if(found_passing_read && found_failing_read) {
4536
      dtaps_per_ptap = d - initial_failing_dtap;
4537
   }
4538
 
4539
        ALTERA_ASSERT(dtaps_per_ptap <= IO_DQS_EN_DELAY_MAX);
4540
#if HHP_HPS
4541
        IOWR_32DIRECT (REG_FILE_DTAPS_PER_PTAP, 0, dtaps_per_ptap);
4542
#else
4543
        IOWR_32DIRECT (TRK_DTAPS_PER_PTAP, 0, dtaps_per_ptap);
4544
#endif
4545
 
4546
        DPRINT(2, "find_dqs_en_phase: dtaps_per_ptap=%lu - %lu = %lu", d, initial_failing_dtap, dtaps_per_ptap);
4547
#endif
4548
 
4549
        //USER ********************************************
4550
        //USER * step 6:  Find the centre of the window   *
4551
 
4552
        work_mid = (work_bgn + work_end) / 2;
4553
        tmp_delay = 0;
4554
 
4555
        DPRINT(2, "work_bgn=%ld work_end=%ld work_mid=%ld", work_bgn, work_end, work_mid);
4556
        //USER Get the middle delay to be less than a VFIFO delay 
4557
        for (p = 0; p <= IO_DQS_EN_PHASE_MAX; p++, tmp_delay += IO_DELAY_PER_OPA_TAP);
4558
        DPRINT(2, "vfifo ptap delay %ld", tmp_delay);
4559
        while(work_mid > tmp_delay) work_mid -= tmp_delay;
4560
        DPRINT(2, "new work_mid %ld", work_mid);
4561
        tmp_delay = 0;
4562
        for (p = 0; p <= IO_DQS_EN_PHASE_MAX && tmp_delay < work_mid; p++, tmp_delay += IO_DELAY_PER_OPA_TAP);
4563
        tmp_delay -= IO_DELAY_PER_OPA_TAP;
4564
        DPRINT(2, "new p %ld, tmp_delay=%ld", p-1, tmp_delay);
4565
        for (d = 0; d <= IO_DQS_EN_DELAY_MAX && tmp_delay < work_mid; d++, tmp_delay += IO_DELAY_PER_DQS_EN_DCHAIN_TAP);
4566
        DPRINT(2, "new d %ld, tmp_delay=%ld", d, tmp_delay);
4567
 
4568
        // DQSEN same for all shadow reg
4569
        for(sr = 0; sr < NUM_SHADOW_REGS; sr++) {
4570
                TCLRPT_SET(debug_cal_report->cal_dqs_in_margins[sr][grp].dqsen_margin, max_working_cnt -1);
4571
        }
4572
#if SKIP_PTAP_0_DQS_EN_CAL      
4573
                if (p == 1) {
4574
                        // If center lies at p=0 and d=d, then the safest choice is to set the center at p=1 and d=0
4575
                        p = 2;
4576
                        d = 0;
4577
                }
4578
#endif
4579
        scc_mgr_set_dqs_en_phase_all_ranks(grp, p-1);
4580
        scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4581
 
4582
        //USER push vfifo until we can successfully calibrate. We can do this because
4583
        //USER the largest possible margin in 1 VFIFO cycle
4584
 
4585
        for (i = 0; i < VFIFO_SIZE; i++) {
4586
                DPRINT(2, "find_dqs_en_phase: center: vfifo=%lu", BFM_GBL_GET(vfifo_idx));
4587
                if (rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4588
                        break;
4589
                }
4590
 
4591
                //USER fiddle with FIFO
4592
                rw_mgr_incr_vfifo(grp, &v);
4593
        }
4594
 
4595
        if (i >= VFIFO_SIZE) {
4596
                DPRINT(2, "find_dqs_en_phase: center: failed");
4597
                return 0;
4598
        }
4599
#if RUNTIME_CAL_REPORT
4600
        for(sr = 0; sr < NUM_SHADOW_REGS; sr++) {
4601
                RPRINT("DQS Enable ; Group %lu ; Rank %lu ; Start  VFIFO %2li ; Phase %li ; Delay %2li", grp, sr, start_v[sr], start_p[sr], start_d[sr]);
4602
                RPRINT("DQS Enable ; Group %lu ; Rank %lu ; End    VFIFO %2li ; Phase %li ; Delay %2li", grp, sr, end_v[sr], end_p[sr], end_d[sr]);
4603
      // Case 174276: Normalizing VFIFO center
4604
                RPRINT("DQS Enable ; Group %lu ; Rank %lu ; Center VFIFO %2li ; Phase %li ; Delay %2li", grp, sr, (v % VFIFO_SIZE), p-1, d);
4605
        }
4606
#endif
4607
        DPRINT(2, "find_dqs_en_phase: center found: vfifo=%li ptap=%lu dtap=%lu", BFM_GBL_GET(vfifo_idx), p-1, d);
4608
        #if ENABLE_DELAY_CHAIN_WRITE
4609
        vfifo_settings[grp] = v;
4610
        #endif // ENABLE_DELAY_CHAIN_WRITE
4611
        BFM_GBL_SET(dqs_enable_mid[grp].v,BFM_GBL_GET(vfifo_idx));
4612
        BFM_GBL_SET(dqs_enable_mid[grp].p,p-1);
4613
        BFM_GBL_SET(dqs_enable_mid[grp].d,d);
4614
        BFM_GBL_SET(dqs_enable_mid[grp].ps,work_mid);
4615
        return 1;
4616
}
4617
 
4618
#if 0
4619
// Ryan's algorithm 
4620
 
4621
alt_u32 rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase (alt_u32 grp)
4622
{
4623
        alt_u32 i, d, v, p;
4624
        alt_u32 min_working_p, max_working_p, min_working_d, max_working_d, max_working_cnt;
4625
        alt_u32 fail_cnt;
4626
        t_btfld bit_chk;
4627
        alt_u32 dtaps_per_ptap;
4628
        alt_u32 found_begin, found_end;
4629
        alt_u32 tmp_delay;
4630
 
4631
        TRACE_FUNC("%lu", grp);
4632
 
4633
        reg_file_set_sub_stage(CAL_SUBSTAGE_VFIFO_CENTER);
4634
 
4635
        scc_mgr_set_dqs_en_delay_all_ranks(grp, 0);
4636
        scc_mgr_set_dqs_en_phase_all_ranks(grp, 0);
4637
 
4638
        fail_cnt = 0;
4639
 
4640
        //USER **************************************************************
4641
        //USER * Step 0 : Determine number of delay taps for each phase tap *
4642
 
4643
        dtaps_per_ptap = 0;
4644
        tmp_delay = 0;
4645
        while (tmp_delay < IO_DELAY_PER_OPA_TAP) {
4646
                dtaps_per_ptap++;
4647
                tmp_delay += IO_DELAY_PER_DQS_EN_DCHAIN_TAP;
4648
        }
4649
        dtaps_per_ptap--;
4650
 
4651
        //USER *********************************************************
4652
        //USER * Step 1 : First push vfifo until we get a failing read *
4653
        for (v = 0; v < VFIFO_SIZE; ) {
4654
                if (!rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4655
                        fail_cnt++;
4656
 
4657
                        if (fail_cnt == 2) {
4658
                                break;
4659
                        }
4660
                }
4661
 
4662
                //USER fiddle with FIFO
4663
                rw_mgr_incr_vfifo(grp, &v);
4664
        }
4665
 
4666
        if (i >= VFIFO_SIZE) {
4667
                //USER no failing read found!! Something must have gone wrong
4668
                return 0;
4669
        }
4670
 
4671
        max_working_cnt = 0;
4672
        min_working_p = 0;
4673
 
4674
        //USER ********************************************************
4675
        //USER * step 2: find first working phase, increment in ptaps *
4676
        found_begin = 0;
4677
        for (d = 0; d <= dtaps_per_ptap; d++) {
4678
                scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4679
 
4680
                for (i = 0; i < VFIFO_SIZE; i++) {
4681
                        for (p = 0; p <= IO_DQS_EN_PHASE_MAX; p++) {
4682
                                scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
4683
 
4684
                                if (rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4685
                                        max_working_cnt = 1;
4686
                                        found_begin = 1;
4687
                                        break;
4688
                                }
4689
                        }
4690
 
4691
                        if (found_begin) {
4692
                                break;
4693
                        }
4694
 
4695
                        if (p > IO_DQS_EN_PHASE_MAX) {
4696
                                //USER fiddle with FIFO
4697
                                rw_mgr_incr_vfifo(grp, &v);
4698
                        }
4699
                }
4700
 
4701
                if (found_begin) {
4702
                        break;
4703
                }
4704
        }
4705
 
4706
        if (i >= VFIFO_SIZE) {
4707
                //USER cannot find working solution 
4708
                return 0;
4709
        }
4710
 
4711
        min_working_p = p;
4712
 
4713
        //USER  If d is 0 then the working window covers a phase tap and we can follow the old procedure
4714
        //USER  otherwise, we've found the beginning, and we need to increment the dtaps until we find the end 
4715
        if (d == 0) {
4716
                //USER ********************************************************************
4717
                //USER * step 3a: if we have room, back off by one and increment in dtaps *
4718
                min_working_d = 0;
4719
 
4720
                //USER Special case code for backing up a phase 
4721
                if (p == 0) {
4722
                        p = IO_DQS_EN_PHASE_MAX ;
4723
                        rw_mgr_decr_vfifo(grp, &v);
4724
                } else {
4725
                        p = p - 1;
4726
                }
4727
                scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
4728
 
4729
                found_begin = 0;
4730
                for (d = 0; d <= dtaps_per_ptap; d++) {
4731
                        scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4732
 
4733
                        if (rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4734
                                found_begin = 1;
4735
                                min_working_d = d;
4736
                                break;
4737
                        }
4738
                }
4739
 
4740
                //USER We have found a working dtap before the ptap found above 
4741
                if (found_begin == 1) {
4742
                        min_working_p = p;
4743
                        max_working_cnt++;
4744
                }
4745
 
4746
                //USER Restore VFIFO to old state before we decremented it 
4747
                p = p + 1;
4748
                if (p > IO_DQS_EN_PHASE_MAX) {
4749
                        p = 0;
4750
                        rw_mgr_incr_vfifo(grp, &v);
4751
                }
4752
 
4753
                scc_mgr_set_dqs_en_delay_all_ranks(grp, 0);
4754
 
4755
 
4756
                //USER ***********************************************************************************
4757
                //USER * step 4a: go forward from working phase to non working phase, increment in ptaps *
4758
                p = p + 1;
4759
                if (p > IO_DQS_EN_PHASE_MAX) {
4760
                        //USER fiddle with FIFO
4761
                        p = 0;
4762
                        rw_mgr_incr_vfifo(grp, &v);
4763
                }
4764
 
4765
                found_end = 0;
4766
                for (; i < VFIFO_SIZE+1; i++) {
4767
                        for (; p <= IO_DQS_EN_PHASE_MAX; p++) {
4768
                                scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
4769
 
4770
                                if (!rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4771
                                        found_end = 1;
4772
                                        break;
4773
                                } else {
4774
                                        max_working_cnt++;
4775
                                }
4776
                        }
4777
 
4778
                        if (found_end) {
4779
                                break;
4780
                        }
4781
 
4782
                        if (p > IO_DQS_EN_PHASE_MAX) {
4783
                                //USER fiddle with FIFO
4784
                                rw_mgr_incr_vfifo(grp, &v);
4785
                                p = 0;
4786
                        }
4787
                }
4788
 
4789
                if (i >= VFIFO_SIZE+1) {
4790
                        //USER cannot see edge of failing read 
4791
                        return 0;
4792
                }
4793
 
4794
                //USER *********************************************************
4795
                //USER * step 5a:  back off one from last, increment in dtaps  *
4796
                max_working_d = 0;
4797
 
4798
                //USER Special case code for backing up a phase 
4799
                if (p == 0) {
4800
                        p = IO_DQS_EN_PHASE_MAX;
4801
                        rw_mgr_decr_vfifo(grp, &v);
4802
                } else {
4803
                        p = p - 1;
4804
                }
4805
 
4806
                max_working_p = p;
4807
                scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
4808
 
4809
                for (d = 0; d <= IO_DQS_EN_DELAY_MAX; d++) {
4810
                        scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4811
 
4812
                        if (!rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4813
                                break;
4814
                        }
4815
                }
4816
 
4817
                //USER Go back to working dtap 
4818
                if (d != 0) {
4819
                        max_working_d = d - 1;
4820
                }
4821
 
4822
        } else {
4823
 
4824
                //USER ********************************************************************
4825
                //USER * step 3-5b:  Find the right edge of the window using delay taps   *             
4826
 
4827
                max_working_p = min_working_p;
4828
                min_working_d = d;
4829
 
4830
                for (; d <= IO_DQS_EN_DELAY_MAX; d++) {
4831
                        scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4832
 
4833
                        if (!rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4834
                                break;
4835
                        }
4836
                }
4837
 
4838
                //USER Go back to working dtap 
4839
                if (d != 0) {
4840
                        max_working_d = d - 1;
4841
                }
4842
 
4843
                //USER Only here to counterbalance a subtract later on which is not needed if this branch
4844
                //USER of the algorithm is taken 
4845
                max_working_cnt++;
4846
        }
4847
 
4848
        //USER ********************************************
4849
        //USER * step 6:  Find the centre of the window   *
4850
 
4851
        //USER If the number of working phases is even we will step back a phase and find the
4852
        //USER  edge with a larger delay chain tap 
4853
        if ((max_working_cnt & 1) == 0) {
4854
                p = min_working_p + (max_working_cnt-1)/2;
4855
 
4856
                //USER Special case code for backing up a phase 
4857
                if (max_working_p == 0) {
4858
                        max_working_p = IO_DQS_EN_PHASE_MAX;
4859
                        rw_mgr_decr_vfifo(grp, &v);
4860
                } else {
4861
                        max_working_p = max_working_p - 1;
4862
                }
4863
 
4864
                scc_mgr_set_dqs_en_phase_all_ranks(grp, max_working_p);
4865
 
4866
                //USER Code to determine at which dtap we should start searching again for a failure
4867
                //USER If we've moved back such that the max and min p are the same, we should start searching
4868
                //USER from where the window actually exists
4869
                if (max_working_p == min_working_p) {
4870
                        d = min_working_d;
4871
                } else {
4872
                        d = max_working_d;
4873
                }
4874
 
4875
                for (; d <= IO_DQS_EN_DELAY_MAX; d++) {
4876
                        scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4877
 
4878
                        if (!rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4879
                                break;
4880
                        }
4881
                }
4882
 
4883
                //USER Go back to working dtap 
4884
                if (d != 0) {
4885
                        max_working_d = d - 1;
4886
                }
4887
        } else {
4888
                p = min_working_p + (max_working_cnt)/2;
4889
        }
4890
 
4891
        while (p > IO_DQS_EN_PHASE_MAX) {
4892
                p -= (IO_DQS_EN_PHASE_MAX + 1);
4893
        }
4894
 
4895
        d = (min_working_d + max_working_d)/2;
4896
 
4897
        scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
4898
        scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
4899
 
4900
        //USER push vfifo until we can successfully calibrate 
4901
 
4902
        for (i = 0; i < VFIFO_SIZE; i++) {
4903
                if (rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4904
                        break;
4905
                }
4906
 
4907
                //USER fiddle with FIFO
4908
                rw_mgr_incr_vfifo(grp, &v);
4909
        }
4910
 
4911
        if (i >= VFIFO_SIZE) {
4912
                return 0;
4913
        }
4914
 
4915
        return 1;
4916
}
4917
 
4918
#endif
4919
 
4920
#else
4921
// Val's original version 
4922
 
4923
alt_u32 rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase (alt_u32 grp)
4924
{
4925
        alt_u32 i, j, v, d;
4926
        alt_u32 min_working_d, max_working_cnt;
4927
        alt_u32 fail_cnt;
4928
        t_btfld bit_chk;
4929
        alt_u32 delay_per_ptap_mid;
4930
 
4931
        TRACE_FUNC("%lu", grp);
4932
 
4933
        reg_file_set_sub_stage(CAL_SUBSTAGE_VFIFO_CENTER);
4934
 
4935
        scc_mgr_set_dqs_en_delay_all_ranks(grp, 0);
4936
        scc_mgr_set_dqs_en_phase_all_ranks(grp, 0);
4937
 
4938
        fail_cnt = 0;
4939
 
4940
        //USER first push vfifo until we get a failing read 
4941
        v = 0;
4942
        for (i = 0; i < VFIFO_SIZE; i++) {
4943
                if (!rw_mgr_mem_calibrate_read_test_all_ranks (grp, 1, PASS_ONE_BIT, &bit_chk, 0)) {
4944
                        fail_cnt++;
4945
 
4946
                        if (fail_cnt == 2) {
4947
                                break;
4948
                        }
4949
                }
4950
 
4951
                //USER fiddle with FIFO
4952
                rw_mgr_incr_vfifo(grp, &v);
4953
        }
4954
 
4955
        if (v >= VFIFO_SIZE) {
4956
                //USER no failing read found!! Something must have gone wrong
4957
 
4958
                return 0;
4959
        }
4960
 
4961
        max_working_cnt = 0;
4962
        min_working_d = 0;
4963
 
4964
        for (i = 0; i < VFIFO_SIZE+1; i++) {
4965
                for (d = 0; d <= IO_DQS_EN_PHASE_MAX; d++) {
4966
                        scc_mgr_set_dqs_en_phase_all_ranks(grp, d);
4967
 
4968
                        rw_mgr_mem_calibrate_read_test_all_ranks (grp, NUM_READ_PB_TESTS, PASS_ONE_BIT, &bit_chk, 0);
4969
                        if (bit_chk) {
4970
                                //USER passing read 
4971
 
4972
                                if (max_working_cnt == 0) {
4973
                                        min_working_d = d;
4974
                                }
4975
 
4976
                                max_working_cnt++;
4977
                        } else {
4978
                                if (max_working_cnt > 0) {
4979
                                        //USER already have one working value 
4980
                                        break;
4981
                                }
4982
                        }
4983
                }
4984
 
4985
                if (d > IO_DQS_EN_PHASE_MAX) {
4986
                        //USER fiddle with FIFO
4987
                        rw_mgr_incr_vfifo(grp, &v);
4988
                } else {
4989
                        //USER found working solution! 
4990
 
4991
                        d = min_working_d + (max_working_cnt - 1) / 2;
4992
 
4993
                        while (d > IO_DQS_EN_PHASE_MAX) {
4994
                                d -= (IO_DQS_EN_PHASE_MAX + 1);
4995
                        }
4996
 
4997
                        break;
4998
                }
4999
        }
5000
 
5001
        if (i >= VFIFO_SIZE+1) {
5002
                //USER cannot find working solution or cannot see edge of failing read 
5003
 
5004
                return 0;
5005
        }
5006
 
5007
        //USER in the case the number of working steps is even, use 50ps taps to further center the window 
5008
 
5009
        if ((max_working_cnt & 1) == 0) {
5010
                delay_per_ptap_mid = IO_DELAY_PER_OPA_TAP / 2;
5011
 
5012
                //USER increment in 50ps taps until we reach the required amount 
5013
 
5014
                for (i = 0, j = 0; i <= IO_DQS_EN_DELAY_MAX && j < delay_per_ptap_mid; i++, j += IO_DELAY_PER_DQS_EN_DCHAIN_TAP);
5015
 
5016
                scc_mgr_set_dqs_en_delay_all_ranks(grp, i - 1);
5017
        }
5018
 
5019
        scc_mgr_set_dqs_en_phase_all_ranks(grp, d);
5020
 
5021
        //USER push vfifo until we can successfully calibrate 
5022
 
5023
        for (i = 0; i < VFIFO_SIZE; i++) {
5024
                if (rw_mgr_mem_calibrate_read_test_all_ranks (grp, NUM_READ_PB_TESTS, PASS_ONE_BIT, &bit_chk, 0)) {
5025
                        break;
5026
                }
5027
 
5028
                //USER fiddle with FIFO
5029
                rw_mgr_incr_vfifo (grp, &v);
5030
        }
5031
 
5032
        if (i >= VFIFO_SIZE) {
5033
                return 0;
5034
        }
5035
 
5036
        return 1;
5037
}
5038
 
5039
#endif
5040
#endif
5041
 
5042
 
5043
// Try rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase across different dq_in_delay values
5044
static inline alt_u32 rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase_sweep_dq_in_delay (alt_u32 write_group, alt_u32 read_group, alt_u32 test_bgn)
5045
{
5046
#if STRATIXV || ARRIAV || CYCLONEV || ARRIAVGZ
5047
        alt_u32 found;
5048
        alt_u32 i;
5049
        alt_u32 p;
5050
        alt_u32 d;
5051
        alt_u32 r;
5052
 
5053
        const alt_u32 delay_step = IO_IO_IN_DELAY_MAX/(RW_MGR_MEM_DQ_PER_READ_DQS-1); /* we start at zero, so have one less dq to devide among */
5054
 
5055
        TRACE_FUNC("(%lu,%lu,%lu)", write_group, read_group, test_bgn);
5056
 
5057
        // try different dq_in_delays since the dq path is shorter than dqs
5058
 
5059
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
5060
                select_shadow_regs_for_update(r, write_group, 1);
5061
                for (i = 0, p = test_bgn, d = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++, p++, d += delay_step) {
5062
                        DPRINT(1, "rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase_sweep_dq_in_delay: g=%lu/%lu r=%lu, i=%lu p=%lu d=%lu",
5063
                               write_group, read_group, r, i, p, d);
5064
                        scc_mgr_set_dq_in_delay(write_group, p, d);
5065
                        scc_mgr_load_dq (p);
5066
                }
5067
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5068
        }
5069
 
5070
        found = rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(read_group);
5071
 
5072
        DPRINT(1, "rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase_sweep_dq_in_delay: g=%lu/%lu found=%lu; Reseting delay chain to zero",
5073
               write_group, read_group, found);
5074
 
5075
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
5076
                select_shadow_regs_for_update(r, write_group, 1);
5077
                for (i = 0, p = test_bgn; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++, p++) {
5078
                        scc_mgr_set_dq_in_delay(write_group, p, 0);
5079
                        scc_mgr_load_dq (p);
5080
                }
5081
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5082
        }
5083
 
5084
        return found;
5085
#else
5086
        return rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(read_group);
5087
#endif
5088
}
5089
 
5090
//USER per-bit deskew DQ and center 
5091
 
5092
#if NEWVERSION_RDDESKEW
5093
 
5094
alt_u32 rw_mgr_mem_calibrate_vfifo_center (alt_u32 rank_bgn, alt_u32 write_group, alt_u32 read_group, alt_u32 test_bgn, alt_u32 use_read_test, alt_u32 update_fom)
5095
{
5096
        alt_u32 i, p, d, min_index;
5097
        //USER Store these as signed since there are comparisons with signed numbers
5098
        t_btfld bit_chk;
5099
        t_btfld sticky_bit_chk;
5100
        alt_32 left_edge[RW_MGR_MEM_DQ_PER_READ_DQS];
5101
        alt_32 right_edge[RW_MGR_MEM_DQ_PER_READ_DQS];
5102
        alt_32 final_dq[RW_MGR_MEM_DQ_PER_READ_DQS];
5103
        alt_32 mid;
5104
        alt_32 orig_mid_min, mid_min;
5105
        alt_32 new_dqs, start_dqs, start_dqs_en, shift_dq, final_dqs, final_dqs_en;
5106
        alt_32 dq_margin, dqs_margin;
5107
        alt_u32 stop;
5108
 
5109
        TRACE_FUNC("%lu %lu", read_group, test_bgn);
5110
#if BFM_MODE    
5111
        if (use_read_test) {
5112
                BFM_STAGE("vfifo_center");
5113
        } else {
5114
                BFM_STAGE("vfifo_center_after_writes");
5115
        }
5116
#endif  
5117
 
5118
        ALTERA_ASSERT(read_group < RW_MGR_MEM_IF_READ_DQS_WIDTH);
5119
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
5120
 
5121
        start_dqs = READ_SCC_DQS_IN_DELAY(read_group);
5122
        if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS) {
5123
                start_dqs_en = READ_SCC_DQS_EN_DELAY(read_group);
5124
        }
5125
 
5126
        select_curr_shadow_reg_using_rank(rank_bgn);
5127
 
5128
        //USER per-bit deskew 
5129
 
5130
        //USER set the left and right edge of each bit to an illegal value 
5131
        //USER use (IO_IO_IN_DELAY_MAX + 1) as an illegal value 
5132
        sticky_bit_chk = 0;
5133
        for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
5134
                left_edge[i]  = IO_IO_IN_DELAY_MAX + 1;
5135
                right_edge[i] = IO_IO_IN_DELAY_MAX + 1;
5136
        }
5137
 
5138
        //USER Search for the left edge of the window for each bit
5139
        for (d = 0; d <= IO_IO_IN_DELAY_MAX; d++) {
5140
                scc_mgr_apply_group_dq_in_delay (write_group, test_bgn, d);
5141
 
5142
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5143
 
5144
                //USER Stop searching when the read test doesn't pass AND when we've seen a passing read on every bit
5145
                if (use_read_test) {
5146
                        stop = !rw_mgr_mem_calibrate_read_test (rank_bgn, read_group, NUM_READ_PB_TESTS, PASS_ONE_BIT, &bit_chk, 0, 0);
5147
                } else {
5148
                        rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 0, PASS_ONE_BIT, &bit_chk, 0);
5149
                        bit_chk = bit_chk >> (RW_MGR_MEM_DQ_PER_READ_DQS * (read_group - (write_group * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH)));
5150
                        stop = (bit_chk == 0);
5151
                }
5152
                sticky_bit_chk = sticky_bit_chk | bit_chk;
5153
                stop = stop && (sticky_bit_chk == param->read_correct_mask);
5154
                DPRINT(2, "vfifo_center(left): dtap=%lu => " BTFLD_FMT " == " BTFLD_FMT " && %lu", d, sticky_bit_chk, param->read_correct_mask, stop);
5155
 
5156
                if (stop == 1) {
5157
                        break;
5158
                } else {
5159
                        for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
5160
                                if (bit_chk & 1) {
5161
                                        //USER Remember a passing test as the left_edge
5162
                                        left_edge[i] = d;
5163
                                } else {
5164
                                        //USER If a left edge has not been seen yet, then a future passing test will mark this edge as the right edge 
5165
                                        if (left_edge[i] == IO_IO_IN_DELAY_MAX + 1) {
5166
                                                right_edge[i] = -(d + 1);
5167
                                        }
5168
                                }
5169
                                DPRINT(2, "vfifo_center[l,d=%lu]: bit_chk_test=%d left_edge[%lu]: %ld right_edge[%lu]: %ld",
5170
                                       d, (int)(bit_chk & 1), i, left_edge[i], i, right_edge[i]);
5171
                                bit_chk = bit_chk >> 1;
5172
                        }
5173
                }
5174
        }
5175
 
5176
        //USER Reset DQ delay chains to 0 
5177
        scc_mgr_apply_group_dq_in_delay (write_group, test_bgn, 0);
5178
        sticky_bit_chk = 0;
5179
        for (i = RW_MGR_MEM_DQ_PER_READ_DQS - 1;; i--) {
5180
 
5181
                DPRINT(2, "vfifo_center: left_edge[%lu]: %ld right_edge[%lu]: %ld", i, left_edge[i], i, right_edge[i]);
5182
 
5183
                //USER Check for cases where we haven't found the left edge, which makes our assignment of the the 
5184
                //USER right edge invalid.  Reset it to the illegal value. 
5185
                if ((left_edge[i] == IO_IO_IN_DELAY_MAX + 1) && (right_edge[i] != IO_IO_IN_DELAY_MAX + 1)) {
5186
                        right_edge[i] = IO_IO_IN_DELAY_MAX + 1;
5187
                        DPRINT(2, "vfifo_center: reset right_edge[%lu]: %ld", i, right_edge[i]);
5188
                }
5189
 
5190
                //USER Reset sticky bit (except for bits where we have seen both the left and right edge) 
5191
                sticky_bit_chk = sticky_bit_chk << 1;
5192
                if ((left_edge[i] != IO_IO_IN_DELAY_MAX + 1) && (right_edge[i] != IO_IO_IN_DELAY_MAX + 1)) {
5193
                        sticky_bit_chk = sticky_bit_chk | 1;
5194
                }
5195
 
5196
                if (i == 0)
5197
                {
5198
                        break;
5199
                }
5200
        }
5201
 
5202
        //USER Search for the right edge of the window for each bit 
5203
        for (d = 0; d <= IO_DQS_IN_DELAY_MAX - start_dqs; d++) {
5204
                scc_mgr_set_dqs_bus_in_delay(read_group, d + start_dqs);
5205
                if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS) {
5206
                        alt_u32 delay = d + start_dqs_en;
5207
                        if (delay > IO_DQS_EN_DELAY_MAX) {
5208
                                delay = IO_DQS_EN_DELAY_MAX;
5209
                        }
5210
                        scc_mgr_set_dqs_en_delay(read_group, delay);
5211
                }
5212
                scc_mgr_load_dqs (read_group);
5213
 
5214
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5215
 
5216
                //USER Stop searching when the read test doesn't pass AND when we've seen a passing read on every bit 
5217
                if (use_read_test) {
5218
                        stop = !rw_mgr_mem_calibrate_read_test (rank_bgn, read_group, NUM_READ_PB_TESTS, PASS_ONE_BIT, &bit_chk, 0, 0);
5219
                } else {
5220
                        rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 0, PASS_ONE_BIT, &bit_chk, 0);
5221
                        bit_chk = bit_chk >> (RW_MGR_MEM_DQ_PER_READ_DQS * (read_group - (write_group * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH)));
5222
                        stop = (bit_chk == 0);
5223
                }
5224
                sticky_bit_chk = sticky_bit_chk | bit_chk;
5225
                stop = stop && (sticky_bit_chk == param->read_correct_mask);
5226
 
5227
                DPRINT(2, "vfifo_center(right): dtap=%lu => " BTFLD_FMT " == " BTFLD_FMT " && %lu", d, sticky_bit_chk, param->read_correct_mask, stop);
5228
 
5229
                if (stop == 1) {
5230
                        break;
5231
                } else {
5232
                        for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
5233
                                if (bit_chk & 1) {
5234
                                        //USER Remember a passing test as the right_edge 
5235
                                        right_edge[i] = d;
5236
                                } else {
5237
                                        if (d != 0) {
5238
                                                //USER If a right edge has not been seen yet, then a future passing test will mark this edge as the left edge 
5239
                                                if (right_edge[i] == IO_IO_IN_DELAY_MAX + 1) {
5240
                                                        left_edge[i] = -(d + 1);
5241
                                                }
5242
                                        } else {
5243
                                                //USER d = 0 failed, but it passed when testing the left edge, so it must be marginal, set it to -1
5244
                                                if (right_edge[i] == IO_IO_IN_DELAY_MAX + 1 && left_edge[i] != IO_IO_IN_DELAY_MAX + 1) {
5245
                                                        right_edge[i] = -1;
5246
                                                }
5247
                                                //USER If a right edge has not been seen yet, then a future passing test will mark this edge as the left edge 
5248
                                                else if (right_edge[i] == IO_IO_IN_DELAY_MAX + 1) {
5249
                                                        left_edge[i] = -(d + 1);
5250
                                                }
5251
 
5252
                                        }
5253
                                }
5254
 
5255
                                DPRINT(2, "vfifo_center[r,d=%lu]: bit_chk_test=%d left_edge[%lu]: %ld right_edge[%lu]: %ld",
5256
                                       d, (int)(bit_chk & 1), i, left_edge[i], i, right_edge[i]);
5257
                                bit_chk = bit_chk >> 1;
5258
                        }
5259
                }
5260
        }
5261
 
5262
        // Store all observed margins
5263
#if ENABLE_TCL_DEBUG
5264
        for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
5265
                alt_u32 dq = read_group*RW_MGR_MEM_DQ_PER_READ_DQS + i;
5266
 
5267
                ALTERA_ASSERT(dq < RW_MGR_MEM_DATA_WIDTH);
5268
 
5269
                TCLRPT_SET(debug_cal_report->cal_dq_in_margins[curr_shadow_reg][dq].left_edge, left_edge[i]);
5270
                TCLRPT_SET(debug_cal_report->cal_dq_in_margins[curr_shadow_reg][dq].right_edge, right_edge[i]);
5271
        }
5272
#endif
5273
 
5274
        //USER Check that all bits have a window
5275
        for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
5276
                DPRINT(2, "vfifo_center: left_edge[%lu]: %ld right_edge[%lu]: %ld", i, left_edge[i], i, right_edge[i]);
5277
                BFM_GBL_SET(dq_read_left_edge[read_group][i],left_edge[i]);
5278
                BFM_GBL_SET(dq_read_right_edge[read_group][i],right_edge[i]);
5279
                if ((left_edge[i] == IO_IO_IN_DELAY_MAX + 1) || (right_edge[i] == IO_IO_IN_DELAY_MAX + 1)) {
5280
 
5281
                        //USER Restore delay chain settings before letting the loop in 
5282
                        //USER rw_mgr_mem_calibrate_vfifo to retry different dqs/ck relationships
5283
                        scc_mgr_set_dqs_bus_in_delay(read_group, start_dqs);
5284
                        if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS) {
5285
                                scc_mgr_set_dqs_en_delay(read_group, start_dqs_en);
5286
                        }
5287
                        scc_mgr_load_dqs (read_group);
5288
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5289
 
5290
                        DPRINT(1, "vfifo_center: failed to find edge [%lu]: %ld %ld", i, left_edge[i], right_edge[i]);
5291
                        if (use_read_test) {
5292
                                set_failing_group_stage(read_group*RW_MGR_MEM_DQ_PER_READ_DQS + i, CAL_STAGE_VFIFO, CAL_SUBSTAGE_VFIFO_CENTER);
5293
                        } else {
5294
                                set_failing_group_stage(read_group*RW_MGR_MEM_DQ_PER_READ_DQS + i, CAL_STAGE_VFIFO_AFTER_WRITES, CAL_SUBSTAGE_VFIFO_CENTER);
5295
                        }
5296
                        return 0;
5297
                }
5298
        }
5299
 
5300
        //USER Find middle of window for each DQ bit 
5301
        mid_min = left_edge[0] - right_edge[0];
5302
        min_index = 0;
5303
        for (i = 1; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
5304
                mid = left_edge[i] - right_edge[i];
5305
                if (mid < mid_min) {
5306
                        mid_min = mid;
5307
                        min_index = i;
5308
                }
5309
        }
5310
 
5311
        //USER  -mid_min/2 represents the amount that we need to move DQS.  If mid_min is odd and positive we'll need to add one to
5312
        //USER make sure the rounding in further calculations is correct (always bias to the right), so just add 1 for all positive values
5313
        if (mid_min > 0) {
5314
                mid_min++;
5315
        }
5316
        mid_min = mid_min / 2;
5317
 
5318
        DPRINT(1, "vfifo_center: mid_min=%ld (index=%lu)", mid_min, min_index);
5319
 
5320
        //USER Determine the amount we can change DQS (which is -mid_min)
5321
        orig_mid_min = mid_min;
5322
#if ENABLE_DQS_IN_CENTERING
5323
        new_dqs = start_dqs - mid_min;
5324
        if (new_dqs > IO_DQS_IN_DELAY_MAX) {
5325
                new_dqs = IO_DQS_IN_DELAY_MAX;
5326
        } else if (new_dqs < 0) {
5327
                new_dqs = 0;
5328
        }
5329
        mid_min = start_dqs - new_dqs;
5330
        DPRINT(1, "vfifo_center: new mid_min=%ld new_dqs=%ld", mid_min, new_dqs);
5331
 
5332
        if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS) {
5333
                if (start_dqs_en - mid_min > IO_DQS_EN_DELAY_MAX) {
5334
                        mid_min += start_dqs_en - mid_min - IO_DQS_EN_DELAY_MAX;
5335
                } else if (start_dqs_en - mid_min < 0) {
5336
                        mid_min += start_dqs_en - mid_min;
5337
                }
5338
        }
5339
        new_dqs = start_dqs - mid_min;
5340
#else
5341
        new_dqs = start_dqs;
5342
        mid_min = 0;
5343
#endif
5344
 
5345
        DPRINT(1, "vfifo_center: start_dqs=%ld start_dqs_en=%ld new_dqs=%ld mid_min=%ld",
5346
               start_dqs, IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS ? start_dqs_en : -1, new_dqs, mid_min);
5347
 
5348
        //USER Initialize data for export structures 
5349
        dqs_margin = IO_IO_IN_DELAY_MAX + 1;
5350
        dq_margin  = IO_IO_IN_DELAY_MAX + 1;
5351
 
5352
        //USER add delay to bring centre of all DQ windows to the same "level" 
5353
        for (i = 0, p = test_bgn; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++, p++) {
5354
                //USER Use values before divide by 2 to reduce round off error 
5355
                shift_dq = (left_edge[i] - right_edge[i] - (left_edge[min_index] - right_edge[min_index]))/2  + (orig_mid_min - mid_min);
5356
 
5357
                DPRINT(2, "vfifo_center: before: shift_dq[%lu]=%ld", i, shift_dq);
5358
 
5359
                if (shift_dq + (alt_32)READ_SCC_DQ_IN_DELAY(p) > (alt_32)IO_IO_IN_DELAY_MAX) {
5360
                        shift_dq = (alt_32)IO_IO_IN_DELAY_MAX - READ_SCC_DQ_IN_DELAY(i);
5361
                } else if (shift_dq + (alt_32)READ_SCC_DQ_IN_DELAY(p) < 0) {
5362
                        shift_dq = -(alt_32)READ_SCC_DQ_IN_DELAY(p);
5363
                }
5364
                DPRINT(2, "vfifo_center: after: shift_dq[%lu]=%ld", i, shift_dq);
5365
                final_dq[i] = READ_SCC_DQ_IN_DELAY(p) + shift_dq;
5366
                scc_mgr_set_dq_in_delay(write_group, p, final_dq[i]);
5367
                scc_mgr_load_dq (p);
5368
 
5369
                DPRINT(2, "vfifo_center: margin[%lu]=[%ld,%ld]", i,
5370
                       left_edge[i] - shift_dq + (-mid_min),
5371
                       right_edge[i] + shift_dq - (-mid_min));
5372
                //USER To determine values for export structures 
5373
                if (left_edge[i] - shift_dq + (-mid_min) < dq_margin) {
5374
                        dq_margin = left_edge[i] - shift_dq + (-mid_min);
5375
                }
5376
                if (right_edge[i] + shift_dq - (-mid_min) < dqs_margin) {
5377
                        dqs_margin = right_edge[i] + shift_dq - (-mid_min);
5378
                }
5379
        }
5380
 
5381
#if ENABLE_DQS_IN_CENTERING     
5382
        final_dqs = new_dqs;
5383
        if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS) {
5384
                final_dqs_en = start_dqs_en - mid_min;
5385
        }
5386
#else
5387
        final_dqs = start_dqs;
5388
        if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS) {
5389
                final_dqs_en = start_dqs_en;
5390
        }
5391
#endif  
5392
 
5393
        //USER Move DQS-en
5394
        if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS) {
5395
                scc_mgr_set_dqs_en_delay(read_group, final_dqs_en);
5396
                scc_mgr_load_dqs (read_group);
5397
        }
5398
 
5399
#if QDRII || RLDRAMX    
5400
        //USER Move DQS. Do it gradually to minimize the chance of causing a timing
5401
        //USER failure in core FPGA logic driven by an input-strobe-derived clock
5402
        d = READ_SCC_DQS_IN_DELAY(read_group);
5403
        while (d != final_dqs) {
5404
                if (d > final_dqs) {
5405
                        --d;
5406
                } else {
5407
                        ++d;
5408
                }
5409
                scc_mgr_set_dqs_bus_in_delay(read_group, d);
5410
                scc_mgr_load_dqs (read_group);
5411
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5412
        }
5413
#else
5414
        //USER Move DQS
5415
        scc_mgr_set_dqs_bus_in_delay(read_group, final_dqs);
5416
        scc_mgr_load_dqs (read_group);
5417
#endif
5418
 
5419
    if(update_fom) {
5420
        //USER Export values 
5421
        gbl->fom_in += (dq_margin + dqs_margin)/(RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
5422
        TCLRPT_SET(debug_summary_report->fom_in, debug_summary_report->fom_in + (dq_margin + dqs_margin)/(RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH));
5423
            TCLRPT_SET(debug_cal_report->cal_status_per_group[curr_shadow_reg][write_group].fom_in, debug_cal_report->cal_status_per_group[curr_shadow_reg][write_group].fom_in + (dq_margin + dqs_margin)/(RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH));
5424
    }
5425
 
5426
        TCLRPT_SET(debug_cal_report->cal_dqs_in_margins[curr_shadow_reg][read_group].dqs_margin, dqs_margin);
5427
        TCLRPT_SET(debug_cal_report->cal_dqs_in_margins[curr_shadow_reg][read_group].dq_margin, dq_margin);
5428
 
5429
        DPRINT(2, "vfifo_center: dq_margin=%ld dqs_margin=%ld", dq_margin, dqs_margin);
5430
 
5431
#if RUNTIME_CAL_REPORT
5432
        for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
5433
                if (use_read_test) {
5434
                        RPRINT("Read Deskew ; DQ %2lu ; Rank %lu ; Left edge %3li ; Right edge %3li ; DQ delay %2li ; DQS delay %2li", read_group*RW_MGR_MEM_DQ_PER_READ_DQS + i, curr_shadow_reg, left_edge[i],  right_edge[i], final_dq[i], final_dqs);
5435
                } else {
5436
                        RPRINT("Read after Write ; DQ %2lu ; Rank %lu ; Left edge %3li ; Right edge %3li ; DQ delay %2li ; DQS delay %2li", read_group*RW_MGR_MEM_DQ_PER_READ_DQS + i, curr_shadow_reg, left_edge[i],  right_edge[i], final_dq[i], final_dqs);
5437
                }
5438
        }
5439
#endif
5440
 
5441
        //USER Do not remove this line as it makes sure all of our decisions have been applied
5442
        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5443
        return (dq_margin >= 0) && (dqs_margin >= 0);
5444
}
5445
 
5446
#else
5447
 
5448
alt_u32 rw_mgr_mem_calibrate_vfifo_center (alt_u32 rank_bgn, alt_u32 grp, alt_u32 test_bgn, alt_u32 use_read_test)
5449
{
5450
        alt_u32 i, p, d;
5451
        alt_u32 mid;
5452
        t_btfld bit_chk;
5453
        alt_u32 max_working_dq[RW_MGR_MEM_DQ_PER_READ_DQS];
5454
        alt_u32 dq_margin, dqs_margin;
5455
        alt_u32 start_dqs;
5456
 
5457
        TRACE_FUNC("%lu %lu", grp, test_bgn);
5458
 
5459
        //USER per-bit deskew.
5460
        //USER start of the per-bit sweep with the minimum working delay setting for
5461
        //USER all bits.
5462
 
5463
        for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
5464
                max_working_dq[i] = 0;
5465
        }
5466
 
5467
        for (d = 1; d <= IO_IO_IN_DELAY_MAX; d++) {
5468
                scc_mgr_apply_group_dq_in_delay (write_group, test_bgn, d);
5469
 
5470
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5471
 
5472
                if (!rw_mgr_mem_calibrate_read_test (rank_bgn, grp, NUM_READ_PB_TESTS, PASS_ONE_BIT, &bit_chk, 0, 0)) {
5473
                        break;
5474
                } else {
5475
                        for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
5476
                                if (bit_chk & 1) {
5477
                                        max_working_dq[i] = d;
5478
                                }
5479
                                bit_chk = bit_chk >> 1;
5480
                        }
5481
                }
5482
        }
5483
 
5484
        //USER determine minimum working value for DQ 
5485
 
5486
        dq_margin = IO_IO_IN_DELAY_MAX;
5487
 
5488
        for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
5489
                if (max_working_dq[i] < dq_margin) {
5490
                        dq_margin = max_working_dq[i];
5491
                }
5492
        }
5493
 
5494
        //USER add delay to bring all DQ windows to the same "level" 
5495
 
5496
        for (i = 0, p = test_bgn; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++, p++) {
5497
                if (max_working_dq[i] > dq_margin) {
5498
                        scc_mgr_set_dq_in_delay(write_group, i, max_working_dq[i] - dq_margin);
5499
                } else {
5500
                        scc_mgr_set_dq_in_delay(write_group, i, 0);
5501
                }
5502
 
5503
                scc_mgr_load_dq (p, p);
5504
        }
5505
 
5506
        //USER sweep DQS window, may potentially have more window due to per-bit-deskew that was done
5507
        //USER in the previous step.
5508
 
5509
        start_dqs = READ_SCC_DQS_IN_DELAY(grp);
5510
 
5511
        for (d = start_dqs + 1; d <= IO_DQS_IN_DELAY_MAX; d++) {
5512
                scc_mgr_set_dqs_bus_in_delay(grp, d);
5513
                scc_mgr_load_dqs (grp);
5514
 
5515
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5516
 
5517
                if (!rw_mgr_mem_calibrate_read_test (rank_bgn, grp, NUM_READ_TESTS, PASS_ALL_BITS, &bit_chk, 0, 0)) {
5518
                        break;
5519
                }
5520
        }
5521
 
5522
        scc_mgr_set_dqs_bus_in_delay(grp, start_dqs);
5523
 
5524
        //USER margin on the DQS pin 
5525
 
5526
        dqs_margin = d - start_dqs - 1;
5527
 
5528
        //USER find mid point, +1 so that we don't go crazy pushing DQ 
5529
 
5530
        mid = (dq_margin + dqs_margin + 1) / 2;
5531
 
5532
        gbl->fom_in += dq_margin + dqs_margin;
5533
//      TCLRPT_SET(debug_summary_report->fom_in, debug_summary_report->fom_in + (dq_margin + dqs_margin));
5534
//      TCLRPT_SET(debug_cal_report->cal_status_per_group[grp].fom_in, (dq_margin + dqs_margin));
5535
 
5536
 
5537
 
5538
 
5539
#if ENABLE_DQS_IN_CENTERING
5540
        //USER center DQS ... if the headroom is setup properly we shouldn't need to 
5541
 
5542
        if (dqs_margin > mid) {
5543
                scc_mgr_set_dqs_bus_in_delay(grp, READ_SCC_DQS_IN_DELAY(grp) + dqs_margin - mid);
5544
 
5545
                if (DDRX) {
5546
                        alt_u32 delay = READ_SCC_DQS_EN_DELAY(grp) + dqs_margin - mid;
5547
 
5548
                        if (delay > IO_DQS_EN_DELAY_MAX) {
5549
                                delay = IO_DQS_EN_DELAY_MAX;
5550
                        }
5551
 
5552
                        scc_mgr_set_dqs_en_delay(grp, delay);
5553
                }
5554
        }
5555
#endif
5556
 
5557
        scc_mgr_load_dqs (grp);
5558
 
5559
        //USER center DQ 
5560
 
5561
        if (dq_margin > mid) {
5562
                for (i = 0, p = test_bgn; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++, p++) {
5563
                        scc_mgr_set_dq_in_delay(write_group, i, READ_SCC_DQ_IN_DELAY(i) + dq_margin - mid);
5564
                        scc_mgr_load_dq (p, p);
5565
                }
5566
 
5567
                dqs_margin += dq_margin - mid;
5568
                dq_margin  -= dq_margin - mid;
5569
        }
5570
 
5571
        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5572
 
5573
        return (dq_margin + dqs_margin) > 0;
5574
}
5575
 
5576
#endif
5577
 
5578
//USER calibrate the read valid prediction FIFO.
5579
//USER 
5580
//USER  - read valid prediction will consist of finding a good DQS enable phase, DQS enable delay, DQS input phase, and DQS input delay.
5581
//USER  - we also do a per-bit deskew on the DQ lines.
5582
 
5583
#if DYNAMIC_CALIBRATION_MODE || STATIC_QUICK_CALIBRATION
5584
 
5585
#if !ENABLE_SUPER_QUICK_CALIBRATION
5586
 
5587
//USER VFIFO Calibration -- Quick Calibration
5588
alt_u32 rw_mgr_mem_calibrate_vfifo (alt_u32 g, alt_u32 test_bgn)
5589
{
5590
        alt_u32 v, d, i;
5591
        alt_u32 found;
5592
        t_btfld bit_chk;
5593
 
5594
        TRACE_FUNC("%lu %lu", grp, test_bgn);
5595
 
5596
        //USER update info for sims 
5597
 
5598
        reg_file_set_stage(CAL_STAGE_VFIFO);
5599
 
5600
        //USER Load up the patterns used by read calibration 
5601
 
5602
        rw_mgr_mem_calibrate_read_load_patterns_all_ranks ();
5603
 
5604
        //USER maximum phase values for the sweep 
5605
 
5606
 
5607
        //USER update info for sims 
5608
 
5609
        reg_file_set_group(g);
5610
 
5611
        found = 0;
5612
        v = 0;
5613
        for (i = 0; i < VFIFO_SIZE && found == 0; i++) {
5614
                for (d = 0; d <= IO_DQS_EN_PHASE_MAX && found == 0; d++) {
5615
                        if (DDRX)
5616
                        {
5617
                                scc_mgr_set_dqs_en_phase_all_ranks(g, d);
5618
                        }
5619
 
5620
                        //USER calibrate the vfifo with the current dqs enable phase setting 
5621
 
5622
                        if (rw_mgr_mem_calibrate_read_test_all_ranks (g, 1, PASS_ONE_BIT, &bit_chk, 0)) {
5623
                                found = 1;
5624
                        }
5625
                }
5626
 
5627
                if (found) {
5628
                        break;
5629
                } else {
5630
                        rw_mgr_incr_vfifo_all (g, &v);
5631
                }
5632
        }
5633
 
5634
        return found;
5635
}
5636
 
5637
#else
5638
 
5639
//USER VFIFO Calibration -- Super Quick Calibration
5640
alt_u32 rw_mgr_mem_calibrate_vfifo (alt_u32 grp, alt_u32 test_bgn2)
5641
{
5642
        alt_u32 g, v, d, i;
5643
        alt_u32 test_bgn;
5644
        alt_u32 found;
5645
        t_btfld bit_chk;
5646
        alt_u32 phase_increment;
5647
        alt_u32 final_v_setting = 0;
5648
        alt_u32 final_d_setting = 0;
5649
 
5650
        TRACE_FUNC("%lu %lu", grp, test_bgn2);
5651
 
5652
        #if ARRIAV || CYCLONEV
5653
            // Compensate for simulation model behaviour 
5654
            for (i = 0; i < RW_MGR_MEM_IF_READ_DQS_WIDTH; i++) {
5655
                scc_mgr_set_dqs_bus_in_delay(i, 10);
5656
                scc_mgr_load_dqs (i);
5657
            }
5658
            IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5659
        #endif
5660
 
5661
        //USER The first call to this function will calibrate all groups
5662
        if (grp !=0) {
5663
                return 1;
5664
        }
5665
 
5666
        //USER update info for sims 
5667
 
5668
        reg_file_set_stage(CAL_STAGE_VFIFO);
5669
 
5670
        //USER Load up the patterns used by read calibration 
5671
 
5672
        rw_mgr_mem_calibrate_read_load_patterns_all_ranks ();
5673
 
5674
        //USER maximum phase values for the sweep 
5675
 
5676
        //USER Calibrate group 0
5677
        g = 0;
5678
        test_bgn = 0;
5679
 
5680
        //USER update info for sims
5681
 
5682
        reg_file_set_group(g);
5683
 
5684
        found = 0;
5685
 
5686
        //USER In behavioral simulation only phases 0 and IO_DQS_EN_PHASE_MAX/2 are relevant
5687
        //USER All other values produces the same results as those 2, so there's really no
5688
        //USER point in sweeping them all
5689
        phase_increment = (IO_DQS_EN_PHASE_MAX + 1) / 2;
5690
        //USER Make sure phase_increment is > 0 to prevent infinite loop
5691
        if (phase_increment == 0) phase_increment++;
5692
 
5693
        v = 0;
5694
        for (i = 0; i < VFIFO_SIZE && found == 0; i++) {
5695
                for (d = 0; d <= IO_DQS_EN_PHASE_MAX && found == 0; d += phase_increment) {
5696
 
5697
                        scc_mgr_set_dqs_en_phase_all_ranks(g, d);
5698
 
5699
                        //USER calibrate the vfifo with the current dqs enable phase setting 
5700
 
5701
                        if (rw_mgr_mem_calibrate_read_test_all_ranks (g, 1, PASS_ONE_BIT, &bit_chk, 0)) {
5702
                                found = 1;
5703
                                final_v_setting = v;
5704
                                final_d_setting = d;
5705
                        }
5706
                }
5707
 
5708
                if (!found) {
5709
                        rw_mgr_incr_vfifo_all (g, &v);
5710
                } else {
5711
                        break;
5712
                }
5713
        }
5714
 
5715
        if (!found) return 0;
5716
 
5717
        //USER Now copy the calibration settings to all other groups
5718
        for (g = 1, test_bgn = RW_MGR_MEM_DQ_PER_READ_DQS; (g < RW_MGR_MEM_IF_READ_DQS_WIDTH) && found; g++, test_bgn += RW_MGR_MEM_DQ_PER_READ_DQS) {
5719
                //USER Set the VFIFO
5720
                v = 0;
5721
                for (i = 0; i < final_v_setting; i++) {
5722
                        rw_mgr_incr_vfifo_all (g, &v);
5723
                }
5724
 
5725
                //USER Set the proper phase
5726
                IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, g);
5727
                scc_mgr_set_dqs_en_phase_all_ranks(g, final_d_setting);
5728
 
5729
                //USER Verify that things worked as expected
5730
                if(!rw_mgr_mem_calibrate_read_test_all_ranks (g, 1, PASS_ONE_BIT, &bit_chk, 0)) {
5731
                        //USER Fail
5732
                        found = 0;
5733
                }
5734
        }
5735
 
5736
        IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, 0);
5737
        return found;
5738
}
5739
 
5740
#endif
5741
#endif
5742
 
5743
#if DYNAMIC_CALIBRATION_MODE || STATIC_FULL_CALIBRATION
5744
 
5745
#if NEWVERSION_GW
5746
 
5747
//USER VFIFO Calibration -- Full Calibration
5748
alt_u32 rw_mgr_mem_calibrate_vfifo (alt_u32 read_group, alt_u32 test_bgn)
5749
{
5750
        alt_u32 p, d, rank_bgn, sr;
5751
        alt_u32 dtaps_per_ptap;
5752
        alt_u32 tmp_delay;
5753
        t_btfld bit_chk;
5754
        alt_u32 grp_calibrated;
5755
        alt_u32 write_group, write_test_bgn;
5756
        alt_u32 failed_substage;
5757
        alt_u32 dqs_in_dtaps, orig_start_dqs;
5758
 
5759
        TRACE_FUNC("%lu %lu", read_group, test_bgn);
5760
 
5761
        //USER update info for sims 
5762
 
5763
        reg_file_set_stage(CAL_STAGE_VFIFO);
5764
 
5765
        if (DDRX) {
5766
                write_group = read_group;
5767
                write_test_bgn = test_bgn;
5768
        } else {
5769
                write_group = read_group / (RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
5770
                write_test_bgn = read_group * RW_MGR_MEM_DQ_PER_READ_DQS;
5771
        }
5772
 
5773
        // USER Determine number of delay taps for each phase tap
5774
        dtaps_per_ptap = 0;
5775
        tmp_delay = 0;
5776
        if (!QDRII) {
5777
                while (tmp_delay < IO_DELAY_PER_OPA_TAP) {
5778
                        dtaps_per_ptap++;
5779
                        tmp_delay += IO_DELAY_PER_DQS_EN_DCHAIN_TAP;
5780
                }
5781
                dtaps_per_ptap--;
5782
                tmp_delay = 0;
5783
        }
5784
 
5785
        //USER update info for sims 
5786
 
5787
        reg_file_set_group(read_group);
5788
 
5789
        grp_calibrated = 0;
5790
 
5791
        reg_file_set_sub_stage(CAL_SUBSTAGE_GUARANTEED_READ);
5792
        failed_substage = CAL_SUBSTAGE_GUARANTEED_READ;
5793
 
5794
        for (d = 0; d <= dtaps_per_ptap && grp_calibrated == 0; d+=2) {
5795
 
5796
                if (DDRX || RLDRAMX) {
5797
                        // In RLDRAMX we may be messing the delay of pins in the same write group but outside of
5798
                        // the current read group, but that's ok because we haven't calibrated the output side yet.
5799
                        if (d > 0) {
5800
                                scc_mgr_apply_group_all_out_delay_add_all_ranks (write_group, write_test_bgn, d);
5801
                        }
5802
                }
5803
 
5804
                for (p = 0; p <= IO_DQDQS_OUT_PHASE_MAX && grp_calibrated == 0; p++) {
5805
                        //USER set a particular dqdqs phase 
5806
                        if (DDRX) {
5807
                                scc_mgr_set_dqdqs_output_phase_all_ranks(read_group, p);
5808
                        }
5809
 
5810
                        //USER Previous iteration may have failed as a result of ck/dqs or ck/dk violation,
5811
                        //USER in which case the device may require special recovery.
5812
                        if (DDRX || RLDRAMX) {
5813
                                if (d != 0 || p != 0) {
5814
                                        recover_mem_device_after_ck_dqs_violation();
5815
                                }
5816
                        }
5817
 
5818
                        DPRINT(1, "calibrate_vfifo: g=%lu p=%lu d=%lu", read_group, p, d);
5819
                        BFM_GBL_SET(gwrite_pos[read_group].p, p);
5820
                        BFM_GBL_SET(gwrite_pos[read_group].d, d);
5821
 
5822
                        //USER Load up the patterns used by read calibration using current DQDQS phase 
5823
 
5824
#if BFM_MODE
5825
                        // handled by pre-initializing memory if skipping
5826
                        if (bfm_gbl.bfm_skip_guaranteed_write == 0) {
5827
                                rw_mgr_mem_calibrate_read_load_patterns_all_ranks ();
5828
                        }
5829
#else
5830
                        rw_mgr_mem_calibrate_read_load_patterns_all_ranks ();
5831
 
5832
#if DDRX
5833
#if !AP_MODE
5834
                        if (!(gbl->phy_debug_mode_flags & PHY_DEBUG_DISABLE_GUARANTEED_READ)) {
5835
                                if (!rw_mgr_mem_calibrate_read_test_patterns_all_ranks (read_group, 1, &bit_chk)) {
5836
                                        DPRINT(1, "Guaranteed read test failed: g=%lu p=%lu d=%lu", read_group, p, d);
5837
                                        break;
5838
                                }
5839
                        }
5840
#endif
5841
#endif
5842
#endif
5843
 
5844
#if ARRIAV || CYCLONEV
5845
                        ///////
5846
                        // To make DQS bypass able to calibrate more often
5847
                        ///////
5848
                        // Loop over different DQS in delay chains for the purpose of DQS Enable calibration finding one bit working
5849
                        orig_start_dqs = READ_SCC_DQS_IN_DELAY(read_group);
5850
                        for (dqs_in_dtaps = orig_start_dqs; dqs_in_dtaps <= IO_DQS_IN_DELAY_MAX && grp_calibrated == 0; dqs_in_dtaps++) {
5851
 
5852
                                for (rank_bgn = 0, sr = 0; rank_bgn < RW_MGR_MEM_NUMBER_OF_RANKS; rank_bgn += NUM_RANKS_PER_SHADOW_REG, ++sr) {
5853
 
5854
                                        if (! param->skip_shadow_regs[sr]) {
5855
 
5856
                                                //USER Select shadow register set
5857
                                                select_shadow_regs_for_update(rank_bgn, read_group, 1);
5858
 
5859
                                                WRITE_SCC_DQS_IN_DELAY(read_group, dqs_in_dtaps);
5860
                                                scc_mgr_load_dqs (read_group);
5861
                                                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5862
                                        }
5863
                                }
5864
#endif                          
5865
 
5866
// case:56390
5867
#if 0 && ARRIAV && QDRII
5868
                                // Note, much of this counts on the fact that we don't need to keep track
5869
                                // of what vfifo offset we are at because incr_vfifo doesn't use it
5870
                                // We also assume only a single group, and that the vfifo incrementers start at offset zero
5871
 
5872
#define BIT(w,b) (((w) >> (b)) & 1)
5873
                                {
5874
                                        alt_u32 prev;
5875
                                        alt_u32 vbase;
5876
                                        alt_u32 i;
5877
 
5878
                                        grp_calibrated = 0;
5879
 
5880
                                        // check every combination of vfifo relative settings
5881
                                        for (prev = vbase = 0; vbase < (1 << VFIFO_CONTROL_WIDTH_PER_DQS); prev=vbase, vbase++ ) {
5882
                                                // check each bit to see if we need to increment, decrement, or leave the corresponding vfifo alone
5883
                                                for (i = 0; i < VFIFO_CONTROL_WIDTH_PER_DQS; i++) {
5884
                                                        if (BIT(vbase,i) > BIT(prev,i)) {
5885
                                                                rw_mgr_incr_vfifo(read_group*VFIFO_CONTROL_WIDTH_PER_DQS + i,0);
5886
                                                        } else if (BIT(vbase,i) < BIT(prev,i)) {
5887
                                                                rw_mgr_decr_vfifo(read_group*VFIFO_CONTROL_WIDTH_PER_DQS + i,0);
5888
                                                        }
5889
                                                }
5890
                                                if (rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase_sweep_dq_in_delay (write_group, read_group, test_bgn)) {
5891
 
5892
#if ARRIAV || CYCLONEV                                          
5893
                                                        ///////
5894
                                                        // To make DQS bypass able to calibrate more often
5895
                                                        ///////
5896
                                                        // Before doing read deskew, set DQS in back to the reserve value
5897
                                                        WRITE_SCC_DQS_IN_DELAY(read_group, orig_start_dqs);
5898
                                                        scc_mgr_load_dqs (read_group);
5899
                                                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5900
#endif
5901
 
5902
                                                        if (! rw_mgr_mem_calibrate_vfifo_center (0, write_group, read_group, test_bgn, 1)) {
5903
                                                                // remember last failed stage
5904
                                                                failed_substage = CAL_SUBSTAGE_VFIFO_CENTER;
5905
                                                        } else {
5906
                                                                grp_calibrated = 1;
5907
                                                        }
5908
                                                } else {
5909
                                                        failed_substage = CAL_SUBSTAGE_DQS_EN_PHASE;
5910
                                                }
5911
                                                if (grp_calibrated) {
5912
                                                        break;
5913
                                                }
5914
 
5915
                                                break; // comment out for fix
5916
 
5917
                                        }
5918
                                }
5919
#else                           
5920
                                grp_calibrated = 1;
5921
                                if (rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase_sweep_dq_in_delay (write_group, read_group, test_bgn)) {
5922
                                        // USER Read per-bit deskew can be done on a per shadow register basis
5923
                                        for (rank_bgn = 0, sr = 0; rank_bgn < RW_MGR_MEM_NUMBER_OF_RANKS; rank_bgn += NUM_RANKS_PER_SHADOW_REG, ++sr) {
5924
#if RUNTIME_CAL_REPORT          
5925
                                                //Report print can cause a delay at each instance of rw_mgr_mem_calibrate_vfifo_center, need to re-issue guaranteed write to ensure no refresh violation
5926
                                                rw_mgr_mem_calibrate_read_load_patterns_all_ranks ();
5927
#endif                          
5928
                                                //USER Determine if this set of ranks should be skipped entirely
5929
                                                if (! param->skip_shadow_regs[sr]) {
5930
 
5931
                                                        //USER Select shadow register set
5932
                                                        select_shadow_regs_for_update(rank_bgn, read_group, 1);
5933
 
5934
#if ARRIAV || CYCLONEV
5935
                                                        ///////
5936
                                                        // To make DQS bypass able to calibrate more often
5937
                                                        ///////
5938
                                                        // Before doing read deskew, set DQS in back to the reserve value
5939
                                                        WRITE_SCC_DQS_IN_DELAY(read_group, orig_start_dqs);
5940
                                                        scc_mgr_load_dqs (read_group);
5941
                                                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
5942
#endif
5943
 
5944
                                                        // If doing read after write calibration, do not update FOM now - do it then
5945
#if READ_AFTER_WRITE_CALIBRATION
5946
                                                        if (! rw_mgr_mem_calibrate_vfifo_center (rank_bgn, write_group, read_group, test_bgn, 1, 0)) {
5947
#else
5948
                                                        if (! rw_mgr_mem_calibrate_vfifo_center (rank_bgn, write_group, read_group, test_bgn, 1, 1)) {
5949
#endif
5950
                                                                grp_calibrated = 0;
5951
                                                                failed_substage = CAL_SUBSTAGE_VFIFO_CENTER;
5952
                                                        }
5953
                                                }
5954
                                        }
5955
                                } else {
5956
                                        grp_calibrated = 0;
5957
                                        failed_substage = CAL_SUBSTAGE_DQS_EN_PHASE;
5958
                                }
5959
#endif
5960
#if BFM_MODE
5961
                                if (bfm_gbl.bfm_skip_guaranteed_write > 0 && !grp_calibrated) {
5962
                                        // This should never happen with pre-initialized guaranteed write load pattern
5963
                                        // unless calibration was always going to fail
5964
                                        DPRINT(0, "calibrate_vfifo: skip guaranteed write calibration failed");
5965
                                        break;
5966
                                } else if (bfm_gbl.bfm_skip_guaranteed_write == -1) {
5967
                                        // if skip value is -1, then we expect to fail, but we want to use
5968
                                        // the regular guaranteed write next time
5969
                                        if (grp_calibrated) {
5970
                                                // We shouldn't be succeeding for this test, so this is an error
5971
                                                DPRINT(0, "calibrate_vfifo: ERROR: skip guaranteed write == -1, but calibration passed");
5972
                                                grp_calibrated = 0;
5973
                                                break;
5974
                                        } else {
5975
                                                DPRINT(0, "calibrate_vfifo: skip guaranteed write == -1, expected failure, trying again with no skip");
5976
                                                bfm_gbl.bfm_skip_guaranteed_write = 0;
5977
                                        }
5978
                                }
5979
 
5980
#endif
5981
#if ARRIAV || CYCLONEV
5982
                        ///////
5983
                        // To make DQS bypass able to calibrate more often
5984
                        ///////
5985
                        }
5986
#endif                  
5987
 
5988
                }
5989
#if BFM_MODE
5990
                if (bfm_gbl.bfm_skip_guaranteed_write && !grp_calibrated) break;
5991
#endif
5992
        }
5993
 
5994
        if (grp_calibrated == 0) {
5995
                set_failing_group_stage(write_group, CAL_STAGE_VFIFO, failed_substage);
5996
 
5997
                return 0;
5998
        }
5999
 
6000
        //USER Reset the delay chains back to zero if they have moved > 1 (check for > 1 because loop will increase d even when pass in first case)
6001
        if (DDRX || RLDRAMII) {
6002
                if (d > 2) {
6003
                        scc_mgr_zero_group(write_group, write_test_bgn, 1);
6004
                }
6005
        }
6006
 
6007
 
6008
        return 1;
6009
}
6010
 
6011
#else
6012
 
6013
//USER VFIFO Calibration -- Full Calibration
6014
alt_u32 rw_mgr_mem_calibrate_vfifo (alt_u32 g, alt_u32 test_bgn)
6015
{
6016
        alt_u32 p, rank_bgn, sr;
6017
        alt_u32 grp_calibrated;
6018
        alt_u32 failed_substage;
6019
 
6020
        TRACE_FUNC("%lu %lu", g, test_bgn);
6021
 
6022
        //USER update info for sims 
6023
 
6024
        reg_file_set_stage(CAL_STAGE_VFIFO);
6025
 
6026
        reg_file_set_sub_stage(CAL_SUBSTAGE_GUARANTEED_READ);
6027
 
6028
        failed_substage = CAL_SUBSTAGE_GUARANTEED_READ;
6029
 
6030
        //USER update info for sims 
6031
 
6032
        reg_file_set_group(g);
6033
 
6034
        grp_calibrated = 0;
6035
 
6036
        for (p = 0; p <= IO_DQDQS_OUT_PHASE_MAX && grp_calibrated == 0; p++) {
6037
                //USER set a particular dqdqs phase 
6038
                if (DDRX) {
6039
                        scc_mgr_set_dqdqs_output_phase_all_ranks(g, p);
6040
                }
6041
 
6042
                //USER Load up the patterns used by read calibration using current DQDQS phase 
6043
 
6044
                rw_mgr_mem_calibrate_read_load_patterns_all_ranks ();
6045
#if DDRX
6046
                if (!(gbl->phy_debug_mode_flags & PHY_DEBUG_DISABLE_GUARANTEED_READ)) {
6047
                        if (!rw_mgr_mem_calibrate_read_test_patterns_all_ranks (read_group, 1, &bit_chk)) {
6048
                                break;
6049
                        }
6050
                }
6051
#endif
6052
 
6053
                grp_calibrated = 1;
6054
                if (rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase_sweep_dq_in_delay (g, g, test_bgn)) {
6055
                        // USER Read per-bit deskew can be done on a per shadow register basis
6056
                        for (rank_bgn = 0, sr = 0; rank_bgn < RW_MGR_MEM_NUMBER_OF_RANKS; rank_bgn += NUM_RANKS_PER_SHADOW_REG, ++sr) {
6057
 
6058
                                //USER Determine if this set of ranks should be skipped entirely
6059
                                if (! param->skip_shadow_regs[sr]) {
6060
 
6061
                                        //USER Select shadow register set
6062
                                        select_shadow_regs_for_update(rank_bgn, read_group, 1);
6063
 
6064
                                        if (! rw_mgr_mem_calibrate_vfifo_center (rank_bgn, g, test_bgn, 1)) {
6065
                                                grp_calibrated = 0;
6066
                                                failed_substage = CAL_SUBSTAGE_VFIFO_CENTER;
6067
                                        }
6068
                                }
6069
                        }
6070
                } else {
6071
                        grp_calibrated = 0;
6072
                        failed_substage = CAL_SUBSTAGE_DQS_EN_PHASE;
6073
                }
6074
        }
6075
 
6076
        if (grp_calibrated == 0) {
6077
                set_failing_group_stage(g, CAL_STAGE_VFIFO, failed_substage);
6078
                return 0;
6079
        }
6080
 
6081
 
6082
        return 1;
6083
}
6084
 
6085
#endif
6086
 
6087
#endif
6088
 
6089
#if READ_AFTER_WRITE_CALIBRATION
6090
//USER VFIFO Calibration -- Read Deskew Calibration after write deskew
6091
alt_u32 rw_mgr_mem_calibrate_vfifo_end (alt_u32 read_group, alt_u32 test_bgn)
6092
{
6093
        alt_u32 rank_bgn, sr;
6094
        alt_u32 grp_calibrated;
6095
        alt_u32 write_group;
6096
 
6097
        TRACE_FUNC("%lu %lu", read_group, test_bgn);
6098
 
6099
        //USER update info for sims 
6100
 
6101
        reg_file_set_stage(CAL_STAGE_VFIFO_AFTER_WRITES);
6102
        reg_file_set_sub_stage(CAL_SUBSTAGE_VFIFO_CENTER);
6103
 
6104
        if (DDRX) {
6105
                write_group = read_group;
6106
        } else {
6107
                write_group = read_group / (RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
6108
        }
6109
 
6110
        //USER update info for sims 
6111
        reg_file_set_group(read_group);
6112
 
6113
        grp_calibrated = 1;
6114
        // USER Read per-bit deskew can be done on a per shadow register basis
6115
        for (rank_bgn = 0, sr = 0; rank_bgn < RW_MGR_MEM_NUMBER_OF_RANKS; rank_bgn += NUM_RANKS_PER_SHADOW_REG, ++sr) {
6116
 
6117
                //USER Determine if this set of ranks should be skipped entirely
6118
                if (! param->skip_shadow_regs[sr]) {
6119
 
6120
                        //USER Select shadow register set
6121
                        select_shadow_regs_for_update(rank_bgn, read_group, 1);
6122
 
6123
            // This is the last calibration round, update FOM here
6124
                        if (! rw_mgr_mem_calibrate_vfifo_center (rank_bgn, write_group, read_group, test_bgn, 0, 1)) {
6125
                                grp_calibrated = 0;
6126
                        }
6127
                }
6128
        }
6129
 
6130
 
6131
        if (grp_calibrated == 0) {
6132
                set_failing_group_stage(write_group, CAL_STAGE_VFIFO_AFTER_WRITES, CAL_SUBSTAGE_VFIFO_CENTER);
6133
                return 0;
6134
        }
6135
 
6136
        return 1;
6137
}
6138
#endif
6139
 
6140
 
6141
//USER Calibrate LFIFO to find smallest read latency
6142
 
6143
alt_u32 rw_mgr_mem_calibrate_lfifo (void)
6144
{
6145
        alt_u32 found_one;
6146
        t_btfld bit_chk;
6147
        alt_u32 g;
6148
 
6149
        TRACE_FUNC();
6150
        BFM_STAGE("lfifo");
6151
 
6152
        //USER update info for sims 
6153
 
6154
        reg_file_set_stage(CAL_STAGE_LFIFO);
6155
        reg_file_set_sub_stage(CAL_SUBSTAGE_READ_LATENCY);
6156
 
6157
        //USER Load up the patterns used by read calibration for all ranks
6158
 
6159
        rw_mgr_mem_calibrate_read_load_patterns_all_ranks ();
6160
 
6161
        found_one = 0;
6162
 
6163
        do {
6164
                IOWR_32DIRECT (PHY_MGR_PHY_RLAT, 0, gbl->curr_read_lat);
6165
                DPRINT(2, "lfifo: read_lat=%lu", gbl->curr_read_lat);
6166
 
6167
                if (!rw_mgr_mem_calibrate_read_test_all_ranks (0, NUM_READ_TESTS, PASS_ALL_BITS, &bit_chk, 1)) {
6168
                        break;
6169
                }
6170
 
6171
                found_one = 1;
6172
 
6173
                //USER reduce read latency and see if things are working
6174
                //USER correctly
6175
 
6176
                gbl->curr_read_lat--;
6177
        } while (gbl->curr_read_lat > 0);
6178
 
6179
        //USER reset the fifos to get pointers to known state 
6180
 
6181
        IOWR_32DIRECT (PHY_MGR_CMD_FIFO_RESET, 0, 0);
6182
 
6183
#if SET_FIX_READ_LATENCY_ENABLE          
6184
   if(gbl->curr_read_lat < (FIX_READ_LATENCY -1) ) {
6185
      gbl->curr_read_lat = FIX_READ_LATENCY -2;
6186
   } else {
6187
     //Mark as fail by changing found_one back to 0
6188
      found_one = 0 ;
6189
   }
6190
#endif 
6191
 
6192
        if (found_one) {
6193
                //USER add a fudge factor to the read latency that was determined 
6194
                gbl->curr_read_lat += 2;
6195
#if BFM_MODE
6196
                gbl->curr_read_lat += BFM_GBL_GET(lfifo_margin);
6197
#endif
6198
                IOWR_32DIRECT (PHY_MGR_PHY_RLAT, 0, gbl->curr_read_lat);
6199
#if RUNTIME_CAL_REPORT          
6200
                RPRINT("LFIFO Calibration ; PHY Read Latency %li", gbl->curr_read_lat);
6201
#endif
6202
 
6203
                DPRINT(2, "lfifo: success: using read_lat=%lu", gbl->curr_read_lat);
6204
 
6205
                return 1;
6206
        } else {
6207
                set_failing_group_stage(0xff, CAL_STAGE_LFIFO, CAL_SUBSTAGE_READ_LATENCY);
6208
 
6209
                for (g = 0; g < RW_MGR_MEM_IF_WRITE_DQS_WIDTH; g++)
6210
                {
6211
                        TCLRPT_SET(debug_cal_report->cal_status_per_group[curr_shadow_reg][g].error_stage, CAL_STAGE_LFIFO);
6212
                        TCLRPT_SET(debug_cal_report->cal_status_per_group[curr_shadow_reg][g].error_sub_stage, CAL_SUBSTAGE_READ_LATENCY);
6213
                }
6214
 
6215
                DPRINT(2, "lfifo: failed at initial read_lat=%lu", gbl->curr_read_lat);
6216
 
6217
                return 0;
6218
        }
6219
}
6220
 
6221
//USER issue write test command.
6222
//USER two variants are provided. one that just tests a write pattern and another that
6223
//USER tests datamask functionality.
6224
 
6225
#if QDRII
6226
void rw_mgr_mem_calibrate_write_test_issue (alt_u32 group, alt_u32 test_dm)
6227
{
6228
        alt_u32 quick_write_mode = (((STATIC_CALIB_STEPS) & CALIB_SKIP_WRITES) && ENABLE_SUPER_QUICK_CALIBRATION) || BFM_MODE;
6229
 
6230
        //USER CNTR 1 - This is used to ensure enough time elapses for read data to come back.
6231
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x30);
6232
 
6233
        if (test_dm) {
6234
                IOWR_32DIRECT (RW_MGR_RESET_READ_DATAPATH, 0, 0);
6235
                if(quick_write_mode) {
6236
                        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x08);
6237
                } else {
6238
                        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x40);
6239
                }
6240
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_LFSR_WR_RD_DM_BANK_0);
6241
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_LFSR_WR_RD_DM_BANK_0_WAIT);
6242
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, (group) << 2, __RW_MGR_LFSR_WR_RD_DM_BANK_0);
6243
        } else {
6244
                IOWR_32DIRECT (RW_MGR_RESET_READ_DATAPATH, 0, 0);
6245
                if(quick_write_mode) {
6246
                        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x08);
6247
                } else {
6248
                        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x40);
6249
                }
6250
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_LFSR_WR_RD_BANK_0);
6251
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_LFSR_WR_RD_BANK_0_WAIT);
6252
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, (group) << 2, __RW_MGR_LFSR_WR_RD_BANK_0);
6253
        }
6254
}
6255
#else
6256
void rw_mgr_mem_calibrate_write_test_issue (alt_u32 group, alt_u32 test_dm)
6257
{
6258
        alt_u32 mcc_instruction;
6259
        alt_u32 quick_write_mode = (((STATIC_CALIB_STEPS) & CALIB_SKIP_WRITES) && ENABLE_SUPER_QUICK_CALIBRATION) || BFM_MODE;
6260
        alt_u32 rw_wl_nop_cycles;
6261
 
6262
        //USER Set counter and jump addresses for the right
6263
        //USER number of NOP cycles.
6264
        //USER The number of supported NOP cycles can range from -1 to infinity
6265
        //USER Three different cases are handled:
6266
        //USER
6267
        //USER 1. For a number of NOP cycles greater than 0, the RW Mgr looping
6268
        //USER    mechanism will be used to insert the right number of NOPs
6269
        //USER
6270
        //USER 2. For a number of NOP cycles equals to 0, the micro-instruction
6271
        //USER    issuing the write command will jump straight to the micro-instruction
6272
        //USER    that turns on DQS (for DDRx), or outputs write data (for RLD), skipping
6273
        //USER    the NOP micro-instruction all together
6274
        //USER
6275
        //USER 3. A number of NOP cycles equal to -1 indicates that DQS must be turned
6276
        //USER    on in the same micro-instruction that issues the write command. Then we need
6277
        //USER    to directly jump to the micro-instruction that sends out the data
6278
        //USER
6279
        //USER NOTE: Implementing this mechanism uses 2 RW Mgr jump-counters (2 and 3). One
6280
        //USER       jump-counter (0) is used to perform multiple write-read operations.
6281
        //USER       one counter left to issue this command in "multiple-group" mode.
6282
 
6283
#if MULTIPLE_AFI_WLAT
6284
        rw_wl_nop_cycles = gbl->rw_wl_nop_cycles_per_group[group];
6285
#else
6286
        rw_wl_nop_cycles = gbl->rw_wl_nop_cycles;
6287
#endif  
6288
 
6289
        if(rw_wl_nop_cycles == -1)
6290
        {
6291
                #if DDRX
6292
                //USER CNTR 2 - We want to execute the special write operation that
6293
                //USER turns on DQS right away and then skip directly to the instruction that
6294
                //USER sends out the data. We set the counter to a large number so that the
6295
                //USER jump is always taken
6296
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0xFF);
6297
 
6298
                //USER CNTR 3 - Not used
6299
                if(test_dm)
6300
                {
6301
                        mcc_instruction = __RW_MGR_LFSR_WR_RD_DM_BANK_0_WL_1;
6302
                        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_LFSR_WR_RD_DM_BANK_0_DATA);
6303
                        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_3, 0, __RW_MGR_LFSR_WR_RD_DM_BANK_0_NOP);
6304
                }
6305
                else
6306
                {
6307
                        mcc_instruction = __RW_MGR_LFSR_WR_RD_BANK_0_WL_1;
6308
                        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_LFSR_WR_RD_BANK_0_DATA);
6309
                        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_3, 0, __RW_MGR_LFSR_WR_RD_BANK_0_NOP);
6310
                }
6311
 
6312
                #endif
6313
        }
6314
        else if(rw_wl_nop_cycles == 0)
6315
        {
6316
                #if DDRX
6317
                //USER CNTR 2 - We want to skip the NOP operation and go straight to
6318
                //USER the DQS enable instruction. We set the counter to a large number so that the
6319
                //USER jump is always taken
6320
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0xFF);
6321
 
6322
                //USER CNTR 3 - Not used
6323
                if(test_dm)
6324
                {
6325
                        mcc_instruction = __RW_MGR_LFSR_WR_RD_DM_BANK_0;
6326
                        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_LFSR_WR_RD_DM_BANK_0_DQS);
6327
                }
6328
                else
6329
                {
6330
                        mcc_instruction = __RW_MGR_LFSR_WR_RD_BANK_0;
6331
                        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_LFSR_WR_RD_BANK_0_DQS);
6332
                }
6333
                #endif
6334
 
6335
                #if RLDRAMX
6336
                //USER CNTR 2 - We want to skip the NOP operation and go straight to
6337
                //USER the write data instruction. We set the counter to a large number so that the
6338
                //USER jump is always taken
6339
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0xFF);
6340
 
6341
                //USER CNTR 3 - Not used
6342
                if(test_dm)
6343
                {
6344
                        mcc_instruction = __RW_MGR_LFSR_WR_RD_DM_BANK_0;
6345
                        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_LFSR_WR_RD_DM_BANK_0_DATA);
6346
                }
6347
                else
6348
                {
6349
                        mcc_instruction = __RW_MGR_LFSR_WR_RD_BANK_0;
6350
                        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_LFSR_WR_RD_BANK_0_DATA);
6351
                }
6352
                #endif
6353
        }
6354
        else
6355
        {
6356
                //USER CNTR 2 - In this case we want to execute the next instruction and NOT
6357
                //USER take the jump. So we set the counter to 0. The jump address doesn't count
6358
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0x0);
6359
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, 0x0);
6360
 
6361
                //USER CNTR 3 - Set the nop counter to the number of cycles we need to loop for, minus 1
6362
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_3, 0, rw_wl_nop_cycles - 1);
6363
                if(test_dm)
6364
                {
6365
                        mcc_instruction = __RW_MGR_LFSR_WR_RD_DM_BANK_0;
6366
                        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_3, 0, __RW_MGR_LFSR_WR_RD_DM_BANK_0_NOP);
6367
                }
6368
                else
6369
                {
6370
                        mcc_instruction = __RW_MGR_LFSR_WR_RD_BANK_0;
6371
                        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_3, 0, __RW_MGR_LFSR_WR_RD_BANK_0_NOP);
6372
                }
6373
        }
6374
 
6375
        IOWR_32DIRECT (RW_MGR_RESET_READ_DATAPATH, 0, 0);
6376
 
6377
        if(quick_write_mode) {
6378
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x08);
6379
        } else {
6380
#if ENABLE_NON_DES_CAL
6381
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x08); // Break this up for refresh purposes
6382
#else
6383
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x40);
6384
#endif
6385
        }
6386
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, mcc_instruction);
6387
 
6388
        //USER CNTR 1 - This is used to ensure enough time elapses for read data to come back.
6389
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x30);
6390
 
6391
        if(test_dm)
6392
        {
6393
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_LFSR_WR_RD_DM_BANK_0_WAIT);
6394
        } else {
6395
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_LFSR_WR_RD_BANK_0_WAIT);
6396
        }
6397
 
6398
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, (group << 2), mcc_instruction);
6399
 
6400
#if ENABLE_NON_DES_CAL  
6401
        alt_u32 i = 0;
6402
        for (i=0; i < 8; i++)
6403
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, (group << 2), mcc_instruction);
6404
#endif  
6405
 
6406
 
6407
 
6408
 
6409
 
6410
 
6411
 
6412
}
6413
#endif
6414
 
6415
//USER Test writes, can check for a single bit pass or multiple bit pass
6416
 
6417
alt_u32 rw_mgr_mem_calibrate_write_test (alt_u32 rank_bgn, alt_u32 write_group, alt_u32 use_dm, alt_u32 all_correct, t_btfld *bit_chk, alt_u32 all_ranks)
6418
{
6419
        alt_u32 r;
6420
        t_btfld correct_mask_vg;
6421
        t_btfld tmp_bit_chk;
6422
        alt_u32 vg;
6423
        alt_u32 rank_end = all_ranks ? RW_MGR_MEM_NUMBER_OF_RANKS : (rank_bgn + NUM_RANKS_PER_SHADOW_REG);
6424
 
6425
        *bit_chk = param->write_correct_mask;
6426
        correct_mask_vg = param->write_correct_mask_vg;
6427
 
6428
        for (r = rank_bgn; r < rank_end; r++) {
6429
                if (param->skip_ranks[r]) {
6430
                        //USER request to skip the rank
6431
 
6432
                        continue;
6433
                }
6434
 
6435
                //USER set rank 
6436
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_READ_WRITE);
6437
 
6438
                tmp_bit_chk = 0;
6439
                for (vg = RW_MGR_MEM_VIRTUAL_GROUPS_PER_WRITE_DQS-1; ; vg--) {
6440
 
6441
                        //USER reset the fifos to get pointers to known state 
6442
                        IOWR_32DIRECT (PHY_MGR_CMD_FIFO_RESET, 0, 0);
6443
 
6444
                        tmp_bit_chk = tmp_bit_chk << (RW_MGR_MEM_DQ_PER_WRITE_DQS / RW_MGR_MEM_VIRTUAL_GROUPS_PER_WRITE_DQS);
6445
                        rw_mgr_mem_calibrate_write_test_issue (write_group*RW_MGR_MEM_VIRTUAL_GROUPS_PER_WRITE_DQS+vg, use_dm);
6446
 
6447
                        tmp_bit_chk = tmp_bit_chk | (correct_mask_vg & ~(IORD_32DIRECT(BASE_RW_MGR, 0)));
6448
                        DPRINT(2, "write_test(%lu,%lu,%lu) :[%lu,%lu] " BTFLD_FMT " & ~%x => " BTFLD_FMT " => " BTFLD_FMT,
6449
                               write_group, use_dm, all_correct, r, vg,
6450
                               correct_mask_vg, IORD_32DIRECT(BASE_RW_MGR, 0), correct_mask_vg & ~IORD_32DIRECT(BASE_RW_MGR, 0),
6451
                               tmp_bit_chk);
6452
 
6453
                        if (vg == 0) {
6454
                                break;
6455
                        }
6456
                }
6457
                *bit_chk &= tmp_bit_chk;
6458
        }
6459
 
6460
        if (all_correct)
6461
        {
6462
                set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
6463
                DPRINT(2, "write_test(%lu,%lu,ALL) : " BTFLD_FMT " == " BTFLD_FMT " => %lu", write_group, use_dm,
6464
                       *bit_chk, param->write_correct_mask, (long unsigned int)(*bit_chk == param->write_correct_mask));
6465
                return (*bit_chk == param->write_correct_mask);
6466
        }
6467
        else
6468
        {
6469
                set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
6470
                DPRINT(2, "write_test(%lu,%lu,ONE) : " BTFLD_FMT " != " BTFLD_FMT " => %lu", write_group, use_dm,
6471
                       *bit_chk, (long unsigned int)0, (long unsigned int)(*bit_chk != 0));
6472
                return (*bit_chk != 0x00);
6473
        }
6474
}
6475
 
6476
static inline alt_u32 rw_mgr_mem_calibrate_write_test_all_ranks (alt_u32 write_group, alt_u32 use_dm, alt_u32 all_correct, t_btfld *bit_chk)
6477
{
6478
        return rw_mgr_mem_calibrate_write_test (0, write_group, use_dm, all_correct, bit_chk, 1);
6479
}
6480
 
6481
 
6482
//USER level the write operations
6483
 
6484
#if DYNAMIC_CALIBRATION_MODE || STATIC_QUICK_CALIBRATION
6485
 
6486
#if QDRII
6487
 
6488
//USER Write Levelling -- Quick Calibration
6489
alt_u32 rw_mgr_mem_calibrate_wlevel (alt_u32 g, alt_u32 test_bgn)
6490
{
6491
        TRACE_FUNC("%lu %lu", g, test_bgn);
6492
 
6493
        return 0;
6494
}
6495
 
6496
#endif
6497
 
6498
#if RLDRAMX
6499
#if !ENABLE_SUPER_QUICK_CALIBRATION
6500
 
6501
//USER Write Levelling -- Quick Calibration
6502
alt_u32 rw_mgr_mem_calibrate_wlevel (alt_u32 g, alt_u32 test_bgn)
6503
{
6504
        alt_u32 d;
6505
        t_btfld bit_chk;
6506
 
6507
        TRACE_FUNC("%lu %lu", g, test_bgn);
6508
 
6509
        //USER update info for sims
6510
 
6511
        reg_file_set_stage(CAL_STAGE_WLEVEL);
6512
        reg_file_set_sub_stage(CAL_SUBSTAGE_WORKING_DELAY);
6513
        reg_file_set_group(g);
6514
 
6515
        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX; d++) {
6516
                scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, d);
6517
 
6518
                if (rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
6519
                        break;
6520
                }
6521
        }
6522
 
6523
        if (d > IO_IO_OUT1_DELAY_MAX) {
6524
                set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_WORKING_DELAY);
6525
 
6526
                return 0;
6527
        }
6528
 
6529
        return 1;
6530
}
6531
 
6532
#else
6533
 
6534
//USER Write Levelling -- Super Quick Calibration
6535
alt_u32 rw_mgr_mem_calibrate_wlevel (alt_u32 g, alt_u32 test_bgn)
6536
{
6537
        alt_u32 d;
6538
        t_btfld bit_chk;
6539
 
6540
        TRACE_FUNC("%lu %lu", g, test_bgn);
6541
 
6542
        //USER The first call to this function will calibrate all groups
6543
        if (g != 0) {
6544
                return 1;
6545
        }
6546
 
6547
        //USER update info for sims
6548
 
6549
        reg_file_set_stage(CAL_STAGE_WLEVEL);
6550
        reg_file_set_sub_stage(CAL_SUBSTAGE_WORKING_DELAY);
6551
        reg_file_set_group(g);
6552
 
6553
        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX; d++) {
6554
                scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, d);
6555
 
6556
                if (rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
6557
                        break;
6558
                }
6559
        }
6560
 
6561
        if (d > IO_IO_OUT1_DELAY_MAX) {
6562
                set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_WORKING_DELAY);
6563
 
6564
                return 0;
6565
        }
6566
 
6567
        reg_file_set_sub_stage(CAL_SUBSTAGE_WLEVEL_COPY);
6568
 
6569
        //USER Now copy the calibration settings to all other groups
6570
        for (g = 1, test_bgn = RW_MGR_MEM_DQ_PER_WRITE_DQS; g < RW_MGR_MEM_IF_WRITE_DQS_WIDTH; g++, test_bgn += RW_MGR_MEM_DQ_PER_WRITE_DQS) {
6571
                scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, d);
6572
 
6573
                //USER Verify that things worked as expected
6574
                if (!rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
6575
                        set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_WLEVEL_COPY);
6576
 
6577
                        return 0;
6578
                }
6579
        }
6580
 
6581
        return 1;
6582
}
6583
 
6584
#endif
6585
#endif
6586
 
6587
#if DDRX
6588
#if !ENABLE_SUPER_QUICK_CALIBRATION
6589
 
6590
//USER Write Levelling -- Quick Calibration
6591
alt_u32 rw_mgr_mem_calibrate_wlevel (alt_u32 g, alt_u32 test_bgn)
6592
{
6593
        alt_u32 p;
6594
        t_btfld bit_chk;
6595
 
6596
        TRACE_FUNC("%lu %lu", g, test_bgn);
6597
 
6598
        //USER update info for sims 
6599
 
6600
        reg_file_set_stage(CAL_STAGE_WLEVEL);
6601
        reg_file_set_sub_stage(CAL_SUBSTAGE_WORKING_DELAY);
6602
 
6603
        //USER maximum phases for the sweep 
6604
 
6605
        //USER starting phases 
6606
 
6607
        //USER update info for sims
6608
 
6609
        reg_file_set_group(g);
6610
 
6611
        for (p = 0; p <= IO_DQDQS_OUT_PHASE_MAX; p++) {
6612
                scc_mgr_set_dqdqs_output_phase_all_ranks(g, p);
6613
 
6614
                if (rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
6615
                        break;
6616
                }
6617
        }
6618
 
6619
        if (p > IO_DQDQS_OUT_PHASE_MAX) {
6620
                set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_WORKING_DELAY);
6621
 
6622
                return 0;
6623
        }
6624
 
6625
        return 1;
6626
}
6627
 
6628
#else
6629
 
6630
//USER Write Levelling -- Super Quick Calibration
6631
alt_u32 rw_mgr_mem_calibrate_wlevel (alt_u32 g, alt_u32 test_bgn)
6632
{
6633
        alt_u32 p;
6634
        t_btfld bit_chk;
6635
 
6636
        TRACE_FUNC("%lu %lu", g, test_bgn);
6637
 
6638
        //USER The first call to this function will calibrate all groups
6639
        if (g != 0) {
6640
                return 1;
6641
        }
6642
 
6643
        //USER update info for sims 
6644
 
6645
        reg_file_set_stage(CAL_STAGE_WLEVEL);
6646
        reg_file_set_sub_stage(CAL_SUBSTAGE_WORKING_DELAY);
6647
 
6648
        //USER maximum phases for the sweep 
6649
 
6650
        //USER starting phases 
6651
 
6652
        //USER update info for sims
6653
 
6654
        reg_file_set_group(g);
6655
 
6656
        for (p = 0; p <= IO_DQDQS_OUT_PHASE_MAX; p++) {
6657
                scc_mgr_set_dqdqs_output_phase_all_ranks(g, p);
6658
 
6659
                if (rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
6660
                        break;
6661
                }
6662
        }
6663
 
6664
        if (p > IO_DQDQS_OUT_PHASE_MAX) {
6665
                set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_WORKING_DELAY);
6666
 
6667
                return 0;
6668
        }
6669
 
6670
        reg_file_set_sub_stage(CAL_SUBSTAGE_WLEVEL_COPY);
6671
 
6672
        //USER Now copy the calibration settings to all other groups
6673
        for (g = 1, test_bgn = RW_MGR_MEM_DQ_PER_READ_DQS; (g < RW_MGR_MEM_IF_READ_DQS_WIDTH); g++, test_bgn += RW_MGR_MEM_DQ_PER_READ_DQS) {
6674
                IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, g);
6675
                scc_mgr_set_dqdqs_output_phase_all_ranks(g, p);
6676
 
6677
                //USER Verify that things worked as expected
6678
                if (!rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
6679
                        set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_WLEVEL_COPY);
6680
 
6681
                        IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, 0);
6682
                        return 0;
6683
                }
6684
        }
6685
 
6686
        IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, 0);
6687
        return 1;
6688
}
6689
 
6690
#endif
6691
#endif
6692
 
6693
#endif
6694
 
6695
#if DYNAMIC_CALIBRATION_MODE || STATIC_FULL_CALIBRATION
6696
 
6697
#if QDRII 
6698
//USER Write Levelling -- Full Calibration
6699
alt_u32 rw_mgr_mem_calibrate_wlevel (alt_u32 g, alt_u32 test_bgn)
6700
{
6701
        TRACE_FUNC("%lu %lu", g, test_bgn);
6702
 
6703
        return 0;
6704
}
6705
#endif
6706
 
6707
#if RLDRAMX
6708
//USER Write Levelling -- Full Calibration
6709
alt_u32 rw_mgr_mem_calibrate_wlevel (alt_u32 g, alt_u32 test_bgn)
6710
{
6711
        alt_u32 d;
6712
        t_btfld bit_chk;
6713
        alt_u32 work_bgn, work_end;
6714
        alt_u32 d_bgn, d_end;
6715
        alt_u32 found_begin;
6716
 
6717
        TRACE_FUNC("%lu %lu", g, test_bgn);
6718
        BFM_STAGE("wlevel");
6719
 
6720
        ALTERA_ASSERT(g < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
6721
 
6722
        //USER update info for sims
6723
 
6724
        reg_file_set_stage(CAL_STAGE_WLEVEL);
6725
        reg_file_set_sub_stage(CAL_SUBSTAGE_WORKING_DELAY);
6726
 
6727
        //USER maximum delays for the sweep 
6728
 
6729
        //USER update info for sims
6730
 
6731
        reg_file_set_group(g);
6732
 
6733
        //USER starting and end range where writes work
6734
 
6735
        scc_mgr_spread_out2_delay_all_ranks (g,test_bgn);
6736
 
6737
        work_bgn = 0;
6738
        work_end = 0;
6739
 
6740
        //USER step 1: find first working dtap, increment in dtaps
6741
        found_begin = 0;
6742
        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX; d++, work_bgn += IO_DELAY_PER_DCHAIN_TAP) {
6743
                DPRINT(2, "wlevel: begin: d=%lu", d);
6744
                scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, d);
6745
 
6746
                if (rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
6747
                        found_begin = 1;
6748
                        d_bgn = d;
6749
                        break;
6750
                } else {
6751
                        recover_mem_device_after_ck_dqs_violation();
6752
                }
6753
        }
6754
 
6755
        if (!found_begin) {
6756
                //USER fail, cannot find first working delay
6757
 
6758
                DPRINT(2, "wlevel: failed to find first working delay", d);
6759
 
6760
                set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_WORKING_DELAY);
6761
 
6762
                return 0;
6763
        }
6764
 
6765
        DPRINT(2, "wlevel: found begin d=%lu work_bgn=%lu", d_bgn, work_bgn);
6766
        BFM_GBL_SET(dqs_wlevel_left_edge[g].d,d_bgn);
6767
        BFM_GBL_SET(dqs_wlevel_left_edge[g].ps,work_bgn);
6768
 
6769
        reg_file_set_sub_stage(CAL_SUBSTAGE_LAST_WORKING_DELAY);
6770
 
6771
        //USER step 2 : find first non-working dtap, increment in dtaps
6772
        work_end = work_bgn;
6773
        d = d + 1;
6774
        for (; d <= IO_IO_OUT1_DELAY_MAX; d++, work_end += IO_DELAY_PER_DCHAIN_TAP) {
6775
                DPRINT(2, "wlevel: end: d=%lu", d);
6776
                scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, d);
6777
 
6778
                if (!rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
6779
                        recover_mem_device_after_ck_dqs_violation();
6780
                        break;
6781
                }
6782
        }
6783
        d_end = d - 1;
6784
 
6785
        if (d_end >= d_bgn) {
6786
                //USER we have a working range 
6787
        } else {
6788
                //USER nil range
6789
                //Note: don't think this is possible
6790
 
6791
                set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_LAST_WORKING_DELAY);
6792
 
6793
                return 0;
6794
        }
6795
 
6796
        DPRINT(2, "wlevel: found end: d=%lu work_end=%lu", d_end, work_end);
6797
        BFM_GBL_SET(dqs_wlevel_right_edge[g].d,d_end);
6798
        BFM_GBL_SET(dqs_wlevel_right_edge[g].ps,work_end);
6799
 
6800
        TCLRPT_SET(debug_cal_report->cal_dqs_out_margins[curr_shadow_reg][g].dqdqs_start, work_bgn);
6801
        TCLRPT_SET(debug_cal_report->cal_dqs_out_margins[curr_shadow_reg][g].dqdqs_end, work_end);
6802
 
6803
 
6804
        //USER center 
6805
 
6806
        d = (d_end + d_bgn) / 2;
6807
 
6808
        DPRINT(2, "wlevel: found middle: d=%lu work_mid=%lu", d, (work_end + work_bgn)/2);
6809
        BFM_GBL_SET(dqs_wlevel_mid[g].d,d);
6810
        BFM_GBL_SET(dqs_wlevel_mid[g].ps,(work_end + work_bgn)/2);
6811
 
6812
        scc_mgr_zero_group (g, test_bgn, 1);
6813
        scc_mgr_apply_group_all_out_delay_add_all_ranks (g, test_bgn, d);
6814
 
6815
        return 1;
6816
}
6817
#endif
6818
 
6819
 
6820
#if DDRX
6821
#if NEWVERSION_WL
6822
 
6823
//USER Write Levelling -- Full Calibration
6824
alt_u32 rw_mgr_mem_calibrate_wlevel (alt_u32 g, alt_u32 test_bgn)
6825
{
6826
        alt_u32 p, d, sr;
6827
 
6828
#if CALIBRATE_BIT_SLIPS
6829
#if QUARTER_RATE_MODE   
6830
        alt_32 num_additional_fr_cycles = 3;
6831
#elif HALF_RATE_MODE    
6832
        alt_32 num_additional_fr_cycles = 1;
6833
#else
6834
        alt_32 num_additional_fr_cycles = 0;
6835
#endif
6836
#if MULTIPLE_AFI_WLAT
6837
        num_additional_fr_cycles++;
6838
#endif
6839
#else   
6840
        alt_u32 num_additional_fr_cycles = 0;
6841
#endif
6842
 
6843
        t_btfld bit_chk;
6844
        alt_u32 work_bgn, work_end, work_mid;
6845
        alt_u32 tmp_delay;
6846
        alt_u32 found_begin;
6847
        alt_u32 dtaps_per_ptap;
6848
 
6849
        TRACE_FUNC("%lu %lu", g, test_bgn);
6850
        BFM_STAGE("wlevel");
6851
 
6852
 
6853
        //USER update info for sims
6854
 
6855
        reg_file_set_stage(CAL_STAGE_WLEVEL);
6856
        reg_file_set_sub_stage(CAL_SUBSTAGE_WORKING_DELAY);
6857
 
6858
        //USER maximum phases for the sweep 
6859
 
6860
#if USE_DQS_TRACKING
6861
#if HHP_HPS
6862
        dtaps_per_ptap = IORD_32DIRECT(REG_FILE_DTAPS_PER_PTAP, 0);
6863
#else
6864
        dtaps_per_ptap = IORD_32DIRECT(TRK_DTAPS_PER_PTAP, 0);
6865
#endif
6866
#else
6867
        dtaps_per_ptap = 0;
6868
        tmp_delay = 0;
6869
        while (tmp_delay < IO_DELAY_PER_OPA_TAP) {
6870
                dtaps_per_ptap++;
6871
                tmp_delay += IO_DELAY_PER_DCHAIN_TAP;
6872
        }
6873
        dtaps_per_ptap--;
6874
        tmp_delay = 0;
6875
#endif
6876
 
6877
        //USER starting phases 
6878
 
6879
        //USER update info for sims
6880
 
6881
        reg_file_set_group(g);
6882
 
6883
        //USER starting and end range where writes work 
6884
 
6885
        scc_mgr_spread_out2_delay_all_ranks (g,test_bgn);
6886
 
6887
        work_bgn = 0;
6888
        work_end = 0;
6889
 
6890
        //USER step 1: find first working phase, increment in ptaps, and then in dtaps if ptaps doesn't find a working phase 
6891
        found_begin = 0;
6892
        tmp_delay = 0;
6893
        for (d = 0; d <= dtaps_per_ptap; d++, tmp_delay += IO_DELAY_PER_DCHAIN_TAP) {
6894
                scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, d);
6895
 
6896
                work_bgn = tmp_delay;
6897
 
6898
                for (p = 0; p <= IO_DQDQS_OUT_PHASE_MAX + num_additional_fr_cycles*IO_DLL_CHAIN_LENGTH; p++, work_bgn += IO_DELAY_PER_OPA_TAP) {
6899
                        DPRINT(2, "wlevel: begin-1: p=%lu d=%lu", p, d);
6900
                        scc_mgr_set_dqdqs_output_phase_all_ranks(g, p);
6901
 
6902
                        if (rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
6903
                                found_begin = 1;
6904
                                break;
6905
                        }
6906
                }
6907
 
6908
                if (found_begin) {
6909
                        break;
6910
                }
6911
        }
6912
 
6913
        if (p > IO_DQDQS_OUT_PHASE_MAX + num_additional_fr_cycles*IO_DLL_CHAIN_LENGTH) {
6914
                //USER fail, cannot find first working phase 
6915
 
6916
                set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_WORKING_DELAY);
6917
 
6918
                return 0;
6919
        }
6920
 
6921
        DPRINT(2, "wlevel: first valid p=%lu d=%lu", p, d);
6922
 
6923
        reg_file_set_sub_stage(CAL_SUBSTAGE_LAST_WORKING_DELAY);
6924
 
6925
        //USER If d is 0 then the working window covers a phase tap and we can follow the old procedure
6926
        //USER  otherwise, we've found the beginning, and we need to increment the dtaps until we find the end 
6927
        if (d == 0) {
6928
                COV(WLEVEL_PHASE_PTAP_OVERLAP);
6929
                work_end = work_bgn + IO_DELAY_PER_OPA_TAP;
6930
 
6931
                //USER step 2: if we have room, back off by one and increment in dtaps 
6932
 
6933
                if (p > 0) {
6934
#ifdef BFM_MODE
6935
                        int found = 0;
6936
#endif
6937
                        scc_mgr_set_dqdqs_output_phase_all_ranks(g, p - 1);
6938
 
6939
                        tmp_delay = work_bgn - IO_DELAY_PER_OPA_TAP;
6940
 
6941
                        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX && tmp_delay < work_bgn; d++, tmp_delay += IO_DELAY_PER_DCHAIN_TAP) {
6942
                                DPRINT(2, "wlevel: begin-2: p=%lu d=%lu", (p-1), d);
6943
                                scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, d);
6944
 
6945
                                if (rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
6946
#ifdef BFM_MODE
6947
                                        found = 1;
6948
#endif
6949
                                        work_bgn = tmp_delay;
6950
                                        break;
6951
                                }
6952
                        }
6953
 
6954
#ifdef BFM_MODE
6955
                        {
6956
                                alt_u32 d2;
6957
                                alt_u32 p2;
6958
                                if (found) {
6959
                                        d2 = d;
6960
                                        p2 = p - 1;
6961
                                } else {
6962
                                        d2 = 0;
6963
                                        p2 = p;
6964
                                }
6965
 
6966
                                DPRINT(2, "wlevel: found begin-A: p=%lu d=%lu ps=%lu", p2, d2, work_bgn);
6967
 
6968
                                BFM_GBL_SET(dqs_wlevel_left_edge[g].p,p2);
6969
                                BFM_GBL_SET(dqs_wlevel_left_edge[g].d,d2);
6970
                                BFM_GBL_SET(dqs_wlevel_left_edge[g].ps,work_bgn);
6971
                        }
6972
#endif
6973
 
6974
                        scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, 0);
6975
                } else {
6976
                        DPRINT(2, "wlevel: found begin-B: p=%lu d=%lu ps=%lu", p, d, work_bgn);
6977
 
6978
                        BFM_GBL_SET(dqs_wlevel_left_edge[g].p,p);
6979
                        BFM_GBL_SET(dqs_wlevel_left_edge[g].d,d);
6980
                        BFM_GBL_SET(dqs_wlevel_left_edge[g].ps,work_bgn);
6981
                }
6982
 
6983
                //USER step 3: go forward from working phase to non working phase, increment in ptaps 
6984
 
6985
                for (p = p + 1; p <= IO_DQDQS_OUT_PHASE_MAX + num_additional_fr_cycles*IO_DLL_CHAIN_LENGTH; p++, work_end += IO_DELAY_PER_OPA_TAP) {
6986
                        DPRINT(2, "wlevel: end-0: p=%lu d=%lu", p, (long unsigned int)0);
6987
                        scc_mgr_set_dqdqs_output_phase_all_ranks(g, p);
6988
 
6989
                        if (!rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
6990
                                break;
6991
                        }
6992
                }
6993
 
6994
                //USER step 4: back off one from last, increment in dtaps 
6995
                //USER The actual increment is done outside the if/else statement since it is shared with other code
6996
 
6997
                p = p - 1;
6998
 
6999
                scc_mgr_set_dqdqs_output_phase_all_ranks(g, p);
7000
 
7001
                work_end -= IO_DELAY_PER_OPA_TAP;
7002
                d = 0;
7003
 
7004
        } else {
7005
                //USER step 5: Window doesn't cover phase tap, just increment dtaps until failure
7006
                //USER The actual increment is done outside the if/else statement since it is shared with other code
7007
                COV(WLEVEL_PHASE_PTAP_NO_OVERLAP);
7008
                work_end = work_bgn;
7009
                DPRINT(2, "wlevel: found begin-C: p=%lu d=%lu ps=%lu", p, d, work_bgn);
7010
                BFM_GBL_SET(dqs_wlevel_left_edge[g].p,p);
7011
                BFM_GBL_SET(dqs_wlevel_left_edge[g].d,d);
7012
                BFM_GBL_SET(dqs_wlevel_left_edge[g].ps,work_bgn);
7013
 
7014
        }
7015
 
7016
        //USER The actual increment until failure
7017
        for (; d <= IO_IO_OUT1_DELAY_MAX; d++, work_end += IO_DELAY_PER_DCHAIN_TAP) {
7018
                DPRINT(2, "wlevel: end: p=%lu d=%lu", p, d);
7019
                scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, d);
7020
 
7021
                if (!rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
7022
                        break;
7023
                }
7024
        }
7025
        scc_mgr_zero_group (g, test_bgn, 1);
7026
 
7027
        work_end -= IO_DELAY_PER_DCHAIN_TAP;
7028
 
7029
        if (work_end >= work_bgn) {
7030
                //USER we have a working range 
7031
        } else {
7032
                //USER nil range 
7033
 
7034
                set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_LAST_WORKING_DELAY);
7035
 
7036
                return 0;
7037
        }
7038
 
7039
        DPRINT(2, "wlevel: found end: p=%lu d=%lu; range: [%lu,%lu]", p, d-1, work_bgn, work_end);
7040
        BFM_GBL_SET(dqs_wlevel_right_edge[g].p,p);
7041
        BFM_GBL_SET(dqs_wlevel_right_edge[g].d,d-1);
7042
        BFM_GBL_SET(dqs_wlevel_right_edge[g].ps,work_end);
7043
 
7044
        for(sr = 0; sr < NUM_SHADOW_REGS; sr++) {
7045
                TCLRPT_SET(debug_cal_report->cal_dqs_out_margins[sr][g].dqdqs_start, work_bgn);
7046
                TCLRPT_SET(debug_cal_report->cal_dqs_out_margins[sr][g].dqdqs_end, work_end);
7047
        }
7048
 
7049
        //USER center 
7050
 
7051
        work_mid = (work_bgn + work_end) / 2;
7052
 
7053
        DPRINT(2, "wlevel: work_mid=%ld", work_mid);
7054
 
7055
        tmp_delay = 0;
7056
 
7057
        for (p = 0; p <= IO_DQDQS_OUT_PHASE_MAX  + num_additional_fr_cycles*IO_DLL_CHAIN_LENGTH && tmp_delay < work_mid; p++, tmp_delay += IO_DELAY_PER_OPA_TAP);
7058
 
7059
        if (tmp_delay > work_mid) {
7060
                tmp_delay -= IO_DELAY_PER_OPA_TAP;
7061
                p--;
7062
        }
7063
 
7064
        while (p > IO_DQDQS_OUT_PHASE_MAX) {
7065
                tmp_delay -= IO_DELAY_PER_OPA_TAP;
7066
                p--;
7067
        }
7068
 
7069
        scc_mgr_set_dqdqs_output_phase_all_ranks(g, p);
7070
 
7071
        DPRINT(2, "wlevel: p=%lu tmp_delay=%lu left=%lu", p, tmp_delay, work_mid - tmp_delay);
7072
 
7073
        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX && tmp_delay < work_mid; d++, tmp_delay += IO_DELAY_PER_DCHAIN_TAP);
7074
 
7075
        if (tmp_delay > work_mid) {
7076
                tmp_delay -= IO_DELAY_PER_DCHAIN_TAP;
7077
                d--;
7078
        }
7079
 
7080
        DPRINT(2, "wlevel: p=%lu d=%lu tmp_delay=%lu left=%lu", p, d, tmp_delay, work_mid - tmp_delay);
7081
 
7082
        scc_mgr_apply_group_all_out_delay_add_all_ranks (g, test_bgn, d);
7083
 
7084
        DPRINT(2, "wlevel: found middle: p=%lu d=%lu", p, d);
7085
        BFM_GBL_SET(dqs_wlevel_mid[g].p,p);
7086
        BFM_GBL_SET(dqs_wlevel_mid[g].d,d);
7087
        BFM_GBL_SET(dqs_wlevel_mid[g].ps,work_mid);
7088
 
7089
        return 1;
7090
}
7091
 
7092
 
7093
#else
7094
 
7095
//USER Write Levelling -- Full Calibration
7096
alt_u32 rw_mgr_mem_calibrate_wlevel (alt_u32 g, alt_u32 test_bgn)
7097
{
7098
        alt_u32 p, d;
7099
        t_btfld bit_chk;
7100
        alt_u32 work_bgn, work_end, work_mid;
7101
        alt_u32 tmp_delay;
7102
 
7103
        TRACE_FUNC("%lu %lu", g, test_bgn);
7104
 
7105
        //USER update info for sims
7106
 
7107
        reg_file_set_stage(CAL_STAGE_WLEVEL);
7108
        reg_file_set_sub_stage(CAL_SUBSTAGE_WORKING_DELAY);
7109
 
7110
        //USER maximum phases for the sweep 
7111
 
7112
        //USER starting phases 
7113
 
7114
        //USER update info for sims
7115
 
7116
        reg_file_set_group(g);
7117
 
7118
        //USER starting and end range where writes work 
7119
 
7120
        work_bgn = 0;
7121
        work_end = 0;
7122
 
7123
        //USER step 1: find first working phase, increment in ptaps 
7124
 
7125
        for (p = 0; p <= IO_DQDQS_OUT_PHASE_MAX; p++, work_bgn += IO_DELAY_PER_OPA_TAP) {
7126
                scc_mgr_set_dqdqs_output_phase_all_ranks(g, p);
7127
 
7128
                if (rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
7129
                        break;
7130
                }
7131
        }
7132
 
7133
        if (p > IO_DQDQS_OUT_PHASE_MAX) {
7134
                //USER fail, cannot find first working phase 
7135
 
7136
                set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_WORKING_DELAY);
7137
 
7138
                return 0;
7139
        }
7140
 
7141
        work_end = work_bgn + IO_DELAY_PER_OPA_TAP;
7142
 
7143
        reg_file_set_sub_stage(CAL_SUBSTAGE_LAST_WORKING_DELAY);
7144
 
7145
        //USER step 2: if we have room, back off by one and increment in dtaps 
7146
 
7147
        if (p > 0) {
7148
                scc_mgr_set_dqdqs_output_phase_all_ranks(g, p - 1);
7149
 
7150
                tmp_delay = work_bgn - IO_DELAY_PER_OPA_TAP;
7151
 
7152
                for (d = 0; d <= IO_IO_OUT1_DELAY_MAX && tmp_delay < work_bgn; d++, tmp_delay += IO_DELAY_PER_DCHAIN_TAP) {
7153
                        scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, d);
7154
 
7155
                        if (rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
7156
                                work_bgn = tmp_delay;
7157
                                break;
7158
                        }
7159
                }
7160
 
7161
                scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, 0);
7162
        }
7163
 
7164
        //USER step 3: go forward from working phase to non working phase, increment in ptaps 
7165
 
7166
        for (p = p + 1; p <= IO_DQDQS_OUT_PHASE_MAX; p++, work_end += IO_DELAY_PER_OPA_TAP) {
7167
                scc_mgr_set_dqdqs_output_phase_all_ranks(g, p);
7168
 
7169
                if (!rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
7170
                        break;
7171
                }
7172
        }
7173
 
7174
        //USER step 4: back off one from last, increment in dtaps 
7175
 
7176
        scc_mgr_set_dqdqs_output_phase_all_ranks(g, p - 1);
7177
 
7178
        work_end -= IO_DELAY_PER_OPA_TAP;
7179
 
7180
        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX; d++, work_end += IO_DELAY_PER_DCHAIN_TAP) {
7181
                scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, d);
7182
 
7183
                if (!rw_mgr_mem_calibrate_write_test_all_ranks (g, 0, PASS_ONE_BIT, &bit_chk)) {
7184
                        break;
7185
                }
7186
        }
7187
 
7188
        scc_mgr_apply_group_all_out_delay_all_ranks (g, test_bgn, 0);
7189
 
7190
        if (work_end > work_bgn) {
7191
                //USER we have a working range 
7192
        } else {
7193
                //USER nil range 
7194
 
7195
                set_failing_group_stage(g, CAL_STAGE_WLEVEL, CAL_SUBSTAGE_LAST_WORKING_DELAY);
7196
 
7197
                return 0;
7198
        }
7199
 
7200
        //USER center 
7201
 
7202
        work_mid = (work_bgn + work_end) / 2;
7203
 
7204
        tmp_delay = 0;
7205
 
7206
        for (p = 0; p <= IO_DQDQS_OUT_PHASE_MAX && tmp_delay < work_mid; p++, tmp_delay += IO_DELAY_PER_OPA_TAP);
7207
 
7208
        tmp_delay -= IO_DELAY_PER_OPA_TAP;
7209
 
7210
        scc_mgr_set_dqdqs_output_phase_all_ranks(g, p - 1);
7211
 
7212
        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX && tmp_delay < work_mid; d++, tmp_delay += IO_DELAY_PER_DCHAIN_TAP);
7213
 
7214
        scc_mgr_apply_group_all_out_delay_add_all_ranks (g, test_bgn, d - 1);
7215
 
7216
 
7217
        return 1;
7218
}
7219
 
7220
#endif
7221
#endif
7222
#endif
7223
 
7224
//USER center all windows. do per-bit-deskew to possibly increase size of certain windows
7225
 
7226
#if NEWVERSION_WRDESKEW
7227
 
7228
alt_u32 rw_mgr_mem_calibrate_writes_center (alt_u32 rank_bgn, alt_u32 write_group, alt_u32 test_bgn)
7229
{
7230
        alt_u32 i, p, min_index;
7231
        alt_32 d;
7232
        //USER Store these as signed since there are comparisons with signed numbers
7233
        t_btfld bit_chk;
7234
#if QDRII
7235
        t_btfld tmp_bit_chk;
7236
        t_btfld tmp_mask;
7237
        t_btfld mask;
7238
#endif
7239
        t_btfld sticky_bit_chk;
7240
        alt_32 left_edge[RW_MGR_MEM_DQ_PER_WRITE_DQS];
7241
        alt_32 right_edge[RW_MGR_MEM_DQ_PER_WRITE_DQS];
7242
        alt_32 mid;
7243
        alt_32 mid_min, orig_mid_min;
7244
        alt_32 new_dqs, start_dqs, shift_dq;
7245
#if RUNTIME_CAL_REPORT  
7246
        alt_32 new_dq[RW_MGR_MEM_DQ_PER_WRITE_DQS];
7247
#endif
7248
        alt_32 dq_margin, dqs_margin, dm_margin;
7249
        alt_u32 stop;
7250
 
7251
        TRACE_FUNC("%lu %lu", write_group, test_bgn);
7252
        BFM_STAGE("writes_center");
7253
 
7254
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
7255
 
7256
        dm_margin = 0;
7257
 
7258
        start_dqs = READ_SCC_DQS_IO_OUT1_DELAY();
7259
 
7260
        select_curr_shadow_reg_using_rank(rank_bgn);
7261
 
7262
        //USER per-bit deskew 
7263
 
7264
        //USER set the left and right edge of each bit to an illegal value 
7265
        //USER use (IO_IO_OUT1_DELAY_MAX + 1) as an illegal value
7266
        sticky_bit_chk = 0;
7267
        for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
7268
                left_edge[i]  = IO_IO_OUT1_DELAY_MAX + 1;
7269
                right_edge[i] = IO_IO_OUT1_DELAY_MAX + 1;
7270
        }
7271
 
7272
        //USER Search for the left edge of the window for each bit
7273
        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX; d++) {
7274
                scc_mgr_apply_group_dq_out1_delay (write_group, test_bgn, d);
7275
 
7276
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7277
 
7278
                //USER Stop searching when the read test doesn't pass AND when we've seen a passing read on every bit 
7279
                stop = !rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 0, PASS_ONE_BIT, &bit_chk, 0);
7280
                sticky_bit_chk = sticky_bit_chk | bit_chk;
7281
                stop = stop && (sticky_bit_chk == param->write_correct_mask);
7282
                DPRINT(2, "write_center(left): dtap=%lu => " BTFLD_FMT " == " BTFLD_FMT " && %lu [bit_chk=" BTFLD_FMT "]",
7283
                       d, sticky_bit_chk, param->write_correct_mask, stop, bit_chk);
7284
 
7285
                if (stop == 1) {
7286
                        break;
7287
                } else {
7288
                        for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
7289
                                if (bit_chk & 1) {
7290
                                        //USER Remember a passing test as the left_edge
7291
                                        left_edge[i] = d;
7292
                                } else {
7293
                                        //USER If a left edge has not been seen yet, then a future passing test will mark this edge as the right edge 
7294
                                        if (left_edge[i] == IO_IO_OUT1_DELAY_MAX + 1) {
7295
                                                right_edge[i] = -(d + 1);
7296
                                        }
7297
                                }
7298
                                DPRINT(2, "write_center[l,d=%lu): bit_chk_test=%d left_edge[%lu]: %ld right_edge[%lu]: %ld",
7299
                                       d, (int)(bit_chk & 1), i, left_edge[i], i, right_edge[i]);
7300
                                bit_chk = bit_chk >> 1;
7301
                        }
7302
                }
7303
        }
7304
 
7305
        //USER Reset DQ delay chains to 0 
7306
        scc_mgr_apply_group_dq_out1_delay (write_group, test_bgn, 0);
7307
        sticky_bit_chk = 0;
7308
        for (i = RW_MGR_MEM_DQ_PER_WRITE_DQS - 1;; i--) {
7309
 
7310
                DPRINT(2, "write_center: left_edge[%lu]: %ld right_edge[%lu]: %ld", i, left_edge[i], i, right_edge[i]);
7311
 
7312
                //USER Check for cases where we haven't found the left edge, which makes our assignment of the the 
7313
                //USER right edge invalid.  Reset it to the illegal value. 
7314
                if ((left_edge[i] == IO_IO_OUT1_DELAY_MAX + 1) && (right_edge[i] != IO_IO_OUT1_DELAY_MAX + 1)) {
7315
                        right_edge[i] = IO_IO_OUT1_DELAY_MAX + 1;
7316
                        DPRINT(2, "write_center: reset right_edge[%lu]: %ld", i, right_edge[i]);
7317
                }
7318
 
7319
                //USER Reset sticky bit (except for bits where we have seen the left edge) 
7320
                sticky_bit_chk = sticky_bit_chk << 1;
7321
                if ((left_edge[i] != IO_IO_OUT1_DELAY_MAX + 1)) {
7322
                        sticky_bit_chk = sticky_bit_chk | 1;
7323
                }
7324
 
7325
                if (i == 0)
7326
                {
7327
                        break;
7328
                }
7329
        }
7330
 
7331
        //USER Search for the right edge of the window for each bit 
7332
        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX - start_dqs; d++) {
7333
                scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, d + start_dqs);
7334
 
7335
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7336
                if (QDRII)
7337
                {
7338
                        rw_mgr_mem_dll_lock_wait();
7339
                }
7340
 
7341
                //USER Stop searching when the read test doesn't pass AND when we've seen a passing read on every bit 
7342
                stop = !rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 0, PASS_ONE_BIT, &bit_chk, 0);
7343
                if (stop) {
7344
                        recover_mem_device_after_ck_dqs_violation();
7345
                }
7346
                sticky_bit_chk = sticky_bit_chk | bit_chk;
7347
                stop = stop && (sticky_bit_chk == param->write_correct_mask);
7348
 
7349
                DPRINT(2, "write_center (right): dtap=%lu => " BTFLD_FMT " == " BTFLD_FMT " && %lu", d, sticky_bit_chk, param->write_correct_mask, stop);
7350
 
7351
                if (stop == 1) {
7352
                        if (d == 0) {
7353
                                for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
7354
                                        //USER d = 0 failed, but it passed when testing the left edge, so it must be marginal, set it to -1
7355
                                        if (right_edge[i] == IO_IO_OUT1_DELAY_MAX + 1 && left_edge[i] != IO_IO_OUT1_DELAY_MAX + 1) {
7356
                                                right_edge[i] = -1;
7357
                                        }
7358
                                }
7359
                        }
7360
                        break;
7361
                } else {
7362
                        for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
7363
                                if (bit_chk & 1) {
7364
                                        //USER Remember a passing test as the right_edge 
7365
                                        right_edge[i] = d;
7366
                                } else {
7367
                                        if (d != 0) {
7368
                                                //USER If a right edge has not been seen yet, then a future passing test will mark this edge as the left edge 
7369
                                                if (right_edge[i] == IO_IO_OUT1_DELAY_MAX + 1) {
7370
                                                        left_edge[i] = -(d + 1);
7371
                                                }
7372
                                        } else {
7373
                                                //USER d = 0 failed, but it passed when testing the left edge, so it must be marginal, set it to -1
7374
                                                if (right_edge[i] == IO_IO_OUT1_DELAY_MAX + 1 && left_edge[i] != IO_IO_OUT1_DELAY_MAX + 1) {
7375
                                                        right_edge[i] = -1;
7376
                                                }
7377
                                                //USER If a right edge has not been seen yet, then a future passing test will mark this edge as the left edge 
7378
                                                else if (right_edge[i] == IO_IO_OUT1_DELAY_MAX + 1) {
7379
                                                        left_edge[i] = -(d + 1);
7380
                                                }
7381
                                        }
7382
                                }
7383
                                DPRINT(2, "write_center[r,d=%lu): bit_chk_test=%d left_edge[%lu]: %ld right_edge[%lu]: %ld",
7384
                                       d, (int)(bit_chk & 1), i, left_edge[i], i, right_edge[i]);
7385
                                bit_chk = bit_chk >> 1;
7386
                        }
7387
                }
7388
        }
7389
 
7390
#if ENABLE_TCL_DEBUG
7391
        // Store all observed margins
7392
        for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
7393
                alt_u32 dq = write_group*RW_MGR_MEM_DQ_PER_WRITE_DQS + i;
7394
 
7395
                ALTERA_ASSERT(dq < RW_MGR_MEM_DATA_WIDTH);
7396
 
7397
                TCLRPT_SET(debug_cal_report->cal_dq_out_margins[curr_shadow_reg][dq].left_edge, left_edge[i]);
7398
                TCLRPT_SET(debug_cal_report->cal_dq_out_margins[curr_shadow_reg][dq].right_edge, right_edge[i]);
7399
        }
7400
#endif
7401
 
7402
        //USER Check that all bits have a window
7403
        for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
7404
                DPRINT(2, "write_center: left_edge[%lu]: %ld right_edge[%lu]: %ld", i, left_edge[i], i, right_edge[i]);
7405
                BFM_GBL_SET(dq_write_left_edge[write_group][i],left_edge[i]);
7406
                BFM_GBL_SET(dq_write_right_edge[write_group][i],right_edge[i]);
7407
                if ((left_edge[i] == IO_IO_OUT1_DELAY_MAX + 1) || (right_edge[i] == IO_IO_OUT1_DELAY_MAX + 1)) {
7408
                        set_failing_group_stage(test_bgn + i, CAL_STAGE_WRITES, CAL_SUBSTAGE_WRITES_CENTER);
7409
                        return 0;
7410
                }
7411
        }
7412
 
7413
        //USER Find middle of window for each DQ bit 
7414
        mid_min = left_edge[0] - right_edge[0];
7415
        min_index = 0;
7416
        for (i = 1; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
7417
                mid = left_edge[i] - right_edge[i];
7418
                if (mid < mid_min) {
7419
                        mid_min = mid;
7420
                        min_index = i;
7421
                }
7422
        }
7423
 
7424
        //USER  -mid_min/2 represents the amount that we need to move DQS.  If mid_min is odd and positive we'll need to add one to
7425
        //USER make sure the rounding in further calculations is correct (always bias to the right), so just add 1 for all positive values
7426
        if (mid_min > 0) {
7427
                mid_min++;
7428
        }
7429
        mid_min = mid_min / 2;
7430
 
7431
        DPRINT(1, "write_center: mid_min=%ld", mid_min);
7432
 
7433
        //USER Determine the amount we can change DQS (which is -mid_min)
7434
        orig_mid_min = mid_min;
7435
#if ENABLE_DQS_OUT_CENTERING
7436
        if (DDRX || RLDRAMX) {
7437
                new_dqs = start_dqs - mid_min;
7438
                DPRINT(2, "write_center: new_dqs(1)=%ld", new_dqs);
7439
                if (new_dqs > IO_IO_OUT1_DELAY_MAX) {
7440
                        new_dqs = IO_IO_OUT1_DELAY_MAX;
7441
                } else if (new_dqs < 0) {
7442
                        new_dqs = 0;
7443
                }
7444
                mid_min = start_dqs - new_dqs;
7445
 
7446
                new_dqs = start_dqs - mid_min;
7447
        } else {
7448
                new_dqs = start_dqs;
7449
                mid_min = 0;
7450
        }
7451
#else
7452
        new_dqs = start_dqs;
7453
        mid_min = 0;
7454
#endif
7455
 
7456
        DPRINT(1, "write_center: start_dqs=%ld new_dqs=%ld mid_min=%ld", start_dqs, new_dqs, mid_min);
7457
 
7458
        //USER Initialize data for export structures 
7459
        dqs_margin = IO_IO_OUT1_DELAY_MAX + 1;
7460
        dq_margin  = IO_IO_OUT1_DELAY_MAX + 1;
7461
 
7462
        //USER add delay to bring centre of all DQ windows to the same "level" 
7463
        for (i = 0, p = test_bgn; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++, p++) {
7464
                //USER Use values before divide by 2 to reduce round off error 
7465
                shift_dq = (left_edge[i] - right_edge[i] - (left_edge[min_index] - right_edge[min_index]))/2  + (orig_mid_min - mid_min);
7466
 
7467
                DPRINT(2, "write_center: before: shift_dq[%lu]=%ld", i, shift_dq);
7468
 
7469
                if (shift_dq + (alt_32)READ_SCC_DQ_OUT1_DELAY(i) > (alt_32)IO_IO_OUT1_DELAY_MAX) {
7470
                        shift_dq = (alt_32)IO_IO_OUT1_DELAY_MAX - READ_SCC_DQ_OUT1_DELAY(i);
7471
                } else if (shift_dq + (alt_32)READ_SCC_DQ_OUT1_DELAY(i) < 0) {
7472
                        shift_dq = -(alt_32)READ_SCC_DQ_OUT1_DELAY(i);
7473
                }
7474
#if RUNTIME_CAL_REPORT
7475
                new_dq[i] = shift_dq;
7476
#endif
7477
                DPRINT(2, "write_center: after: shift_dq[%lu]=%ld", i, shift_dq);
7478
                scc_mgr_set_dq_out1_delay(write_group, i, READ_SCC_DQ_OUT1_DELAY(i) + shift_dq);
7479
                scc_mgr_load_dq (i);
7480
 
7481
                DPRINT(2, "write_center: margin[%lu]=[%ld,%ld]", i,
7482
                       left_edge[i] - shift_dq + (-mid_min),
7483
                       right_edge[i] + shift_dq - (-mid_min));
7484
                //USER To determine values for export structures 
7485
                if (left_edge[i] - shift_dq + (-mid_min) < dq_margin) {
7486
                        dq_margin = left_edge[i] - shift_dq + (-mid_min);
7487
                }
7488
                if (right_edge[i] + shift_dq - (-mid_min) < dqs_margin) {
7489
                        dqs_margin = right_edge[i] + shift_dq - (-mid_min);
7490
                }
7491
        }
7492
 
7493
        //USER Move DQS 
7494
        if (QDRII) {
7495
                scc_mgr_set_group_dqs_io_and_oct_out1_gradual (write_group, new_dqs);
7496
        } else {
7497
                scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, new_dqs);
7498
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7499
        }
7500
 
7501
#if RUNTIME_CAL_REPORT
7502
        for (i = 0, p = test_bgn; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++, p++) {
7503
                RPRINT("Write Deskew ; DQ %2lu ; Rank %lu ; Left edge %3li ; Right edge %3li ; DQ delay %2li ; DQS delay %2li", write_group*RW_MGR_MEM_DQ_PER_WRITE_DQS + i, rank_bgn, left_edge[i], right_edge[i], new_dq[i], new_dqs);
7504
        }
7505
#endif
7506
 
7507
 
7508
        //////////////////////
7509
        //////////////////////
7510
        //USER Centre DM 
7511
        //////////////////////
7512
        //////////////////////
7513
 
7514
        BFM_STAGE("dm_center");
7515
 
7516
        DPRINT(2, "write_center: DM");
7517
 
7518
#if RLDRAMX
7519
 
7520
        //Note: this is essentially the same as DDR with the exception of the dm_ global accounting
7521
 
7522
        //USER Determine if first group in device to initialize left and right edges
7523
        if (!is_write_group_enabled_for_dm(write_group))
7524
        {
7525
                DPRINT(2, "dm_calib: skipping since not last in group");
7526
        }
7527
        else
7528
        {
7529
 
7530
                // last in the group, so we need to do DM
7531
                DPRINT(2, "dm_calib: calibrating DM since last in group");
7532
 
7533
                //USER set the left and right edge of each bit to an illegal value 
7534
                //USER use (IO_IO_OUT1_DELAY_MAX + 1) as an illegal value
7535
                left_edge[0]  = IO_IO_OUT1_DELAY_MAX + 1;
7536
                right_edge[0] = IO_IO_OUT1_DELAY_MAX + 1;
7537
 
7538
                sticky_bit_chk = 0;
7539
                //USER Search for the left edge of the window for the DM bit
7540
                for (d = 0; d <= IO_IO_OUT1_DELAY_MAX; d++) {
7541
                        scc_mgr_apply_group_dm_out1_delay (write_group, d);
7542
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7543
 
7544
                        //USER Stop searching when the write test doesn't pass AND when we've seen a passing write before
7545
                        if (rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 1, PASS_ALL_BITS, &bit_chk, 0)) {
7546
                                DPRINT(2, "dm_calib: left=%lu passed", d);
7547
                                left_edge[0] = d;
7548
                        } else {
7549
                                DPRINT(2, "dm_calib: left=%lu failed", d);
7550
                                //USER If a left edge has not been seen yet, then a future passing test will mark this edge as the right edge 
7551
                                if (left_edge[0] == IO_IO_OUT1_DELAY_MAX + 1) {
7552
                                        right_edge[0] = -(d + 1);
7553
                                } else {
7554
                                        //USER left edge has been seen, so this failure marks the left edge, and we are done
7555
                                        break;
7556
                                }
7557
                        }
7558
                        DPRINT(2, "dm_calib[l,d=%lu]: left_edge: %ld right_edge: %ld",
7559
                               d, left_edge[0], right_edge[0]);
7560
                }
7561
 
7562
                DPRINT(2, "dm_calib left done: left_edge: %ld right_edge: %ld",
7563
                       left_edge[0], right_edge[0]);
7564
 
7565
                //USER Reset DM delay chains to 0
7566
                scc_mgr_apply_group_dm_out1_delay (write_group, 0);
7567
 
7568
                //USER Check for cases where we haven't found the left edge, which makes our assignment of the the 
7569
                //USER right edge invalid.  Reset it to the illegal value. 
7570
                if ((left_edge[0] == IO_IO_OUT1_DELAY_MAX + 1) && (right_edge[0] != IO_IO_OUT1_DELAY_MAX + 1)) {
7571
                        right_edge[0] = IO_IO_OUT1_DELAY_MAX + 1;
7572
                        DPRINT(2, "dm_calib: reset right_edge: %ld", right_edge[0]);
7573
                }
7574
 
7575
                //USER Search for the right edge of the window for the DM bit
7576
                for (d = 0; d <= IO_IO_OUT1_DELAY_MAX - new_dqs; d++) {
7577
                        // Note: This only shifts DQS, so are we limiting ourselve to
7578
                        // width of DQ unnecessarily
7579
                        scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, d + new_dqs);
7580
 
7581
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7582
 
7583
                        //USER Stop searching when the test fails and we've seen passing test already
7584
                        if (rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 1, PASS_ALL_BITS, &bit_chk, 0)) {
7585
                                DPRINT(2, "dm_calib: right=%lu passed", d);
7586
                                right_edge[0] = d;
7587
                        } else {
7588
                                recover_mem_device_after_ck_dqs_violation();
7589
 
7590
                                DPRINT(2, "dm_calib: right=%lu failed", d);
7591
                                if (d != 0) {
7592
                                        //USER If a right edge has not been seen yet, then a future passing test will mark this edge as the left edge 
7593
                                        if (right_edge[0] == IO_IO_OUT1_DELAY_MAX + 1) {
7594
                                                left_edge[0] = -(d + 1);
7595
                                        } else {
7596
                                                break;
7597
                                        }
7598
                                } else {
7599
                                        //USER d = 0 failed, but it passed when testing the left edge, so it must be marginal, set it to -1
7600
                                        if (right_edge[0] == IO_IO_OUT1_DELAY_MAX + 1 && left_edge[0] != IO_IO_OUT1_DELAY_MAX + 1) {
7601
                                                right_edge[0] = -1;
7602
                                                // we're done
7603
                                                break;
7604
                                        }
7605
                                        //USER If a right edge has not been seen yet, then a future passing test will mark this edge as the left edge 
7606
                                        else if (right_edge[0] == IO_IO_OUT1_DELAY_MAX + 1) {
7607
                                                left_edge[0] = -(d + 1);
7608
                                        }
7609
                                }
7610
                        }
7611
                        DPRINT(2, "dm_calib[l,d=%lu]: left_edge: %ld right_edge: %ld",
7612
                               d, left_edge[0], right_edge[0]);
7613
                }
7614
 
7615
                DPRINT(2, "dm_calib: left=%ld right=%ld", left_edge[0], right_edge[0]);
7616
#if BFM_MODE
7617
                // need to update for all groups covered by this dm
7618
                for (i = write_group+1-(RW_MGR_MEM_IF_WRITE_DQS_WIDTH/RW_MGR_MEM_DATA_MASK_WIDTH); i <= write_group; i++)
7619
                {
7620
                        DPRINT(3, "dm_calib: left[%d]=%ld right[%d]=%ld", i, left_edge[0], i, right_edge[0]);
7621
                        BFM_GBL_SET(dm_left_edge[i][0],left_edge[0]);
7622
                        BFM_GBL_SET(dm_right_edge[i][0],right_edge[0]);
7623
                }
7624
#endif
7625
 
7626
                //USER Move DQS (back to orig)
7627
                scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, new_dqs);
7628
 
7629
                //USER move DM
7630
                //USER Find middle of window for the DM bit
7631
                mid = (left_edge[0] - right_edge[0]) / 2;
7632
                if (mid < 0) {
7633
                        mid = 0;
7634
                }
7635
                scc_mgr_apply_group_dm_out1_delay (write_group, mid);
7636
 
7637
                dm_margin = left_edge[0];
7638
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7639
                DPRINT(2, "dm_calib: left=%ld right=%ld mid=%ld dm_margin=%ld",
7640
                       left_edge[0], right_edge[0], mid, dm_margin);
7641
        } // end of DM calibration
7642
#endif
7643
 
7644
 
7645
#if DDRX
7646
        //USER set the left and right edge of each bit to an illegal value 
7647
        //USER use (IO_IO_OUT1_DELAY_MAX + 1) as an illegal value
7648
        left_edge[0]  = IO_IO_OUT1_DELAY_MAX + 1;
7649
        right_edge[0] = IO_IO_OUT1_DELAY_MAX + 1;
7650
        alt_32 bgn_curr = IO_IO_OUT1_DELAY_MAX + 1;
7651
        alt_32 end_curr = IO_IO_OUT1_DELAY_MAX + 1;
7652
        alt_32 bgn_best = IO_IO_OUT1_DELAY_MAX + 1;
7653
        alt_32 end_best = IO_IO_OUT1_DELAY_MAX + 1;
7654
        alt_32 win_best = 0;
7655
 
7656
        //USER Search for the/part of the window with DM shift
7657
        for (d = IO_IO_OUT1_DELAY_MAX; d >= 0; d-=DELTA_D) {
7658
                scc_mgr_apply_group_dm_out1_delay (write_group, d);
7659
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7660
 
7661
                if (rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 1, PASS_ALL_BITS, &bit_chk, 0)) {
7662
 
7663
                        //USE Set current end of the window
7664
                        end_curr = -d;
7665
                        //USER If a starting edge of our window has not been seen this is our current start of the DM window
7666
                        if(bgn_curr == IO_IO_OUT1_DELAY_MAX + 1){
7667
                                bgn_curr = -d;
7668
                        }
7669
 
7670
                        //USER If current window is bigger than best seen. Set best seen to be current window 
7671
                        if((end_curr-bgn_curr+1) > win_best ){
7672
                                win_best = end_curr-bgn_curr+1;
7673
                                bgn_best = bgn_curr;
7674
                                end_best = end_curr;
7675
                        }
7676
                } else {
7677
                        //USER We just saw a failing test. Reset temp edge
7678
                        bgn_curr=IO_IO_OUT1_DELAY_MAX + 1;
7679
                        end_curr=IO_IO_OUT1_DELAY_MAX + 1;
7680
                        }
7681
 
7682
 
7683
                }
7684
 
7685
 
7686
        //USER Reset DM delay chains to 0
7687
        scc_mgr_apply_group_dm_out1_delay (write_group, 0);
7688
 
7689
        //USER Check to see if the current window nudges up aganist 0 delay. If so we need to continue the search by shifting DQS otherwise DQS search begins as a new search
7690
        if(end_curr!=0) {
7691
                bgn_curr=IO_IO_OUT1_DELAY_MAX + 1;
7692
                end_curr=IO_IO_OUT1_DELAY_MAX + 1;
7693
        }
7694
 
7695
        //USER Search for the/part of the window with DQS shifts
7696
        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX - new_dqs; d+=DELTA_D) {
7697
                // Note: This only shifts DQS, so are we limiting ourselve to
7698
                // width of DQ unnecessarily
7699
                scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, d + new_dqs);
7700
 
7701
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7702
 
7703
                if (rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 1, PASS_ALL_BITS, &bit_chk, 0)) {
7704
 
7705
                        //USE Set current end of the window
7706
                        end_curr = d;
7707
                        //USER If a beginning edge of our window has not been seen this is our current begin of the DM window
7708
                        if(bgn_curr == IO_IO_OUT1_DELAY_MAX + 1){
7709
                                bgn_curr = d;
7710
                        }
7711
 
7712
                        //USER If current window is bigger than best seen. Set best seen to be current window
7713
                        if((end_curr-bgn_curr+1) > win_best){
7714
                                win_best = end_curr-bgn_curr+1;
7715
                                bgn_best = bgn_curr;
7716
                                end_best = end_curr;
7717
                        }
7718
                } else {
7719
                        //USER We just saw a failing test. Reset temp edge
7720
                        recover_mem_device_after_ck_dqs_violation();
7721
                        bgn_curr = IO_IO_OUT1_DELAY_MAX + 1;
7722
                        end_curr = IO_IO_OUT1_DELAY_MAX + 1;
7723
 
7724
                        //USER Early exit optimization: if ther remaining delay chain space is less than already seen largest window we can exit
7725
                        if((win_best-1) > (IO_IO_OUT1_DELAY_MAX - new_dqs - d)){
7726
                                        break;
7727
                                }
7728
 
7729
                                }
7730
                                }
7731
 
7732
        //USER assign left and right edge for cal and reporting;
7733
        left_edge[0] = -1*bgn_best;
7734
        right_edge[0] = end_best;
7735
 
7736
        DPRINT(2, "dm_calib: left=%ld right=%ld", left_edge[0], right_edge[0]);
7737
        BFM_GBL_SET(dm_left_edge[write_group][0],left_edge[0]);
7738
        BFM_GBL_SET(dm_right_edge[write_group][0],right_edge[0]);
7739
 
7740
        //USER Move DQS (back to orig)
7741
        scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, new_dqs);
7742
 
7743
        //USER Move DM
7744
 
7745
        //USER Find middle of window for the DM bit
7746
        mid = (left_edge[0] - right_edge[0]) / 2;
7747
 
7748
        //USER only move right, since we are not moving DQS/DQ
7749
        if (mid < 0) {
7750
                mid = 0;
7751
        }
7752
 
7753
        //dm_marign should fail if we never find a window
7754
        if(win_best==0){
7755
                dm_margin = -1;
7756
        }else{
7757
                dm_margin = left_edge[0] - mid;
7758
        }
7759
 
7760
 
7761
 
7762
        scc_mgr_apply_group_dm_out1_delay(write_group, mid);
7763
        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7764
 
7765
        DPRINT(2, "dm_calib: left=%ld right=%ld mid=%ld dm_margin=%ld",
7766
               left_edge[0], right_edge[0], mid, dm_margin);
7767
#endif
7768
 
7769
#if QDRII
7770
        sticky_bit_chk = 0;
7771
 
7772
        //USER set the left and right edge of each bit to an illegal value
7773
        //USER use (IO_IO_OUT1_DELAY_MAX + 1) as an illegal value
7774
        for (i = 0; i < RW_MGR_MEM_DATA_MASK_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
7775
                left_edge[i] = right_edge[i] = IO_IO_OUT1_DELAY_MAX + 1;
7776
        }
7777
 
7778
        mask = param->dm_correct_mask;
7779
 
7780
        //USER Search for the left edge of the window for the DM bit
7781
        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX; d++) {
7782
                scc_mgr_apply_group_dm_out1_delay (write_group, d);
7783
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7784
 
7785
                //USER Stop searching when the read test doesn't pass for all bits (as they've already been calibrated)
7786
                stop = !rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 1, PASS_ONE_BIT, &bit_chk, 0);
7787
                DPRINT(2, "dm_calib[l,d=%lu] stop=%ld bit_chk=%llx sticky_bit_chk=%llx mask=%llx",
7788
                       d, stop, bit_chk, sticky_bit_chk, param->write_correct_mask);
7789
                tmp_bit_chk = bit_chk;
7790
                tmp_mask = mask;
7791
                for (i = 0; i < RW_MGR_MEM_DATA_MASK_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
7792
                        if ( (tmp_bit_chk & mask) == mask ) {
7793
                                sticky_bit_chk = sticky_bit_chk | tmp_mask;
7794
                        }
7795
                        tmp_bit_chk = tmp_bit_chk >> (RW_MGR_MEM_DATA_WIDTH / RW_MGR_MEM_DATA_MASK_WIDTH);
7796
                        tmp_mask = tmp_mask << (RW_MGR_MEM_DATA_WIDTH / RW_MGR_MEM_DATA_MASK_WIDTH);
7797
                }
7798
                stop = stop && (sticky_bit_chk == param->write_correct_mask);
7799
 
7800
                if (stop == 1) {
7801
                        break;
7802
                } else {
7803
                        for (i = 0; i < RW_MGR_MEM_DATA_MASK_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
7804
                                DPRINT(2, "dm_calib[l,i=%lu] d=%lu bit_chk&dm_mask=" BTFLD_FMT " == " BTFLD_FMT, i, d,
7805
                                       bit_chk & mask, mask);
7806
                                if ((bit_chk & mask) == mask) {
7807
                                        DPRINT(2, "dm_calib: left[%lu]=%lu", i, d);
7808
                                        left_edge[i] = d;
7809
                                } else {
7810
                                        //USER If a left edge has not been seen yet, then a future passing test will mark this edge as the right edge
7811
                                        if (left_edge[i] == IO_IO_OUT1_DELAY_MAX + 1) {
7812
                                                right_edge[i] = -(d + 1);
7813
                                        }
7814
                                }
7815
                                bit_chk = bit_chk >> (RW_MGR_MEM_DATA_WIDTH / RW_MGR_MEM_DATA_MASK_WIDTH);
7816
                        }
7817
                }
7818
        }
7819
 
7820
        //USER Reset DM delay chains to 0
7821
        scc_mgr_apply_group_dm_out1_delay (write_group, 0);
7822
 
7823
        //USER Check for cases where we haven't found the left edge, which makes our assignment of the the
7824
        //USER right edge invalid.  Reset it to the illegal value.
7825
        for (i = 0; i < RW_MGR_MEM_DATA_MASK_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
7826
                if ((left_edge[i] == IO_IO_OUT1_DELAY_MAX + 1) && (right_edge[i] != IO_IO_OUT1_DELAY_MAX + 1)) {
7827
                        right_edge[i] = IO_IO_OUT1_DELAY_MAX + 1;
7828
                        DPRINT(2, "dm_calib: reset right_edge: %d", right_edge[i]);
7829
                }
7830
        }
7831
 
7832
        //USER Search for the right edge of the window for the DM bit
7833
        for (d = 0; d <= IO_IO_OUT1_DELAY_MAX - new_dqs; d++) {
7834
                scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, d + new_dqs);
7835
 
7836
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7837
 
7838
                rw_mgr_mem_dll_lock_wait();
7839
 
7840
                //USER Stop searching when the read test doesn't pass for all bits (as they've already been calibrated)
7841
                stop = !rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 1, PASS_ONE_BIT, &bit_chk, 0);
7842
                DPRINT(2, "dm_calib[l,d=%lu] stop=%ld bit_chk=%llx sticky_bit_chk=%llx mask=%llx",
7843
                       d, stop, bit_chk, sticky_bit_chk, param->write_correct_mask);
7844
                tmp_bit_chk = bit_chk;
7845
                tmp_mask = mask;
7846
                for (i = 0; i < RW_MGR_MEM_DATA_MASK_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
7847
                        if ( (tmp_bit_chk & mask) == mask ) {
7848
                                sticky_bit_chk = sticky_bit_chk | tmp_mask;
7849
                        }
7850
                        tmp_bit_chk = tmp_bit_chk >> (RW_MGR_MEM_DATA_WIDTH / RW_MGR_MEM_DATA_MASK_WIDTH);
7851
                        tmp_mask = tmp_mask << (RW_MGR_MEM_DATA_WIDTH / RW_MGR_MEM_DATA_MASK_WIDTH);
7852
                }
7853
                stop = stop && (sticky_bit_chk == param->write_correct_mask);
7854
 
7855
                if (stop == 1) {
7856
                        break;
7857
                } else {
7858
                        for (i = 0; i < RW_MGR_MEM_DATA_MASK_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
7859
                                DPRINT(2, "dm_calib[r,i=%lu] d=%lu bit_chk&dm_mask=" BTFLD_FMT " == " BTFLD_FMT, i, d,
7860
                                       bit_chk & mask, mask);
7861
                                if ((bit_chk & mask) == mask) {
7862
                                        right_edge[i] = d;
7863
                                } else {
7864
                                        //USER d = 0 failed, but it passed when testing the left edge, so it must be marginal, set it to -1
7865
                                        if (right_edge[i] == IO_IO_OUT1_DELAY_MAX + 1 && left_edge[i] != IO_IO_OUT1_DELAY_MAX + 1) {
7866
                                                right_edge[i] = -1;
7867
                                                // we're done
7868
                                                break;
7869
                                        }
7870
                                        //USER If a right edge has not been seen yet, then a future passing test will mark this edge as the left edge
7871
                                        else if (right_edge[i] == IO_IO_OUT1_DELAY_MAX + 1) {
7872
                                                left_edge[i] = -(d + 1);
7873
                                        }
7874
                                }
7875
                                bit_chk = bit_chk >> (RW_MGR_MEM_DATA_WIDTH / RW_MGR_MEM_DATA_MASK_WIDTH);
7876
                        }
7877
                }
7878
        }
7879
 
7880
        //USER Move DQS (back to orig)
7881
        scc_mgr_set_group_dqs_io_and_oct_out1_gradual (write_group, new_dqs);
7882
 
7883
        //USER Move DM
7884
        dm_margin = IO_IO_OUT1_DELAY_MAX;
7885
        for (i = 0; i < RW_MGR_MEM_DATA_MASK_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
7886
                //USER Find middle of window for the DM bit
7887
                mid = (left_edge[i] - right_edge[i]) / 2;
7888
                DPRINT(2, "dm_calib[mid,i=%lu] left=%ld right=%ld mid=%ld", i, left_edge[i], right_edge[i], mid);
7889
                BFM_GBL_SET(dm_left_edge[write_group][i],left_edge[i]);
7890
                BFM_GBL_SET(dm_right_edge[write_group][i],right_edge[i]);
7891
                if (mid < 0) {
7892
                        mid = 0;
7893
                }
7894
                scc_mgr_set_dm_out1_delay(write_group, i, mid);
7895
                scc_mgr_load_dm (i);
7896
                if ((left_edge[i] - mid) < dm_margin) {
7897
                        dm_margin = left_edge[i] - mid;
7898
                }
7899
        }
7900
#endif
7901
 
7902
        // Store observed DM margins
7903
#if RLDRAMX
7904
        if (is_write_group_enabled_for_dm(write_group))
7905
        {
7906
                TCLRPT_SET(debug_cal_report->cal_dm_margins[curr_shadow_reg][write_group][0].left_edge, left_edge[0]);
7907
                TCLRPT_SET(debug_cal_report->cal_dm_margins[curr_shadow_reg][write_group][0].right_edge, right_edge[0]);
7908
        }
7909
#else
7910
        for (i = 0; i < RW_MGR_NUM_TRUE_DM_PER_WRITE_GROUP; i++) {
7911
                TCLRPT_SET(debug_cal_report->cal_dm_margins[curr_shadow_reg][write_group][i].left_edge, left_edge[i]);
7912
                TCLRPT_SET(debug_cal_report->cal_dm_margins[curr_shadow_reg][write_group][i].right_edge, right_edge[i]);
7913
        }
7914
#endif
7915
 
7916
#if RUNTIME_CAL_REPORT
7917
        for (i = 0; i < RW_MGR_NUM_TRUE_DM_PER_WRITE_GROUP; i++) {
7918
                RPRINT("DM Deskew ; Group %lu ; Left edge %3li; Right edge %3li; DM delay %2li", write_group, left_edge[i], right_edge[i], mid);
7919
        }
7920
#endif
7921
 
7922
        //USER Export values 
7923
        gbl->fom_out += dq_margin + dqs_margin;
7924
 
7925
        TCLRPT_SET(debug_cal_report->cal_dqs_out_margins[curr_shadow_reg][write_group].dqs_margin, dqs_margin);
7926
        TCLRPT_SET(debug_cal_report->cal_dqs_out_margins[curr_shadow_reg][write_group].dq_margin, dq_margin);
7927
 
7928
#if RLDRAMX
7929
        if (is_write_group_enabled_for_dm(write_group))
7930
        {
7931
                TCLRPT_SET(debug_cal_report->cal_dqs_out_margins[curr_shadow_reg][write_group].dm_margin, dm_margin);
7932
        }
7933
#else
7934
        TCLRPT_SET(debug_cal_report->cal_dqs_out_margins[curr_shadow_reg][write_group].dm_margin, dm_margin);
7935
#endif
7936
        TCLRPT_SET(debug_summary_report->fom_out, debug_summary_report->fom_out + (dq_margin + dqs_margin));
7937
        TCLRPT_SET(debug_cal_report->cal_status_per_group[curr_shadow_reg][write_group].fom_out, (dq_margin + dqs_margin));
7938
 
7939
        DPRINT(2, "write_center: dq_margin=%ld dqs_margin=%ld dm_margin=%ld", dq_margin, dqs_margin, dm_margin);
7940
 
7941
        //USER Do not remove this line as it makes sure all of our decisions have been applied
7942
        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7943
        return (dq_margin >= 0) && (dqs_margin >= 0) && (dm_margin >= 0);
7944
}
7945
 
7946
#else // !NEWVERSION_WRDESKEW
7947
 
7948
alt_u32 rw_mgr_mem_calibrate_writes_center (alt_u32 rank_bgn, alt_u32 write_group, alt_u32 test_bgn)
7949
{
7950
        alt_u32 i, p, d;
7951
        alt_u32 mid;
7952
        t_btfld bit_chk, sticky_bit_chk;
7953
        alt_u32 max_working_dq[RW_MGR_MEM_DQ_PER_WRITE_DQS];
7954
        alt_u32 max_working_dm[RW_MGR_MEM_DATA_MASK_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH];
7955
        alt_u32 dq_margin, dqs_margin, dm_margin;
7956
        alt_u32 start_dqs;
7957
        alt_u32 stop;
7958
 
7959
        TRACE_FUNC("%lu %lu", write_group, test_bgn);
7960
 
7961
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
7962
 
7963
        //USER per-bit deskew 
7964
 
7965
        for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
7966
                max_working_dq[i] = 0;
7967
        }
7968
 
7969
        for (d = 1; d <= IO_IO_OUT1_DELAY_MAX; d++) {
7970
                scc_mgr_apply_group_dq_out1_delay (write_group, test_bgn, d);
7971
 
7972
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
7973
 
7974
                if (!rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 0, PASS_ONE_BIT, &bit_chk, 0)) {
7975
                        break;
7976
                } else {
7977
                        for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
7978
                                if (bit_chk & 1) {
7979
                                        max_working_dq[i] = d;
7980
                                }
7981
                                bit_chk = bit_chk >> 1;
7982
                        }
7983
                }
7984
        }
7985
 
7986
        scc_mgr_apply_group_dq_out1_delay (write_group, test_bgn, 0);
7987
 
7988
        //USER determine minimum of maximums 
7989
 
7990
        dq_margin = IO_IO_OUT1_DELAY_MAX;
7991
 
7992
        for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
7993
                if (max_working_dq[i] < dq_margin) {
7994
                        dq_margin = max_working_dq[i];
7995
                }
7996
        }
7997
 
7998
        //USER add delay to center DQ windows 
7999
 
8000
        for (i = 0, p = test_bgn; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++, p++) {
8001
                if (max_working_dq[i] > dq_margin) {
8002
                        scc_mgr_set_dq_out1_delay(write_group, i, max_working_dq[i] - dq_margin);
8003
                } else {
8004
                        scc_mgr_set_dq_out1_delay(write_group, i, 0);
8005
                }
8006
 
8007
                scc_mgr_load_dq (p, i);
8008
        }
8009
 
8010
        //USER sweep DQS window, may potentially have more window due to per-bit-deskew
8011
 
8012
        start_dqs = READ_SCC_DQS_IO_OUT1_DELAY();
8013
 
8014
        for (d = start_dqs + 1; d <= IO_IO_OUT1_DELAY_MAX; d++) {
8015
                scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, d);
8016
 
8017
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8018
 
8019
                if (QDRII)
8020
                {
8021
                        rw_mgr_mem_dll_lock_wait();
8022
                }
8023
 
8024
                if (!rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 0, PASS_ALL_BITS, &bit_chk, 0)) {
8025
                        break;
8026
                }
8027
        }
8028
 
8029
        scc_mgr_set_dqs_out1_delay(write_group, start_dqs);
8030
        scc_mgr_set_oct_out1_delay(write_group, start_dqs);
8031
 
8032
        dqs_margin = d - start_dqs - 1;
8033
 
8034
        //USER time to center, +1 so that we don't go crazy centering DQ 
8035
 
8036
        mid = (dq_margin + dqs_margin + 1) / 2;
8037
 
8038
        gbl->fom_out += dq_margin + dqs_margin;
8039
        TCLRPT_SET(debug_summary_report->fom_out, debug_summary_report->fom_out + (dq_margin + dqs_margin));
8040
        TCLRPT_SET(debug_cal_report->cal_status_per_group[curr_shadow_reg][grp].fom_out, (dq_margin + dqs_margin));
8041
 
8042
#if ENABLE_DQS_OUT_CENTERING
8043
        //USER center DQS ... if the headroom is setup properly we shouldn't need to 
8044
        if (DDRX) {
8045
                if (dqs_margin > mid) {
8046
                        scc_mgr_set_dqs_out1_delay(write_group, READ_SCC_DQS_IO_OUT1_DELAY() + dqs_margin - mid);
8047
                        scc_mgr_set_oct_out1_delay(write_group, READ_SCC_OCT_OUT1_DELAY(write_group) + dqs_margin - mid);
8048
                }
8049
        }
8050
#endif
8051
 
8052
        scc_mgr_load_dqs_io ();
8053
        scc_mgr_load_dqs_for_write_group (write_group);
8054
 
8055
        //USER center dq 
8056
 
8057
        if (dq_margin > mid) {
8058
                for (i = 0, p = test_bgn; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++, p++) {
8059
                        scc_mgr_set_dq_out1_delay(write_group, i, READ_SCC_DQ_OUT1_DELAY(i) + dq_margin - mid);
8060
                        scc_mgr_load_dq (p, i);
8061
                }
8062
                dqs_margin += dq_margin - mid;
8063
                dq_margin  -= dq_margin - mid;
8064
        }
8065
 
8066
        //USER do dm centering 
8067
 
8068
        if (!RLDRAMX) {
8069
                dm_margin = IO_IO_OUT1_DELAY_MAX;
8070
 
8071
                if (QDRII) {
8072
                        sticky_bit_chk = 0;
8073
                        for (i = 0; i < RW_MGR_MEM_DATA_MASK_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
8074
                                max_working_dm[i] = 0;
8075
                        }
8076
                }
8077
 
8078
                for (d = 1; d <= IO_IO_OUT1_DELAY_MAX; d++) {
8079
                        scc_mgr_apply_group_dm_out1_delay (write_group, d);
8080
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8081
 
8082
                        if (DDRX) {
8083
                                if (rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 1, PASS_ALL_BITS, &bit_chk, 0)) {
8084
                                        max_working_dm[0] = d;
8085
                                } else {
8086
                                        break;
8087
                                }
8088
                        } else {
8089
                                stop = !rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 1, PASS_ALL_BITS, &bit_chk, 0);
8090
                                sticky_bit_chk = sticky_bit_chk | bit_chk;
8091
                                stop = stop && (sticky_bit_chk == param->read_correct_mask);
8092
 
8093
                                if (stop == 1) {
8094
                                        break;
8095
                                } else {
8096
                                        for (i = 0; i < RW_MGR_MEM_DATA_MASK_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
8097
                                                if ((bit_chk & param->dm_correct_mask) == param->dm_correct_mask) {
8098
                                                        max_working_dm[i] = d;
8099
                                                }
8100
                                                bit_chk = bit_chk >> (RW_MGR_MEM_DATA_WIDTH / RW_MGR_MEM_DATA_MASK_WIDTH);
8101
                                        }
8102
                                }
8103
                        }
8104
                }
8105
 
8106
                i = 0;
8107
                for (i = 0; i < RW_MGR_NUM_DM_PER_WRITE_GROUP; i++) {
8108
                        if (max_working_dm[i] > mid) {
8109
                                scc_mgr_set_dm_out1_delay(write_group, i, max_working_dm[i] - mid);
8110
                        } else {
8111
                                scc_mgr_set_dm_out1_delay(write_group, i, 0);
8112
                        }
8113
 
8114
                        scc_mgr_load_dm (i);
8115
 
8116
                        if (max_working_dm[i] < dm_margin) {
8117
                                dm_margin = max_working_dm[i];
8118
                        }
8119
                }
8120
        } else {
8121
                dm_margin = 0;
8122
        }
8123
 
8124
        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8125
 
8126
        return (dq_margin + dqs_margin) > 0;
8127
}
8128
 
8129
#endif
8130
 
8131
//USER calibrate the write operations
8132
 
8133
alt_u32 rw_mgr_mem_calibrate_writes (alt_u32 rank_bgn, alt_u32 g, alt_u32 test_bgn)
8134
{
8135
        //USER update info for sims
8136
 
8137
        TRACE_FUNC("%lu %lu", g, test_bgn);
8138
 
8139
        reg_file_set_stage(CAL_STAGE_WRITES);
8140
        reg_file_set_sub_stage(CAL_SUBSTAGE_WRITES_CENTER);
8141
 
8142
        //USER starting phases 
8143
 
8144
        //USER update info for sims
8145
 
8146
        reg_file_set_group(g);
8147
 
8148
        if (!rw_mgr_mem_calibrate_writes_center (rank_bgn, g, test_bgn)) {
8149
                set_failing_group_stage(g, CAL_STAGE_WRITES, CAL_SUBSTAGE_WRITES_CENTER);
8150
                return 0;
8151
        }
8152
 
8153
 
8154
        return 1;
8155
}
8156
 
8157
// helpful for creating eye diagrams 
8158
// TODO: This is for the TCL DBG... but obviously it serves no purpose...
8159
// Decide what to do with it!
8160
 
8161
void rw_mgr_mem_calibrate_eye_diag_aid (void)
8162
{
8163
        // no longer exists
8164
}
8165
 
8166
// TODO: This needs to be update to properly handle the number of failures
8167
// Right now it only checks if the write test was successful or not
8168
alt_u32 rw_mgr_mem_calibrate_full_test (alt_u32 min_correct, t_btfld *bit_chk, alt_u32 test_dm)
8169
{
8170
        alt_u32 g;
8171
        alt_u32 success = 0;
8172
        alt_u32 run_groups = ~param->skip_groups;
8173
 
8174
        TRACE_FUNC("%lu %lu", min_correct, test_dm);
8175
 
8176
        for (g = 0; g < RW_MGR_MEM_IF_READ_DQS_WIDTH; g++) {
8177
                if (run_groups & ((1 << RW_MGR_NUM_DQS_PER_WRITE_GROUP) - 1))
8178
                {
8179
                        success = rw_mgr_mem_calibrate_write_test_all_ranks (g, test_dm, PASS_ALL_BITS, bit_chk);
8180
                }
8181
                run_groups = run_groups >> RW_MGR_NUM_DQS_PER_WRITE_GROUP;
8182
        }
8183
 
8184
        return success;
8185
}
8186
 
8187
#if ENABLE_TCL_DEBUG
8188
// see how far we can push a particular DQ pin before complete failure on input and output sides
8189
// NOTE: if ever executing a run_*_margining function outside of calibration context you must first issue IOWR_32DIRECT (PHY_MGR_MUX_SEL, 0, 1);
8190
void run_dq_margining (alt_u32 rank_bgn, alt_u32 write_group)
8191
{
8192
        alt_u32 test_num;
8193
        alt_u32 read_group;
8194
        alt_u32 read_test_bgn;
8195
        alt_u32 subdq;
8196
        alt_u32 dq;
8197
        alt_u32 delay;
8198
        alt_u32 calibrated_delay;
8199
        alt_u32 working_cnt;
8200
        t_btfld bit_chk;
8201
        t_btfld bit_chk_test = 0;
8202
        t_btfld bit_chk_mask;
8203
 
8204
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
8205
 
8206
        select_curr_shadow_reg_using_rank(rank_bgn);
8207
 
8208
        // Load the read patterns
8209
        rw_mgr_mem_calibrate_read_load_patterns (rank_bgn, 0);
8210
 
8211
        // sweep input delays
8212
        for (read_group = write_group * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH, read_test_bgn = 0;
8213
                 read_group < (write_group + 1) * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH;
8214
                 read_group++, read_test_bgn += RW_MGR_MEM_DQ_PER_READ_DQS)
8215
        {
8216
 
8217
                ALTERA_ASSERT(read_group < RW_MGR_MEM_IF_READ_DQS_WIDTH);
8218
 
8219
                for (subdq = 0; subdq < RW_MGR_MEM_DQ_PER_READ_DQS; subdq++)
8220
                {
8221
                        dq = read_group*RW_MGR_MEM_DQ_PER_READ_DQS + subdq;
8222
 
8223
                        ALTERA_ASSERT(dq < RW_MGR_MEM_DATA_WIDTH);
8224
 
8225
                        calibrated_delay =  debug_cal_report->cal_dq_settings[curr_shadow_reg][dq].dq_in_delay;
8226
 
8227
                        working_cnt = 0;
8228
 
8229
                        bit_chk_test = 0;
8230
 
8231
                        // Find the left edge
8232
                        for (delay = calibrated_delay; delay <= IO_IO_IN_DELAY_MAX; delay++)
8233
                        {
8234
                                WRITE_SCC_DQ_IN_DELAY((subdq + read_test_bgn), delay);
8235
                                scc_mgr_load_dq (subdq + read_test_bgn);
8236
                                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8237
 
8238
                                for (test_num = 0; test_num < NUM_READ_TESTS; test_num++)
8239
                                {
8240
                                        rw_mgr_mem_calibrate_read_test (rank_bgn, read_group, 1, PASS_ONE_BIT, &bit_chk, 0, 0);
8241
                                        if (test_num == 0)
8242
                                        {
8243
                                                bit_chk_test = bit_chk;
8244
                                        }
8245
                                        else
8246
                                        {
8247
                                                bit_chk_test &= bit_chk;
8248
                                        }
8249
                                }
8250
 
8251
                                // Check only the bit we are testing
8252
                                bit_chk_mask = (bit_chk_test & (((t_btfld) 1) << ((t_btfld) subdq)));
8253
                                if (bit_chk_mask == 0)
8254
                                {
8255
                                        break;
8256
                                }
8257
 
8258
                                working_cnt++;
8259
                        }
8260
 
8261
                        // Restore the settings
8262
                        WRITE_SCC_DQ_IN_DELAY((subdq + read_test_bgn), calibrated_delay);
8263
                        scc_mgr_load_dq (subdq + read_test_bgn);
8264
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8265
 
8266
                        // Store the setting
8267
                        TCLRPT_SET(debug_margin_report->margin_dq_in_margins[curr_shadow_reg][dq].min_working_setting, working_cnt);
8268
 
8269
                        // Find the right edge
8270
                        calibrated_delay = debug_cal_report->cal_dqs_in_settings[curr_shadow_reg][read_group].dqs_bus_in_delay;
8271
 
8272
                        working_cnt = 0;
8273
                        for (delay = calibrated_delay; delay <= IO_DQS_IN_DELAY_MAX; delay++)
8274
                        {
8275
                                WRITE_SCC_DQS_IN_DELAY(read_group, delay);
8276
                                scc_mgr_load_dqs(read_group);
8277
                                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8278
 
8279
                                for (test_num = 0; test_num < NUM_READ_TESTS; test_num++)
8280
                                {
8281
                                        rw_mgr_mem_calibrate_read_test (rank_bgn, read_group, 1, PASS_ONE_BIT, &bit_chk, 0, 0);
8282
                                        if (test_num == 0)
8283
                                        {
8284
                                                bit_chk_test = bit_chk;
8285
                                        }
8286
                                        else
8287
                                        {
8288
                                                bit_chk_test &= bit_chk;
8289
                                        }
8290
                                }
8291
 
8292
                                // Check only the bit we are testing
8293
                                bit_chk_mask = (bit_chk_test & (((t_btfld)1) << ((t_btfld)(subdq))));
8294
                                if (bit_chk_mask == 0)
8295
                                {
8296
                                        break;
8297
                                }
8298
 
8299
                                working_cnt++;
8300
                        }
8301
 
8302
                        // Restore the settings
8303
                        WRITE_SCC_DQS_IN_DELAY(read_group, calibrated_delay);
8304
                        scc_mgr_load_dqs(read_group);
8305
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8306
 
8307
                        // Store the setting
8308
                        TCLRPT_SET(debug_margin_report->margin_dq_in_margins[curr_shadow_reg][dq].max_working_setting, working_cnt);
8309
 
8310
                }
8311
        }
8312
 
8313
        // sweep output delays
8314
        for (subdq = 0; subdq < RW_MGR_MEM_DQ_PER_WRITE_DQS; subdq++)
8315
        {
8316
                dq = write_group*RW_MGR_MEM_DQ_PER_WRITE_DQS + subdq;
8317
 
8318
                calibrated_delay = debug_cal_report->cal_dq_settings[curr_shadow_reg][dq].dq_out_delay1;
8319
                working_cnt = 0;
8320
 
8321
                // Find the left edge
8322
                for (delay = calibrated_delay; delay <= IO_IO_OUT1_DELAY_MAX; delay++)
8323
                {
8324
                        WRITE_SCC_DQ_OUT1_DELAY(subdq, delay);
8325
                        scc_mgr_load_dq (subdq);
8326
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8327
 
8328
                        for (test_num = 0; test_num < NUM_WRITE_TESTS; test_num++)
8329
                        {
8330
                                rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 0, PASS_ALL_BITS, &bit_chk, 0);
8331
                                if (test_num == 0)
8332
                                {
8333
                                        bit_chk_test = bit_chk;
8334
                                }
8335
                                else
8336
                                {
8337
                                        bit_chk_test &= bit_chk;
8338
                                }
8339
                        }
8340
 
8341
                        // Check only the bit we are testing
8342
                        bit_chk_mask = (bit_chk_test & (((t_btfld)1) << ((t_btfld)subdq)));
8343
                        if (bit_chk_mask == 0)
8344
                        {
8345
                                break;
8346
                        }
8347
 
8348
                        working_cnt++;
8349
                }
8350
 
8351
                // Restore the settings
8352
                WRITE_SCC_DQ_OUT1_DELAY(subdq, calibrated_delay);
8353
                scc_mgr_load_dq (subdq);
8354
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8355
 
8356
                // Store the setting
8357
                TCLRPT_SET(debug_margin_report->margin_dq_out_margins[curr_shadow_reg][dq].min_working_setting, working_cnt);
8358
 
8359
                // Find the right edge
8360
                calibrated_delay = debug_cal_report->cal_dqs_out_settings[curr_shadow_reg][write_group].dqs_out_delay1;
8361
 
8362
                working_cnt = 0;
8363
                for (delay = calibrated_delay; delay <= IO_IO_OUT1_DELAY_MAX; delay++)
8364
                {
8365
                        WRITE_SCC_DQS_IO_OUT1_DELAY(delay);
8366
                        scc_mgr_load_dqs_io();
8367
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8368
                        if (QDRII)
8369
                        {
8370
                                rw_mgr_mem_dll_lock_wait();
8371
                        }
8372
 
8373
                        for (test_num = 0; test_num < NUM_WRITE_TESTS; test_num++)
8374
                        {
8375
                                rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 0, PASS_ONE_BIT, &bit_chk, 0);
8376
                                if (test_num == 0)
8377
                                {
8378
                                        bit_chk_test = bit_chk;
8379
                                }
8380
                                else
8381
                                {
8382
                                        bit_chk_test &= bit_chk;
8383
                                }
8384
                        }
8385
 
8386
                        // Check only the bit we are testing
8387
                        bit_chk_mask = (bit_chk_test & (((t_btfld)1) << ((t_btfld)subdq)));
8388
                        if (bit_chk_mask == 0)
8389
                        {
8390
                                break;
8391
                        }
8392
 
8393
                        working_cnt++;
8394
                }
8395
 
8396
                //USER Restore the settings
8397
                if (QDRII) {
8398
                        scc_mgr_set_group_dqs_io_and_oct_out1_gradual (write_group, calibrated_delay);
8399
                } else {
8400
                        scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, calibrated_delay);
8401
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8402
                }
8403
 
8404
                // Store the setting
8405
                TCLRPT_SET(debug_margin_report->margin_dq_out_margins[curr_shadow_reg][dq].max_working_setting, working_cnt);
8406
        }
8407
}
8408
#endif
8409
 
8410
#if ENABLE_TCL_DEBUG
8411
// NOTE: if ever executing a run_*_margining function outside of calibration context you must first issue IOWR_32DIRECT (PHY_MGR_MUX_SEL, 0, 1);
8412
void run_dm_margining (alt_u32 rank_bgn, alt_u32 write_group)
8413
{
8414
        alt_u32 test_status;
8415
        alt_u32 test_num;
8416
        alt_u32 dm;
8417
        alt_u32 delay;
8418
        alt_u32 calibrated_delay;
8419
        alt_u32 working_cnt;
8420
        t_btfld bit_chk;
8421
 
8422
        ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
8423
 
8424
        select_curr_shadow_reg_using_rank(rank_bgn);
8425
 
8426
        // sweep output delays
8427
        for (dm = 0; dm < RW_MGR_NUM_DM_PER_WRITE_GROUP; dm++)
8428
        {
8429
 
8430
                calibrated_delay = debug_cal_report->cal_dm_settings[curr_shadow_reg][write_group][dm].dm_out_delay1;
8431
                working_cnt = 0;
8432
 
8433
                // Find the left edge
8434
                for (delay = calibrated_delay; delay <= IO_IO_OUT1_DELAY_MAX; delay++)
8435
                {
8436
                        WRITE_SCC_DM_IO_OUT1_DELAY(dm, delay);
8437
                        scc_mgr_load_dm (dm);
8438
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8439
 
8440
                        test_status = 1;
8441
                        for (test_num = 0; test_num < NUM_WRITE_TESTS; test_num++)
8442
                        {
8443
                                if (!rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 1, PASS_ALL_BITS, &bit_chk, 0))
8444
                                {
8445
                                        test_status = 0;
8446
                                        break;
8447
                                }
8448
                        }
8449
 
8450
                        if (test_status == 0)
8451
                        {
8452
                                break;
8453
                        }
8454
 
8455
                        working_cnt++;
8456
                }
8457
 
8458
                // Restore the settings
8459
                WRITE_SCC_DM_IO_OUT1_DELAY(dm, calibrated_delay);
8460
                scc_mgr_load_dm (dm);
8461
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8462
 
8463
                // Store the setting
8464
                TCLRPT_SET(debug_margin_report->margin_dm_margins[curr_shadow_reg][write_group][dm].min_working_setting, working_cnt);
8465
 
8466
                // Find the right edge
8467
                calibrated_delay = debug_cal_report->cal_dqs_out_settings[curr_shadow_reg][write_group].dqs_out_delay1;
8468
 
8469
                working_cnt = 0;
8470
                for (delay = calibrated_delay; delay <= IO_IO_OUT1_DELAY_MAX; delay++)
8471
                {
8472
                        WRITE_SCC_DQS_IO_OUT1_DELAY(delay);
8473
                        scc_mgr_load_dqs_io();
8474
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8475
                        if (QDRII)
8476
                        {
8477
                                rw_mgr_mem_dll_lock_wait();
8478
                        }
8479
 
8480
                        test_status = 1;
8481
                        for (test_num = 0; test_num < NUM_WRITE_TESTS; test_num++)
8482
                        {
8483
                                if (!rw_mgr_mem_calibrate_write_test (rank_bgn, write_group, 1, PASS_ALL_BITS, &bit_chk, 0))
8484
                                {
8485
                                        test_status = 0;
8486
                                        break;
8487
                                }
8488
                        }
8489
 
8490
                        if (test_status == 0)
8491
                        {
8492
                                break;
8493
                        }
8494
 
8495
                        working_cnt++;
8496
                }
8497
 
8498
                //USER Restore the settings
8499
                if (QDRII) {
8500
                        scc_mgr_set_group_dqs_io_and_oct_out1_gradual (write_group, calibrated_delay);
8501
                } else {
8502
                        scc_mgr_apply_group_dqs_io_and_oct_out1 (write_group, calibrated_delay);
8503
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8504
                }
8505
 
8506
                // Store the setting
8507
                TCLRPT_SET(debug_margin_report->margin_dm_margins[curr_shadow_reg][write_group][dm].max_working_setting, working_cnt);
8508
 
8509
        }
8510
}
8511
#endif
8512
 
8513
 
8514
//USER precharge all banks and activate row 0 in bank "000..." and bank "111..." 
8515
#if DDRX
8516
void mem_precharge_and_activate (void)
8517
{
8518
        alt_u32 r;
8519
 
8520
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
8521
                if (param->skip_ranks[r]) {
8522
                        //USER request to skip the rank
8523
 
8524
                        continue;
8525
                }
8526
 
8527
                //USER set rank
8528
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
8529
 
8530
                //USER precharge all banks ... 
8531
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_PRECHARGE_ALL);
8532
 
8533
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x0F);
8534
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_ACTIVATE_0_AND_1_WAIT1);
8535
 
8536
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x0F);
8537
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_ACTIVATE_0_AND_1_WAIT2);
8538
 
8539
                //USER activate rows 
8540
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_ACTIVATE_0_AND_1);
8541
        }
8542
}
8543
#endif
8544
 
8545
#if QDRII || RLDRAMX
8546
void mem_precharge_and_activate (void) {}
8547
#endif
8548
 
8549
//USER perform all refreshes necessary over all ranks
8550
#if (ENABLE_NON_DESTRUCTIVE_CALIB || ENABLE_NON_DES_CAL)
8551
// Only have DDR3 version for now
8552
#if DDR3
8553
alt_u32 mem_refresh_all_ranks (alt_u32 no_validate)
8554
{
8555
        const alt_u32 T_REFI_NS = 3900;                      // JEDEC spec refresh interval in ns (industrial temp)
8556
//      const alt_u32 T_RFC_NS = 350;                        // Worst case REFRESH-REFRESH or REFRESH-ACTIVATE wait time in ns
8557
                                                             // Alternatively, we could extract T_RFC from uniphy_gen.tcl
8558
        const alt_u32 T_RFC_AFI = 350 * AFI_CLK_FREQ / 1000; // T_RFC expressed in mem clk cycles (will be less than 256)
8559
#if (ENABLE_NON_DESTRUCTIVE_CALIB)      
8560
        const alt_u32 NUM_REFRESH_POSTING = 8192;            // Number of consecutive refresh commands supported by Micron DDR3 devices
8561
#else
8562
        const alt_u32 NUM_REFRESH_POSTING = 8;
8563
#endif
8564
        alt_u32 i;
8565
        alt_u32 elapsed_time;  // In AVL clock cycles
8566
 
8567
#if (ENABLE_NON_DESTRUCTIVE_CALIB)      
8568
        //USER Reset the refresh interval timer
8569
        elapsed_time = IORD_32DIRECT (BASE_TIMER, 0);
8570
        IOWR_32DIRECT (BASE_TIMER, 0, 0x00);
8571
 
8572
        //USER Validate that maximum refresh interval is not exceeded
8573
        if ( !no_validate ) {
8574
                if (!(~elapsed_time) || elapsed_time > (NUM_REFRESH_POSTING * T_REFI_NS * AVL_CLK_FREQ / 1000) ) {
8575
                        // Non-destructive calibration failure
8576
                        return 0;
8577
                }
8578
        }
8579
 
8580
#endif
8581
        //USER set CS and ODT mask
8582
        if ( RDIMM || LRDIMM ) {
8583
                if (RW_MGR_MEM_NUMBER_OF_RANKS == 1) {
8584
                        set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
8585
                }
8586
                else {
8587
                        // Only single-rank DIMM supported for non-destructive cal
8588
                        return 0;
8589
                }
8590
        }
8591
        else { // UDIMM
8592
                // Issue refreshes to all ranks simultaneously
8593
                IOWR_32DIRECT (RW_MGR_SET_CS_AND_ODT_MASK, 0, RW_MGR_RANK_ALL);
8594
        }
8595
 
8596
        //USER Precharge all banks
8597
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_PRECHARGE_ALL);
8598
        // Wait for tRP = 15ns before issuing REFRESH commands
8599
        // No need to insert explicit delay; simulation shows more than 1000 ns between PRECHARGE and first REFRESH
8600
 
8601
        //USER Issue refreshes
8602
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_REFRESH_ALL);
8603
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_REFRESH_DELAY);
8604
        for (i = 0; i < NUM_REFRESH_POSTING; i += 256) {
8605
                // Issue 256 REFRESH commands, waiting t_RFC between consecutive refreshes
8606
 
8607
#if (ENABLE_NON_DESTRUCTIVE_CALIB)                      
8608
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0xFF);
8609
#else
8610
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x07);
8611
#endif
8612
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, T_RFC_AFI);
8613
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_REFRESH_ALL);
8614
        }
8615
 
8616
        //USER Re-activate all banks
8617
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x00); // No need to wait between commands to activate different banks (since ACTIVATE is preceded by tRFC wait)
8618
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x0F); // Wait for ACTIVATE to complete
8619
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_ACTIVATE_0_AND_1_WAIT1);
8620
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_ACTIVATE_0_AND_1_WAIT2);
8621
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_ACTIVATE_0_AND_1);
8622
 
8623
        return 1;
8624
}
8625
#else
8626
alt_u32 mem_refresh_all_ranks (alt_u32 no_validate)
8627
{
8628
        return 1;
8629
}
8630
#endif
8631
#endif
8632
 
8633
//USER Configure various memory related parameters.
8634
 
8635
#if DDRX
8636
void mem_config (void)
8637
{
8638
        alt_u32 rlat, wlat;
8639
        alt_u32 rw_wl_nop_cycles;
8640
        alt_u32 max_latency;
8641
#if CALIBRATE_BIT_SLIPS
8642
        alt_u32 i;
8643
#endif  
8644
 
8645
        TRACE_FUNC();
8646
 
8647
        //USER read in write and read latency 
8648
 
8649
        wlat = IORD_32DIRECT (MEM_T_WL_ADD, 0);
8650
#if HARD_PHY
8651
        wlat += IORD_32DIRECT (DATA_MGR_MEM_T_ADD, 0); /* WL for hard phy does not include additive latency */
8652
 
8653
        #if DDR3 || DDR2
8654
                // YYONG: add addtional write latency to offset the address/command extra clock cycle
8655
                // YYONG: We change the AC mux setting causing AC to be delayed by one mem clock cycle
8656
                // YYONG: only do this for DDR3
8657
                wlat = wlat + 1;
8658
        #endif
8659
#endif
8660
 
8661
        rlat = IORD_32DIRECT (MEM_T_RL_ADD, 0);
8662
 
8663
        if (QUARTER_RATE_MODE) {
8664
                //USER In Quarter-Rate the WL-to-nop-cycles works like this
8665
                //USER 0,1     -> 0
8666
                //USER 2,3,4,5 -> 1
8667
                //USER 6,7,8,9 -> 2
8668
                //USER etc...
8669
                rw_wl_nop_cycles = (wlat + 6) / 4 - 1;
8670
        }
8671
        else if(HALF_RATE_MODE) {
8672
                //USER In Half-Rate the WL-to-nop-cycles works like this
8673
                //USER 0,1 -> -1
8674
                //USER 2,3 -> 0
8675
                //USER 4,5 -> 1
8676
                //USER etc...
8677
                if(wlat % 2)
8678
                {
8679
                        rw_wl_nop_cycles = ((wlat - 1) / 2) - 1;
8680
                }
8681
                else
8682
                {
8683
                        rw_wl_nop_cycles = (wlat / 2) - 1;
8684
                }
8685
        }
8686
        else {
8687
                rw_wl_nop_cycles = wlat - 2;
8688
#if LPDDR2
8689
                rw_wl_nop_cycles = rw_wl_nop_cycles + 1;
8690
#endif
8691
        }
8692
#if MULTIPLE_AFI_WLAT
8693
        for (i = 0; i < RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
8694
                gbl->rw_wl_nop_cycles_per_group[i] = rw_wl_nop_cycles;
8695
        }
8696
#endif  
8697
        gbl->rw_wl_nop_cycles = rw_wl_nop_cycles;
8698
 
8699
#if ARRIAV || CYCLONEV
8700
        //USER For AV/CV, lfifo is hardened and always runs at full rate
8701
        //USER so max latency in AFI clocks, used here, is correspondingly smaller
8702
        if (QUARTER_RATE_MODE) {
8703
                max_latency = (1<<MAX_LATENCY_COUNT_WIDTH)/4 - 1;
8704
        } else if (HALF_RATE_MODE) {
8705
                max_latency = (1<<MAX_LATENCY_COUNT_WIDTH)/2 - 1;
8706
        } else {
8707
                max_latency = (1<<MAX_LATENCY_COUNT_WIDTH)/1 - 1;
8708
        }
8709
#else
8710
        max_latency = (1<<MAX_LATENCY_COUNT_WIDTH) - 1;
8711
#endif          
8712
        //USER configure for a burst length of 8
8713
 
8714
        if (QUARTER_RATE_MODE) {
8715
                //USER write latency 
8716
                wlat = (wlat + 5) / 4 + 1;
8717
 
8718
                //USER set a pretty high read latency initially
8719
                gbl->curr_read_lat = (rlat + 1) / 4 + 8;
8720
        } else if (HALF_RATE_MODE) {
8721
                //USER write latency 
8722
                wlat = (wlat - 1) / 2 + 1;
8723
 
8724
                //USER set a pretty high read latency initially 
8725
                gbl->curr_read_lat = (rlat + 1) / 2 + 8;
8726
        } else {
8727
                //USER write latency 
8728
#if HARD_PHY
8729
                // Adjust Write Latency for Hard PHY
8730
                wlat = wlat + 1;
8731
#if LPDDR2
8732
                // Add another one in hard for LPDDR2 since this value is raw from controller
8733
                // assume tdqss is one
8734
                wlat = wlat + 1;
8735
#endif
8736
#endif
8737
 
8738
                //USER set a pretty high read latency initially 
8739
                gbl->curr_read_lat = rlat + 16;
8740
        }
8741
 
8742
        if (gbl->curr_read_lat > max_latency) {
8743
                gbl->curr_read_lat = max_latency;
8744
        }
8745
        IOWR_32DIRECT (PHY_MGR_PHY_RLAT, 0, gbl->curr_read_lat);
8746
 
8747
        //USER advertise write latency 
8748
        gbl->curr_write_lat = wlat;
8749
#if MULTIPLE_AFI_WLAT
8750
        for (i = 0; i < RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
8751
#if HARD_PHY            
8752
                IOWR_32DIRECT (PHY_MGR_AFI_WLAT, i*4, wlat - 2);
8753
#else
8754
                IOWR_32DIRECT (PHY_MGR_AFI_WLAT, i*4, wlat - 1);
8755
#endif
8756
        }
8757
#else
8758
#if HARD_PHY
8759
        IOWR_32DIRECT (PHY_MGR_AFI_WLAT, 0, wlat - 2);
8760
#else
8761
        IOWR_32DIRECT (PHY_MGR_AFI_WLAT, 0, wlat - 1);
8762
#endif
8763
#endif
8764
 
8765
        //USER initialize bit slips
8766
#if CALIBRATE_BIT_SLIPS
8767
        for (i = 0; i < RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
8768
                IOWR_32DIRECT (PHY_MGR_FR_SHIFT, i*4, 0);
8769
        }
8770
#endif  
8771
 
8772
 
8773
        mem_precharge_and_activate ();
8774
}
8775
#endif
8776
 
8777
#if QDRII || RLDRAMX
8778
void mem_config (void)
8779
{
8780
        alt_u32 wlat, nop_cycles, max_latency;
8781
 
8782
        TRACE_FUNC();
8783
 
8784
        max_latency = (1<<MAX_LATENCY_COUNT_WIDTH) - 1;
8785
 
8786
        if (QUARTER_RATE_MODE) {
8787
                // TODO_JCHOI: verify confirm
8788
                gbl->curr_read_lat = (IORD_32DIRECT (MEM_T_RL_ADD, 0) + 1) / 4 + 8;
8789
        } else if (HALF_RATE_MODE) {
8790
                gbl->curr_read_lat = (IORD_32DIRECT (MEM_T_RL_ADD, 0) + 1) / 2 + 8;
8791
        } else {
8792
                gbl->curr_read_lat = IORD_32DIRECT (MEM_T_RL_ADD, 0) + 16;
8793
        }
8794
        if (gbl->curr_read_lat > max_latency) {
8795
                gbl->curr_read_lat = max_latency;
8796
        }
8797
        IOWR_32DIRECT (PHY_MGR_PHY_RLAT, 0, gbl->curr_read_lat);
8798
 
8799
        if (RLDRAMX)
8800
        {
8801
                //USER read in write and read latency 
8802
                wlat = IORD_32DIRECT (MEM_T_WL_ADD, 0);
8803
 
8804
                if (QUARTER_RATE_MODE)
8805
                {
8806
                        // TODO_JCHOI Verify
8807
                        nop_cycles = ((wlat - 1) / 4) - 1;
8808
                }
8809
                else if (HALF_RATE_MODE)
8810
                {
8811
#if HR_DDIO_OUT_HAS_THREE_REGS
8812
                        nop_cycles = (wlat / 2) - 2;
8813
#else           
8814
        #if RLDRAM3
8815
                        // RLDRAM3 uses all AFI phases to issue commands
8816
                        nop_cycles = (wlat / 2) - 2;
8817
        #else
8818
                        nop_cycles = ((wlat + 1) / 2) - 2;
8819
        #endif
8820
#endif                  
8821
                }
8822
                else
8823
                {
8824
                        nop_cycles = wlat - 1;
8825
                }
8826
                gbl->rw_wl_nop_cycles = nop_cycles;
8827
        }
8828
}
8829
#endif
8830
 
8831
//USER Set VFIFO and LFIFO to instant-on settings in skip calibration mode
8832
 
8833
void mem_skip_calibrate (void)
8834
{
8835
        alt_u32 vfifo_offset;
8836
        alt_u32 i, j, r;
8837
#if HCX_COMPAT_MODE && DDR3
8838
        alt_u32 v;
8839
#if (RDIMM || LRDIMM)
8840
        alt_u32 increment = 2;
8841
#else
8842
        alt_u32 wlat = IORD_32DIRECT (PHY_MGR_MEM_T_WL, 0);
8843
        alt_u32 rlat = IORD_32DIRECT (PHY_MGR_MEM_T_RL, 0);
8844
        alt_u32 increment = rlat - wlat*2 + 1;
8845
#endif
8846
#endif
8847
 
8848
        TRACE_FUNC();
8849
 
8850
        // Need to update every shadow register set used by the interface       
8851
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
8852
 
8853
                // Strictly speaking this should be called once per group to make
8854
                // sure each group's delay chains are refreshed from the SCC register file,
8855
                // but since we're resetting all delay chains anyway, we can save some
8856
                // runtime by calling select_shadow_regs_for_update just once to switch rank.
8857
                select_shadow_regs_for_update(r, 0, 1);
8858
 
8859
                //USER Set output phase alignment settings appropriate for skip calibration
8860
                for (i = 0; i < RW_MGR_MEM_IF_READ_DQS_WIDTH; i++) {
8861
 
8862
#if STRATIXV || ARRIAV || CYCLONEV || ARRIAVGZ
8863
                        scc_mgr_set_dqs_en_phase(i, 0);
8864
#else
8865
#if IO_DLL_CHAIN_LENGTH == 6
8866
                        scc_mgr_set_dqs_en_phase(i, (IO_DLL_CHAIN_LENGTH >> 1) - 1);
8867
#else
8868
                        scc_mgr_set_dqs_en_phase(i, (IO_DLL_CHAIN_LENGTH >> 1));
8869
#endif
8870
#endif
8871
#if HCX_COMPAT_MODE && DDR3
8872
                        v = 0;
8873
                        for (j = 0; j < increment; j++) {
8874
                                rw_mgr_incr_vfifo(i, &v);
8875
                        }
8876
 
8877
#if IO_DLL_CHAIN_LENGTH == 6
8878
                        scc_mgr_set_dqdqs_output_phase(i, 6);
8879
#else
8880
                        scc_mgr_set_dqdqs_output_phase(i, 7);
8881
#endif
8882
#else
8883
        #if HCX_COMPAT_MODE
8884
                        // in this mode, write_clk doesn't always lead mem_ck by 90 deg, and so
8885
                        // the enhancement in case:33398 can't be applied.
8886
                        scc_mgr_set_dqdqs_output_phase(i, (IO_DLL_CHAIN_LENGTH - IO_DLL_CHAIN_LENGTH / 3));
8887
        #else
8888
                        // Case:33398
8889
                        //
8890
                        // Write data arrives to the I/O two cycles before write latency is reached (720 deg).
8891
                        //   -> due to bit-slip in a/c bus
8892
                        //   -> to allow board skew where dqs is longer than ck 
8893
                        //      -> how often can this happen!?
8894
                        //      -> can claim back some ptaps for high freq support if we can relax this, but i digress...
8895
                        //
8896
                        // The write_clk leads mem_ck by 90 deg
8897
                        // The minimum ptap of the OPA is 180 deg
8898
                        // Each ptap has (360 / IO_DLL_CHAIN_LENGH) deg of delay
8899
                        // The write_clk is always delayed by 2 ptaps
8900
                        //
8901
                        // Hence, to make DQS aligned to CK, we need to delay DQS by:
8902
                        //    (720 - 90 - 180 - 2 * (360 / IO_DLL_CHAIN_LENGTH))
8903
                        //
8904
                        // Dividing the above by (360 / IO_DLL_CHAIN_LENGTH) gives us the number of ptaps, which simplies to:
8905
                        //
8906
                        //    (1.25 * IO_DLL_CHAIN_LENGTH - 2)
8907
                        scc_mgr_set_dqdqs_output_phase(i, (1.25 * IO_DLL_CHAIN_LENGTH - 2));
8908
        #endif
8909
#endif  
8910
                }
8911
 
8912
                IOWR_32DIRECT (SCC_MGR_DQS_ENA, 0, 0xff);
8913
                IOWR_32DIRECT (SCC_MGR_DQS_IO_ENA, 0, 0xff);
8914
 
8915
                for (i = 0; i < RW_MGR_MEM_IF_WRITE_DQS_WIDTH; i++) {
8916
                        IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, i);
8917
                        IOWR_32DIRECT (SCC_MGR_DQ_ENA, 0, 0xff);
8918
                        IOWR_32DIRECT (SCC_MGR_DM_ENA, 0, 0xff);
8919
                }
8920
 
8921
#if USE_SHADOW_REGS             
8922
                //USER in shadow-register mode, SCC_UPDATE is done on a per-group basis
8923
                //USER unless we explicitly ask for a multicast via the group counter
8924
                IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, 0xFF);
8925
#endif          
8926
                IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8927
        }
8928
 
8929
#if ARRIAV || CYCLONEV
8930
        // Compensate for simulation model behaviour 
8931
        for (i = 0; i < RW_MGR_MEM_IF_READ_DQS_WIDTH; i++) {
8932
                scc_mgr_set_dqs_bus_in_delay(i, 10);
8933
                scc_mgr_load_dqs (i);
8934
        }
8935
        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
8936
#endif
8937
 
8938
#if ARRIAV || CYCLONEV
8939
        //ArriaV has hard FIFOs that can only be initialized by incrementing in sequencer
8940
        vfifo_offset = CALIB_VFIFO_OFFSET;
8941
        for (j = 0; j < vfifo_offset; j++) {
8942
                if(HARD_PHY) {
8943
                        IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_HARD_PHY, 0, 0xff);
8944
                } else {
8945
                        IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_FR, 0, 0xff);
8946
                }
8947
        }
8948
#else
8949
// Note, this is not currently supported; changing this might significantly
8950
// increase the size of the ROM
8951
#if SUPPORT_DYNAMIC_SKIP_CALIBRATE_ACTIONS
8952
        if ((DYNAMIC_CALIB_STEPS) & CALIB_IN_RTL_SIM) {
8953
                //USER VFIFO is reset to the correct settings in RTL simulation 
8954
        } else {
8955
                vfifo_offset = IORD_32DIRECT (PHY_MGR_CALIB_VFIFO_OFFSET, 0);
8956
 
8957
                if (QUARTER_RATE_MODE) {
8958
                        while (vfifo_offset > 3) {
8959
                                IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_QR, 0, 0xff);
8960
                                vfifo_offset -= 4;
8961
                        }
8962
 
8963
                        if (vfifo_offset == 3) {
8964
                                IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_FR_HR, 0, 0xff);
8965
                        } else if (vfifo_offset == 2) {
8966
                                IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_HR, 0, 0xff);
8967
                        } else if (vfifo_offset == 1) {
8968
                                IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_FR, 0, 0xff);
8969
                        }
8970
                } else {
8971
                        while (vfifo_offset > 1) {
8972
                                IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_HR, 0, 0xff);
8973
                                vfifo_offset -= 2;
8974
                        }
8975
 
8976
                        if (vfifo_offset == 1) {
8977
                                IOWR_32DIRECT (PHY_MGR_CMD_INC_VFIFO_FR, 0, 0xff);
8978
                        }
8979
                }
8980
        }
8981
#endif
8982
#endif
8983
 
8984
 
8985
        IOWR_32DIRECT (PHY_MGR_CMD_FIFO_RESET, 0, 0);
8986
 
8987
#if ARRIAV || CYCLONEV
8988
        // For ACV with hard lfifo, we get the skip-cal setting from generation-time constant
8989
        gbl->curr_read_lat = CALIB_LFIFO_OFFSET;
8990
#else
8991
        gbl->curr_read_lat = IORD_32DIRECT (PHY_MGR_CALIB_LFIFO_OFFSET, 0);
8992
#endif
8993
        IOWR_32DIRECT (PHY_MGR_PHY_RLAT, 0, gbl->curr_read_lat);
8994
}
8995
 
8996
 
8997
#if BFM_MODE
8998
void print_group_settings(alt_u32 group, alt_u32 dq_begin)
8999
{
9000
        int i;
9001
 
9002
        fprintf(bfm_gbl.outfp, "Group %lu (offset %lu)\n", group, dq_begin);
9003
 
9004
        fprintf(bfm_gbl.outfp, "Output:\n");
9005
        fprintf(bfm_gbl.outfp, "dqdqs_out_phase: %2u\n", READ_SCC_DQDQS_OUT_PHASE(group));
9006
        fprintf(bfm_gbl.outfp, "dqs_out1_delay:  %2u\n", READ_SCC_DQS_IO_OUT1_DELAY());
9007
        fprintf(bfm_gbl.outfp, "dqs_out2_delay:  %2u\n", READ_SCC_DQS_IO_OUT2_DELAY());
9008
        fprintf(bfm_gbl.outfp, "oct_out1_delay:  %2u\n", READ_SCC_OCT_OUT1_DELAY(group));
9009
        fprintf(bfm_gbl.outfp, "oct_out2_delay:  %2u\n", READ_SCC_OCT_OUT2_DELAY(group));
9010
        fprintf(bfm_gbl.outfp, "dm_out1:         ");
9011
        for (i = 0; i < RW_MGR_NUM_DM_PER_WRITE_GROUP; i++) {
9012
                fprintf(bfm_gbl.outfp, "%2u ", READ_SCC_DM_IO_OUT1_DELAY(i));
9013
        }
9014
        fprintf(bfm_gbl.outfp, "\n");
9015
        fprintf(bfm_gbl.outfp, "dm_out2:         ");
9016
        for (i = 0; i < RW_MGR_NUM_DM_PER_WRITE_GROUP; i++) {
9017
                fprintf(bfm_gbl.outfp, "%2u ", READ_SCC_DM_IO_OUT2_DELAY(i));
9018
        }
9019
        fprintf(bfm_gbl.outfp, "\n");
9020
        fprintf(bfm_gbl.outfp, "dq_out1:         ");
9021
        for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
9022
                fprintf(bfm_gbl.outfp, "%2u ", READ_SCC_DQ_OUT1_DELAY(i));
9023
        }
9024
        fprintf(bfm_gbl.outfp, "\n");
9025
        fprintf(bfm_gbl.outfp, "dq_out2:         ");
9026
        for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
9027
                fprintf(bfm_gbl.outfp, "%2u ", READ_SCC_DQ_OUT2_DELAY(i));
9028
        }
9029
        fprintf(bfm_gbl.outfp, "\n");
9030
 
9031
        fprintf(bfm_gbl.outfp, "Input:\n");
9032
        fprintf(bfm_gbl.outfp, "dqs_en_phase:    %2u\n", READ_SCC_DQS_EN_PHASE(group));
9033
        fprintf(bfm_gbl.outfp, "dqs_en_delay:    %2u\n", READ_SCC_DQS_EN_DELAY(group));
9034
        fprintf(bfm_gbl.outfp, "dqs_in_delay:    %2u\n", READ_SCC_DQS_IN_DELAY(group));
9035
        fprintf(bfm_gbl.outfp, "dq_in:           ");
9036
        for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
9037
                fprintf(bfm_gbl.outfp, "%2u ", READ_SCC_DQ_IN_DELAY(i));
9038
        }
9039
        fprintf(bfm_gbl.outfp, "\n");
9040
 
9041
        fprintf(bfm_gbl.outfp, "\n");
9042
 
9043
        fflush(bfm_gbl.outfp);
9044
}
9045
 
9046
#endif
9047
 
9048
#if RUNTIME_CAL_REPORT
9049
void print_report(alt_u32 pass)
9050
{
9051
        RPRINT("Calibration Summary");
9052
        char *stage_name, *substage_name;
9053
 
9054
        if(pass) {
9055
                RPRINT("Calibration Passed");
9056
                RPRINT("FOM IN  = %lu", gbl->fom_in);
9057
                RPRINT("FOM OUT = %lu", gbl->fom_out);
9058
        } else {
9059
                RPRINT("Calibration Failed");
9060
                switch (gbl->error_stage) {
9061
                        case CAL_STAGE_NIL:
9062
                                stage_name = "NIL";
9063
                                substage_name = "NIL";
9064
                        case CAL_STAGE_VFIFO:
9065
                                stage_name = "VFIFO";
9066
                                switch (gbl->error_substage) {
9067
                                        case CAL_SUBSTAGE_GUARANTEED_READ:
9068
                                                substage_name = "GUARANTEED READ";
9069
                                                break;
9070
                                        case CAL_SUBSTAGE_DQS_EN_PHASE:
9071
                                                substage_name = "DQS ENABLE PHASE";
9072
                                                break;
9073
                                        case CAL_SUBSTAGE_VFIFO_CENTER:
9074
                                                substage_name = "Read Per-Bit Deskew";
9075
                                                break;
9076
                                        default:
9077
                                                substage_name = "NIL";
9078
                                }
9079
                                break;
9080
                        case CAL_STAGE_WLEVEL:
9081
                                stage_name = "WRITE LEVELING";
9082
                                switch (gbl->error_substage) {
9083
                                        case CAL_SUBSTAGE_WORKING_DELAY:
9084
                                                substage_name = "DQS Window Left Edge"; //need a more descriptive name
9085
                                                break;
9086
                                        case CAL_SUBSTAGE_LAST_WORKING_DELAY:
9087
                                                substage_name = "DQS Window Right Edge";
9088
                                                break;
9089
                                        case CAL_SUBSTAGE_WLEVEL_COPY:
9090
                                                substage_name = "WRITE LEVEL COPY";
9091
                                                break;
9092
                                        default:
9093
                                                substage_name = "NIL";
9094
                                }
9095
                                break;
9096
                        case CAL_STAGE_LFIFO:
9097
                                stage_name = "LFIFO";
9098
                                substage_name = "READ LATENCY";
9099
                                break;
9100
                        case CAL_STAGE_WRITES:
9101
                                stage_name = "WRITES";
9102
                                substage_name = "Write Per-Bit Deskew";
9103
                                break;
9104
                        case CAL_STAGE_FULLTEST:
9105
                                stage_name = "FULL TEST";
9106
                                substage_name = "FULL TEST";
9107
                                break;
9108
                        case CAL_STAGE_REFRESH:
9109
                                stage_name = "REFRESH";
9110
                                substage_name = "REFRESH";
9111
                                break;
9112
                        case CAL_STAGE_CAL_SKIPPED:
9113
                                stage_name = "SKIP CALIBRATION"; //hw: is this needed
9114
                                substage_name = "SKIP CALIBRATION";
9115
                                break;
9116
                        case CAL_STAGE_CAL_ABORTED:
9117
                                stage_name = "ABORTED CALIBRATION"; //hw: hum???
9118
                                substage_name = "ABORTED CALIBRATION";
9119
                                break;
9120
                        case CAL_STAGE_VFIFO_AFTER_WRITES:
9121
                                stage_name = "READ Fine-tuning";
9122
                                switch (gbl->error_substage) {
9123
                                        case CAL_SUBSTAGE_GUARANTEED_READ:
9124
                                                substage_name = "GUARANTEED READ";
9125
                                                break;
9126
                                        case CAL_SUBSTAGE_DQS_EN_PHASE:
9127
                                                substage_name = "DQS ENABLE PHASE";
9128
                                                break;
9129
                                        case CAL_SUBSTAGE_VFIFO_CENTER:
9130
                                                substage_name = "VFIFO CENTER";
9131
                                                break;
9132
                                        default:
9133
                                                substage_name = "NIL";
9134
                                }
9135
                                break;
9136
                        default:
9137
                                stage_name = "NIL";
9138
                                substage_name = "NIL";
9139
                }
9140
                RPRINT("Error Stage   : %lu - %s", gbl->error_stage, stage_name);
9141
                RPRINT("Error Substage: %lu - %s", gbl->error_substage, substage_name);
9142
                RPRINT("Error Group   : %lu", gbl->error_group);
9143
        }
9144
}
9145
#endif //RUNTIME_CAL_REPORT
9146
 
9147
//USER Memory calibration entry point
9148
 
9149
alt_u32 mem_calibrate (void)
9150
{
9151
        alt_u32 i;
9152
        alt_u32 rank_bgn, sr;
9153
        alt_u32 write_group, write_test_bgn;
9154
        alt_u32 read_group, read_test_bgn;
9155
        alt_u32 run_groups, current_run;
9156
        alt_u32 failing_groups = 0;
9157
        alt_u32 group_failed = 0;
9158
        alt_u32 sr_failed = 0;
9159
 
9160
        TRACE_FUNC();
9161
 
9162
        // Initialize the data settings
9163
        DPRINT(1, "Preparing to init data");
9164
#if ENABLE_TCL_DEBUG
9165
        tclrpt_initialize_data();
9166
#endif
9167
        DPRINT(1, "Init complete");
9168
 
9169
        gbl->error_substage = CAL_SUBSTAGE_NIL;
9170
        gbl->error_stage = CAL_STAGE_NIL;
9171
        gbl->error_group = 0xff;
9172
        gbl->fom_in = 0;
9173
        gbl->fom_out = 0;
9174
 
9175
        TCLRPT_SET(debug_summary_report->cal_read_latency, 0);
9176
        TCLRPT_SET(debug_summary_report->cal_write_latency, 0);
9177
 
9178
        mem_config ();
9179
 
9180
        if(ARRIAV || CYCLONEV) {
9181
                alt_u32 bypass_mode = (HARD_PHY) ? 0x1 : 0x0;
9182
                for (i = 0; i < RW_MGR_MEM_IF_READ_DQS_WIDTH; i++) {
9183
                        IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, i);
9184
                        scc_set_bypass_mode (i, bypass_mode);
9185
                }
9186
        }
9187
 
9188
        if (((DYNAMIC_CALIB_STEPS) & CALIB_SKIP_ALL) == CALIB_SKIP_ALL) {
9189
                //USER Set VFIFO and LFIFO to instant-on settings in skip calibration mode 
9190
 
9191
                mem_skip_calibrate ();
9192
        } else {
9193
                for (i = 0; i < NUM_CALIB_REPEAT; i++) {
9194
 
9195
                        //USER Zero all delay chain/phase settings for all groups and all shadow register sets
9196
                        scc_mgr_zero_all ();
9197
 
9198
#if ENABLE_SUPER_QUICK_CALIBRATION
9199
                        for (write_group = 0, write_test_bgn = 0; write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH; write_group++, write_test_bgn += RW_MGR_MEM_DQ_PER_WRITE_DQS)
9200
                        {
9201
                                IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, write_group);
9202
                                scc_mgr_zero_group (write_group, write_test_bgn, 0);
9203
                        }
9204
#endif
9205
 
9206
                        run_groups = ~param->skip_groups;
9207
 
9208
                        for (write_group = 0, write_test_bgn = 0; write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH; write_group++, write_test_bgn += RW_MGR_MEM_DQ_PER_WRITE_DQS)
9209
                        {
9210
                                // Initialized the group failure
9211
                                group_failed = 0;
9212
 
9213
                                // Mark the group as being attempted for calibration
9214
#if ENABLE_TCL_DEBUG
9215
                                tclrpt_set_group_as_calibration_attempted(write_group);
9216
#endif
9217
 
9218
#if RLDRAMX || QDRII
9219
                                //Note:
9220
                                //  It seems that with rldram and qdr vfifo starts at max (not sure for ddr)
9221
                                //  also not sure if max is really vfifo_size-1 or vfifo_size
9222
                                BFM_GBL_SET(vfifo_idx,VFIFO_SIZE-1);
9223
#else
9224
                                BFM_GBL_SET(vfifo_idx,0);
9225
#endif
9226
                                current_run = run_groups & ((1 << RW_MGR_NUM_DQS_PER_WRITE_GROUP) - 1);
9227
                                run_groups = run_groups >> RW_MGR_NUM_DQS_PER_WRITE_GROUP;
9228
 
9229
                                if (current_run == 0)
9230
                                {
9231
                                        continue;
9232
                                }
9233
 
9234
                                IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, write_group);
9235
#if !ENABLE_SUPER_QUICK_CALIBRATION
9236
                                scc_mgr_zero_group (write_group, write_test_bgn, 0);
9237
#endif
9238
 
9239
                                for (read_group = write_group * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH, read_test_bgn = 0;
9240
                                     read_group < (write_group + 1) * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH && group_failed == 0;
9241
                                     read_group++, read_test_bgn += RW_MGR_MEM_DQ_PER_READ_DQS) {
9242
 
9243
                                        //USER Calibrate the VFIFO 
9244
                                        if (!((STATIC_CALIB_STEPS) & CALIB_SKIP_VFIFO)) {
9245
                                                if (!rw_mgr_mem_calibrate_vfifo (read_group, read_test_bgn)) {
9246
                                                        group_failed = 1;
9247
 
9248
                                                        if (!(gbl->phy_debug_mode_flags & PHY_DEBUG_SWEEP_ALL_GROUPS)) {
9249
                                                                return 0;
9250
                                                        }
9251
                                                }
9252
                                        }
9253
                                }
9254
 
9255
                                //USER level writes (or align DK with CK for RLDRAMX) 
9256
                                if (group_failed == 0)
9257
                                {
9258
                                        if ((DDRX || RLDRAMII) && !(ARRIAV || CYCLONEV))
9259
                                        {
9260
                                                if (!((STATIC_CALIB_STEPS) & CALIB_SKIP_WLEVEL)) {
9261
                                                        if (!rw_mgr_mem_calibrate_wlevel (write_group, write_test_bgn)) {
9262
                                                                group_failed = 1;
9263
 
9264
                                                                if (!(gbl->phy_debug_mode_flags & PHY_DEBUG_SWEEP_ALL_GROUPS)) {
9265
                                                                        return 0;
9266
                                                                }
9267
                                                        }
9268
                                                }
9269
                                        }
9270
                                }
9271
 
9272
                                //USER Calibrate the output side 
9273
                                if (group_failed == 0)
9274
                                {
9275
                                        for (rank_bgn = 0, sr = 0; rank_bgn < RW_MGR_MEM_NUMBER_OF_RANKS; rank_bgn += NUM_RANKS_PER_SHADOW_REG, ++sr) {
9276
                                                sr_failed = 0;
9277
                                                if (!((STATIC_CALIB_STEPS) & CALIB_SKIP_WRITES)) {
9278
                                                        if ((STATIC_CALIB_STEPS) & CALIB_SKIP_DELAY_SWEEPS) {
9279
                                                                //USER not needed in quick mode!
9280
                                                        } else {
9281
                                                                //USER Determine if this set of ranks should be skipped entirely
9282
                                                                if (! param->skip_shadow_regs[sr]) {
9283
 
9284
                                                                        //USER Select shadow register set
9285
                                                                        select_shadow_regs_for_update(rank_bgn, write_group, 1);
9286
 
9287
                                                                        if (!rw_mgr_mem_calibrate_writes (rank_bgn, write_group, write_test_bgn)) {
9288
                                                                                sr_failed = 1;
9289
                                                                                if (!(gbl->phy_debug_mode_flags & PHY_DEBUG_SWEEP_ALL_GROUPS)) {
9290
                                                                                        return 0;
9291
                                                                                }
9292
                                                                        }
9293
                                                                }
9294
                                                        }
9295
                                                }
9296
                                                if(sr_failed == 0) {
9297
                                                        TCLRPT_SET(debug_cal_report->cal_status_per_group[sr][write_group].error_stage, CAL_STAGE_NIL);
9298
                                                } else {
9299
                                                        group_failed = 1;
9300
                                                }
9301
                                        }
9302
                                }
9303
 
9304
#if READ_AFTER_WRITE_CALIBRATION                                
9305
                                if (group_failed == 0)
9306
                                {
9307
                                        for (read_group = write_group * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH, read_test_bgn = 0;
9308
                                                 read_group < (write_group + 1) * RW_MGR_MEM_IF_READ_DQS_WIDTH / RW_MGR_MEM_IF_WRITE_DQS_WIDTH && group_failed == 0;
9309
                                                 read_group++, read_test_bgn += RW_MGR_MEM_DQ_PER_READ_DQS) {
9310
 
9311
                                                if (!((STATIC_CALIB_STEPS) & CALIB_SKIP_WRITES)) {
9312
                                                        if (!rw_mgr_mem_calibrate_vfifo_end (read_group, read_test_bgn)) {
9313
                                                                group_failed = 1;
9314
 
9315
                                                                if (!(gbl->phy_debug_mode_flags & PHY_DEBUG_SWEEP_ALL_GROUPS)) {
9316
                                                                        return 0;
9317
                                                                }
9318
                                                        }
9319
                                                }
9320
                                        }
9321
                                }
9322
#endif                          
9323
 
9324
                                if (group_failed == 0)
9325
                                {
9326
 
9327
#if BFM_MODE
9328
 
9329
                                        // TODO: should just update global BFM structure with all data
9330
                                        // and print all out at the end
9331
                                        print_group_settings(write_group, write_test_bgn);
9332
#endif
9333
 
9334
#if STATIC_IN_RTL_SIM
9335
#if ENABLE_TCL_DEBUG && BFM_MODE
9336
        tclrpt_populate_fake_margin_data();
9337
#endif
9338
#else
9339
#if ENABLE_TCL_DEBUG
9340
                                if (gbl->phy_debug_mode_flags & PHY_DEBUG_ENABLE_MARGIN_RPT)
9341
                                {
9342
                                        // Run margining
9343
                                        for (rank_bgn = 0, sr = 0; rank_bgn < RW_MGR_MEM_NUMBER_OF_RANKS; rank_bgn += NUM_RANKS_PER_SHADOW_REG, ++sr) {
9344
 
9345
                                                //USER Determine if this set of ranks should be skipped entirely
9346
                                                if (! param->skip_shadow_regs[sr]) {
9347
 
9348
                                                        //USER Select shadow register set
9349
                                                        select_shadow_regs_for_update(rank_bgn, write_group, 1);
9350
 
9351
                                                        run_dq_margining(rank_bgn, write_group);
9352
#if DDRX
9353
                                                                if (RW_MGR_NUM_TRUE_DM_PER_WRITE_GROUP > 0)
9354
                                                                {
9355
                                                                        run_dm_margining(rank_bgn, write_group);
9356
                                                                }
9357
#endif
9358
#if QDRII
9359
                                                                run_dm_margining(rank_bgn, write_group);
9360
#endif
9361
#if RLDRAMX
9362
                                                                if (is_write_group_enabled_for_dm(write_group))
9363
                                                                {
9364
                                                                        run_dm_margining(rank_bgn, write_group);
9365
                                                                }
9366
#endif
9367
                                                        }
9368
                                                }
9369
                                        }
9370
#endif
9371
#endif
9372
                                }
9373
 
9374
                                if (group_failed != 0)
9375
                                {
9376
                                        failing_groups++;
9377
                                }
9378
 
9379
#if ENABLE_NON_DESTRUCTIVE_CALIB
9380
                                if (gbl->phy_debug_mode_flags & PHY_DEBUG_ENABLE_NON_DESTRUCTIVE_CALIBRATION) {
9381
                                  // USER Refresh the memory
9382
                                  if (!mem_refresh_all_ranks(0)) {
9383
                                        set_failing_group_stage(write_group, CAL_STAGE_REFRESH, CAL_SUBSTAGE_REFRESH);
9384
                                        TCLRPT_SET(debug_cal_report->cal_status_per_group[curr_shadow_reg][write_group].error_stage, CAL_STAGE_REFRESH);
9385
                                        return 0;
9386
                                  }
9387
                                }
9388
#endif
9389
 
9390
#if ENABLE_NON_DESTRUCTIVE_CALIB
9391
                                // USER Check if synchronous abort has been asserted
9392
                                if (abort_cal) {
9393
                                        set_failing_group_stage(write_group, CAL_STAGE_CAL_ABORTED, CAL_SUBSTAGE_NIL);
9394
                                        return 0;
9395
                                }
9396
#endif
9397
                        }
9398
 
9399
                        // USER If there are any failing groups then report the failure
9400
                        if (failing_groups != 0)
9401
                        {
9402
                                return 0;
9403
                        }
9404
 
9405
                        //USER Calibrate the LFIFO 
9406
                        if (!((STATIC_CALIB_STEPS) & CALIB_SKIP_LFIFO)) {
9407
                                //USER If we're skipping groups as part of debug, don't calibrate LFIFO
9408
                                if (param->skip_groups == 0)
9409
                                {
9410
                                        if (!rw_mgr_mem_calibrate_lfifo ()) {
9411
                                                return 0;
9412
                                        }
9413
                                }
9414
                        }
9415
                }
9416
        }
9417
 
9418
        TCLRPT_SET(debug_summary_report->cal_write_latency, IORD_32DIRECT (MEM_T_WL_ADD, 0));
9419
        if (QUARTER_RATE == 1) {
9420
                // The read latency is in terms of AFI cycles so we multiply by 4 in quarter
9421
                // rate to get the memory cycles.
9422
                TCLRPT_SET(debug_summary_report->cal_read_latency, gbl->curr_read_lat * 4);
9423
        }
9424
        else if (HALF_RATE == 1) {
9425
                // The read latency is in terms of AFI cycles so we multiply by 2 in half
9426
                // rate to get the memory cycles.
9427
                TCLRPT_SET(debug_summary_report->cal_read_latency, gbl->curr_read_lat * 2);
9428
        }
9429
        else {
9430
                TCLRPT_SET(debug_summary_report->cal_read_latency, gbl->curr_read_lat);
9431
        }
9432
 
9433
 
9434
        //USER Do not remove this line as it makes sure all of our decisions have been applied
9435
        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
9436
        return 1;
9437
}
9438
#if ENABLE_NON_DES_CAL
9439
alt_u32 run_mem_calibrate(alt_u32 non_des_mode) {
9440
 
9441
#else
9442
alt_u32 run_mem_calibrate(void) {
9443
#endif
9444
 
9445
        alt_u32 pass;
9446
        alt_u32 debug_info;
9447
 
9448
        // Initialize the debug status to show that calibration has started.
9449
        // This should occur before anything else
9450
#if ENABLE_TCL_DEBUG
9451
        tclrpt_initialize_debug_status();
9452
 
9453
        // Set that calibration has started
9454
        debug_data->status |= 1 << DEBUG_STATUS_CALIBRATION_STARTED;
9455
#endif
9456
   // Reset pass/fail status shown on afi_cal_success/fail
9457
   IOWR_32DIRECT (PHY_MGR_CAL_STATUS, 0, PHY_MGR_CAL_RESET);
9458
 
9459
   TRACE_FUNC();
9460
 
9461
        BFM_STAGE("calibrate");
9462
#if USE_DQS_TRACKING
9463
#if HHP_HPS
9464
        //stop tracking manger
9465
        alt_u32 ctrlcfg = IORD_32DIRECT(CTRL_CONFIG_REG,0);
9466
 
9467
        IOWR_32DIRECT(CTRL_CONFIG_REG, 0, ctrlcfg & 0xFFBFFFFF);
9468
#else
9469
        // we need to stall tracking
9470
        IOWR_32DIRECT (TRK_STALL, 0, TRK_STALL_REQ_VAL);
9471
        // busy wait for tracking manager to ack stall request
9472
        while (IORD_32DIRECT (TRK_STALL, 0) != TRK_STALL_ACKED_VAL) {
9473
        }
9474
#endif
9475
#endif
9476
 
9477
    initialize();
9478
 
9479
#if ENABLE_NON_DESTRUCTIVE_CALIB
9480
        if (gbl->phy_debug_mode_flags & PHY_DEBUG_ENABLE_NON_DESTRUCTIVE_CALIBRATION) {
9481
                if (no_init) {
9482
                        rw_mgr_mem_initialize_no_init();
9483
                        // refresh is done as part of rw_mgr_mem_initialize_no_init()
9484
                } else {
9485
                        rw_mgr_mem_initialize ();
9486
                        mem_refresh_all_ranks(1);
9487
                }
9488
        } else {
9489
                rw_mgr_mem_initialize ();
9490
        }
9491
#else
9492
#if ENABLE_NON_DES_CAL
9493
        if (non_des_mode)
9494
                rw_mgr_mem_initialize_no_init();
9495
        else
9496
                rw_mgr_mem_initialize ();
9497
 
9498
#else
9499
        rw_mgr_mem_initialize ();
9500
#endif  
9501
#endif
9502
 
9503
 
9504
#if ENABLE_BRINGUP_DEBUGGING
9505
        do_bringup_test();
9506
#endif
9507
 
9508
        pass = mem_calibrate ();
9509
 
9510
#if ENABLE_NON_DESTRUCTIVE_CALIB
9511
        if( (gbl->phy_debug_mode_flags & PHY_DEBUG_ENABLE_NON_DESTRUCTIVE_CALIBRATION) ) {
9512
          if (!mem_refresh_all_ranks(0)) {
9513
                set_failing_group_stage(RW_MGR_MEM_IF_WRITE_DQS_WIDTH, CAL_STAGE_REFRESH, CAL_SUBSTAGE_REFRESH);
9514
                pass = 0;
9515
          }
9516
        } else {
9517
          mem_precharge_and_activate ();
9518
        }
9519
#else
9520
        mem_precharge_and_activate ();
9521
#endif
9522
 
9523
        //pe_checkout_pattern();
9524
 
9525
        IOWR_32DIRECT (PHY_MGR_CMD_FIFO_RESET, 0, 0);
9526
 
9527
        if (pass) {
9528
                TCLRPT_SET(debug_summary_report->error_stage, CAL_STAGE_NIL);
9529
 
9530
 
9531
                BFM_STAGE("handoff");
9532
 
9533
#ifdef TEST_SIZE
9534
                if (!check_test_mem(0)) {
9535
                        gbl->error_stage = 0x92;
9536
                        gbl->error_group = 0x92;
9537
                }
9538
#endif
9539
        }
9540
 
9541
#if TRACKING_ERROR_TEST
9542
        if (IORD_32DIRECT(REG_FILE_TRK_SAMPLE_CHECK, 0) == 0xFE) {
9543
                poll_for_sample_check();
9544
        }
9545
#endif
9546
 
9547
        //USER Handoff 
9548
#if ENABLE_NON_DES_CAL
9549
 
9550
        if (non_des_mode)
9551
        {
9552
                alt_u32 took_too_long = 0;
9553
                IOWR_32DIRECT (RW_MGR_ENABLE_REFRESH, 0, 0);  // Disable refresh engine   
9554
                took_too_long = IORD_32DIRECT (RW_MGR_ENABLE_REFRESH, 0);
9555
 
9556
                if (took_too_long != 0)
9557
                {
9558
                        pass = 0;  // force a failure     
9559
                        set_failing_group_stage(RW_MGR_MEM_IF_WRITE_DQS_WIDTH, CAL_STAGE_REFRESH, CAL_SUBSTAGE_REFRESH);
9560
                }
9561
        }
9562
#endif  
9563
 
9564
 
9565
        //USER Don't return control of the PHY back to AFI when in debug mode
9566
        if ((gbl->phy_debug_mode_flags & PHY_DEBUG_IN_DEBUG_MODE) == 0) {
9567
                rw_mgr_mem_handoff ();
9568
 
9569
#if HARD_PHY
9570
                // In Hard PHY this is a 2-bit control:
9571
                // 0: AFI Mux Select
9572
                // 1: DDIO Mux Select
9573
                IOWR_32DIRECT (PHY_MGR_MUX_SEL, 0, 0x2);
9574
#else
9575
                IOWR_32DIRECT (PHY_MGR_MUX_SEL, 0, 0);
9576
#endif
9577
        }
9578
#if USE_DQS_TRACKING
9579
#if HHP_HPS
9580
        IOWR_32DIRECT(CTRL_CONFIG_REG, 0, ctrlcfg);
9581
#else
9582
        // clear tracking stall flags
9583
        IOWR_32DIRECT (TRK_STALL, 0, 0);
9584
#endif  
9585
#endif
9586
 
9587
#if FAKE_CAL_FAIL
9588
   if (0) {
9589
#else
9590
        if (pass) {
9591
#endif
9592
                IPRINT("CALIBRATION PASSED");
9593
 
9594
                gbl->fom_in /= 2;
9595
                gbl->fom_out /= 2;
9596
 
9597
                if (gbl->fom_in > 0xff) {
9598
                        gbl->fom_in = 0xff;
9599
                }
9600
 
9601
                if (gbl->fom_out > 0xff) {
9602
                        gbl->fom_out = 0xff;
9603
                }
9604
 
9605
#if BFM_MODE
9606
                // duplicated because we want it after updating gbl, but before phy
9607
                // is informed that calibration has completed
9608
                print_gbl();
9609
                fini_outfile();
9610
#endif
9611
 
9612
                // Update the FOM in the register file
9613
                debug_info = gbl->fom_in;
9614
                debug_info |= gbl->fom_out << 8;
9615
                IOWR_32DIRECT (REG_FILE_FOM, 0, debug_info);
9616
 
9617
                IOWR_32DIRECT (PHY_MGR_CAL_DEBUG_INFO, 0, debug_info);
9618
                IOWR_32DIRECT (PHY_MGR_CAL_STATUS, 0, PHY_MGR_CAL_SUCCESS);
9619
 
9620
        } else {
9621
 
9622
                IPRINT("CALIBRATION FAILED");
9623
 
9624
                debug_info = gbl->error_stage;
9625
                debug_info |= gbl->error_substage << 8;
9626
                debug_info |= gbl->error_group << 16;
9627
 
9628
#if BFM_MODE
9629
                // duplicated because we want it after updating gbl, but before phy
9630
                // is informed that calibration has completed
9631
                print_gbl();
9632
                fini_outfile();
9633
#endif
9634
 
9635
                IOWR_32DIRECT (REG_FILE_FAILING_STAGE, 0, debug_info);
9636
                IOWR_32DIRECT (PHY_MGR_CAL_DEBUG_INFO, 0, debug_info);
9637
                IOWR_32DIRECT (PHY_MGR_CAL_STATUS, 0, PHY_MGR_CAL_FAIL);
9638
 
9639
                // Update the failing group/stage in the register file
9640
                debug_info = gbl->error_stage;
9641
                debug_info |= gbl->error_substage << 8;
9642
                debug_info |= gbl->error_group << 16;
9643
                IOWR_32DIRECT (REG_FILE_FAILING_STAGE, 0, debug_info);
9644
 
9645
        }
9646
 
9647
#if RUNTIME_CAL_REPORT
9648
        print_report(pass);
9649
#endif
9650
 
9651
 
9652
        // Mark the reports as being ready to read
9653
        TCLRPT_SET(debug_summary_report->report_flags, debug_summary_report->report_flags |= DEBUG_REPORT_STATUS_REPORT_READY);
9654
        TCLRPT_SET(debug_cal_report->report_flags, debug_cal_report->report_flags |= DEBUG_REPORT_STATUS_REPORT_READY);
9655
        TCLRPT_SET(debug_margin_report->report_flags, debug_margin_report->report_flags |= DEBUG_REPORT_STATUS_REPORT_READY);
9656
 
9657
        // Set the debug status to show that calibration has ended.
9658
        // This should occur after everything else
9659
#if ENABLE_TCL_DEBUG
9660
                debug_data->status |= 1 << DEBUG_STATUS_CALIBRATION_ENDED;
9661
#endif
9662
        return pass;
9663
 
9664
}
9665
 
9666
#if HCX_COMPAT_MODE || ENABLE_INST_ROM_WRITE
9667
void hc_initialize_rom_data(void)
9668
{
9669
        alt_u32 i;
9670
 
9671
        for(i = 0; i < inst_rom_init_size; i++)
9672
        {
9673
                alt_u32 data = inst_rom_init[i];
9674
                IOWR_32DIRECT (RW_MGR_INST_ROM_WRITE, (i << 2), data);
9675
        }
9676
 
9677
        for(i = 0; i < ac_rom_init_size; i++)
9678
        {
9679
                alt_u32 data = ac_rom_init[i];
9680
                IOWR_32DIRECT (RW_MGR_AC_ROM_WRITE, (i << 2), data);
9681
        }
9682
}
9683
#endif
9684
 
9685
#if BFM_MODE
9686
void init_outfile(void)
9687
{
9688
        const char *filename = getenv("SEQ_OUT_FILE");
9689
 
9690
        if (filename == NULL) {
9691
                filename = "sequencer.out";
9692
        }
9693
 
9694
        if ((bfm_gbl.outfp = fopen(filename, "w")) == NULL) {
9695
                printf("ERROR: Failed to open %s for writing; using stdout\n", filename);
9696
                bfm_gbl.outfp = stdout;
9697
        }
9698
 
9699
        fprintf(bfm_gbl.outfp, "%s%s %s ranks=%lu cs/dimm=%lu dq/dqs=%lu,%lu vg/dqs=%lu,%lu dqs=%lu,%lu dq=%lu dm=%lu "
9700
                "ptap_delay=%lu dtap_delay=%lu dtap_dqsen_delay=%lu dll=%lu\n",
9701
                RDIMM ? "r" : (LRDIMM ? "l" : ""),
9702
                DDR2 ? "DDR2" : (DDR3 ? "DDR3" : (QDRII ? "QDRII" : (RLDRAMII ? "RLDRAMII" : (RLDRAM3 ? "RLDRAM3" : "??PROTO??")))),
9703
                FULL_RATE ? "FR" : (HALF_RATE ? "HR" : (QUARTER_RATE ? "QR" : "??RATE??")),
9704
                RW_MGR_MEM_NUMBER_OF_RANKS,
9705
                RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM,
9706
                RW_MGR_MEM_DQ_PER_READ_DQS,
9707
                RW_MGR_MEM_DQ_PER_WRITE_DQS,
9708
                RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS,
9709
                RW_MGR_MEM_VIRTUAL_GROUPS_PER_WRITE_DQS,
9710
                RW_MGR_MEM_IF_READ_DQS_WIDTH,
9711
                RW_MGR_MEM_IF_WRITE_DQS_WIDTH,
9712
                RW_MGR_MEM_DATA_WIDTH,
9713
                RW_MGR_MEM_DATA_MASK_WIDTH,
9714
                IO_DELAY_PER_OPA_TAP,
9715
                IO_DELAY_PER_DCHAIN_TAP,
9716
                IO_DELAY_PER_DQS_EN_DCHAIN_TAP,
9717
                IO_DLL_CHAIN_LENGTH);
9718
        fprintf(bfm_gbl.outfp, "max values: en_p=%lu dqdqs_p=%lu en_d=%lu dqs_in_d=%lu io_in_d=%lu io_out1_d=%lu io_out2_d=%lu "
9719
                "dqs_in_reserve=%lu dqs_out_reserve=%lu\n",
9720
                IO_DQS_EN_PHASE_MAX,
9721
                IO_DQDQS_OUT_PHASE_MAX,
9722
                IO_DQS_EN_DELAY_MAX,
9723
                IO_DQS_IN_DELAY_MAX,
9724
                IO_IO_IN_DELAY_MAX,
9725
                IO_IO_OUT1_DELAY_MAX,
9726
                IO_IO_OUT2_DELAY_MAX,
9727
                IO_DQS_IN_RESERVE,
9728
                IO_DQS_OUT_RESERVE);
9729
        fprintf(bfm_gbl.outfp, "\n");
9730
        // repeat these in a format that can be easily parsed
9731
        fprintf(bfm_gbl.outfp, "ptap_delay: %lu\n", IO_DELAY_PER_OPA_TAP);
9732
        fprintf(bfm_gbl.outfp, "dtap_delay: %lu\n", IO_DELAY_PER_DCHAIN_TAP);
9733
        fprintf(bfm_gbl.outfp, "ptap_per_cycle: %lu\n", IO_DLL_CHAIN_LENGTH);
9734
        fprintf(bfm_gbl.outfp, "ptap_max: %lu\n", IO_DQDQS_OUT_PHASE_MAX);
9735
        fprintf(bfm_gbl.outfp, "dtap_max: %lu\n", IO_IO_OUT1_DELAY_MAX);
9736
        fprintf(bfm_gbl.outfp, "vfifo_size: %lu\n", VFIFO_SIZE);
9737
}
9738
 
9739
void fini_outfile(void)
9740
{
9741
        if (bfm_gbl.outfp != stdout && bfm_gbl.outfp != NULL) {
9742
                // just flush, in case we calibrate again
9743
                fflush(bfm_gbl.outfp);
9744
        }
9745
}
9746
 
9747
void print_u32_array(const char *label, alt_u32 *val, alt_u32 size)
9748
{
9749
        int i;
9750
 
9751
        fprintf(bfm_gbl.outfp, "%s", label);
9752
        for (i = 0; i < size; i++) {
9753
                fprintf(bfm_gbl.outfp, "%lu ", val[i]);
9754
        }
9755
        fprintf(bfm_gbl.outfp, "\n");
9756
}
9757
 
9758
void print_s32_array(const char *label, alt_32 *val, alt_u32 size)
9759
{
9760
        int i;
9761
 
9762
        fprintf(bfm_gbl.outfp, "%s", label);
9763
        for (i = 0; i < size; i++) {
9764
                fprintf(bfm_gbl.outfp, "%ld ", val[i]);
9765
        }
9766
        fprintf(bfm_gbl.outfp, "\n");
9767
}
9768
 
9769
void print_dqs_array(const char *label, alt_u32 *dqs)
9770
{
9771
        print_u32_array(label, dqs, MAX_DQS);
9772
}
9773
 
9774
void print_read_dq_array(const char *label, alt_32 *dq)
9775
{
9776
        print_s32_array(label, dq, RW_MGR_MEM_IF_READ_DQS_WIDTH*RW_MGR_MEM_DQ_PER_READ_DQS);
9777
}
9778
 
9779
void print_write_dq_array(const char *label, alt_32 *dq)
9780
{
9781
        print_s32_array(label, dq, RW_MGR_MEM_IF_WRITE_DQS_WIDTH*RW_MGR_MEM_DQ_PER_WRITE_DQS);
9782
}
9783
 
9784
void print_dm_array(const char *label, alt_32 *dq)
9785
{
9786
        print_s32_array(label, dq, RW_MGR_MEM_IF_WRITE_DQS_WIDTH*RW_MGR_NUM_DM_PER_WRITE_GROUP);
9787
}
9788
 
9789
void print_dqs_pos_array(const char *fmt, dqs_pos_t *dqs, int has_v, int has_ps)
9790
{
9791
        int i;
9792
 
9793
        if (has_v) {
9794
                fprintf(bfm_gbl.outfp, fmt, "_v:  ");
9795
                for (i = 0; i < RW_MGR_MEM_IF_READ_DQS_WIDTH; i++) {
9796
                        fprintf(bfm_gbl.outfp, "%lu ", dqs[i].v);
9797
                }
9798
                fprintf(bfm_gbl.outfp, "\n");
9799
        }
9800
        fprintf(bfm_gbl.outfp, fmt, "_p:  ");
9801
        for (i = 0; i < RW_MGR_MEM_IF_READ_DQS_WIDTH; i++) {
9802
                fprintf(bfm_gbl.outfp, "%lu ", dqs[i].p);
9803
        }
9804
        fprintf(bfm_gbl.outfp, "\n");
9805
        fprintf(bfm_gbl.outfp, fmt, "_d:  ");
9806
        for (i = 0; i < RW_MGR_MEM_IF_READ_DQS_WIDTH; i++) {
9807
                fprintf(bfm_gbl.outfp, "%lu ", dqs[i].d);
9808
        }
9809
        fprintf(bfm_gbl.outfp, "\n");
9810
        if (has_ps) {
9811
                fprintf(bfm_gbl.outfp, fmt, "_ps: ");
9812
                for (i = 0; i < RW_MGR_MEM_IF_READ_DQS_WIDTH; i++) {
9813
                        fprintf(bfm_gbl.outfp, "%lu ", dqs[i].ps);
9814
                }
9815
                fprintf(bfm_gbl.outfp, "\n");
9816
        }
9817
}
9818
 
9819
void print_gbl(void)
9820
{
9821
        int i;
9822
 
9823
        fprintf(bfm_gbl.outfp, "Globals\n");
9824
        fprintf(bfm_gbl.outfp, "bfm_stage:     %s\n", BFM_GBL_GET(stage));
9825
        // TODO: may want to do this per group, like other values
9826
        print_dqs_pos_array(   "dqse_left%s  ", BFM_GBL_GET(dqs_enable_left_edge), 1, 1);
9827
        print_dqs_pos_array(   "dqse_right%s ", BFM_GBL_GET(dqs_enable_right_edge), 1, 1);
9828
        print_dqs_pos_array(   "dqse_mid%s   ", BFM_GBL_GET(dqs_enable_mid), 1, 1);
9829
        print_dqs_pos_array(   "gwrite_pos%s ", BFM_GBL_GET(gwrite_pos), 0, 0);
9830
        print_dqs_pos_array(   "dqswl_left%s ", BFM_GBL_GET(dqs_wlevel_left_edge), 0, 1);
9831
        print_dqs_pos_array(   "dqswl_right%s", BFM_GBL_GET(dqs_wlevel_right_edge), 0, 1);
9832
        print_dqs_pos_array(   "dqswl_mid%s  ", BFM_GBL_GET(dqs_wlevel_mid), 0, 1);
9833
        print_read_dq_array(   "dq_read_l:     ", BFM_GBL_GET(dq_read_left_edge));
9834
        print_read_dq_array(   "dq_read_r:     ", BFM_GBL_GET(dq_read_right_edge));
9835
        print_write_dq_array(  "dq_write_l:    ", BFM_GBL_GET(dq_write_left_edge));
9836
        print_write_dq_array(  "dq_write_r:    ", BFM_GBL_GET(dq_write_right_edge));
9837
        print_dm_array(  "dm_l:          ", BFM_GBL_GET(dm_left_edge));
9838
        print_dm_array(  "dm_r:          ", BFM_GBL_GET(dm_right_edge));
9839
 
9840
        fprintf(bfm_gbl.outfp, "curr_read_lat: %lu\n", gbl->curr_read_lat);
9841
        fprintf(bfm_gbl.outfp, "error_stage:   %lu\n", gbl->error_stage);
9842
        fprintf(bfm_gbl.outfp, "error_group:   %lu\n", gbl->error_group);
9843
        fprintf(bfm_gbl.outfp, "fom_in:        %lu\n", gbl->fom_in);
9844
        fprintf(bfm_gbl.outfp, "fom_out:       %lu\n", gbl->fom_out);
9845
        fflush(bfm_gbl.outfp);
9846
};
9847
 
9848
void bfm_set_globals_from_config()
9849
{
9850
        const char *filename = "board_delay_config.txt";
9851
        const char *seq_c_prefix = "seq_c_";
9852
        FILE *fp;
9853
        char line[1024];
9854
        char name[64];
9855
        int value;
9856
 
9857
        if ((fp = fopen(filename, "r")) == NULL) {
9858
                DPRINT(0, "Failed to open %s for reading; skipping config\n", filename);
9859
                return;
9860
        }
9861
 
9862
        while (fgets(line, sizeof(line), fp) != NULL) {
9863
                if (sscanf(line, "%s %ld", name, &value) != 2) {
9864
                        continue;
9865
                }
9866
                // for some unknown reason, sscanf of 'name' doesn't seem to work when linked into modelsim,
9867
                // so we take a different approach for the name part, by just looking at the original line
9868
                if (strncmp(line, seq_c_prefix, strlen(seq_c_prefix)) != 0) {
9869
                        // not a line targetted for us
9870
                        continue;
9871
                }
9872
 
9873
                if (strncmp(line, "seq_c_skip_guaranteed_write", strlen("seq_c_skip_guaranteed_write")) == 0) {
9874
                        BFM_GBL_SET(bfm_skip_guaranteed_write,value);
9875
                        DPRINT(0, "bfm_skip_guaranteed_write => %ld", value);
9876
                } else if (strncmp(line, "seq_c_trk_sample_count", strlen("seq_c_trk_sample_count")) == 0) {
9877
                        BFM_GBL_SET(trk_sample_count,value);
9878
                        DPRINT(0, "trk_sample_count => %ld", value);
9879
                } else if (strncmp(line, "seq_c_trk_long_idle_updates", strlen("seq_c_trk_long_idle_updates")) == 0) {
9880
                        BFM_GBL_SET(trk_long_idle_updates,value);
9881
                        DPRINT(0, "trk_long_idle_updates => %ld", value);
9882
                } else if (strncmp(line, "seq_c_lfifo_margin", strlen("seq_c_lfifo_margin")) == 0) {
9883
                        BFM_GBL_SET(lfifo_margin,value/AFI_RATE_RATIO);
9884
                        DPRINT(0, "lfifo_margin => %ld", value);
9885
                } else {
9886
                        DPRINT(0, "Unknown Sequencer setting in line: %s\n", line);
9887
                }
9888
        }
9889
 
9890
        fclose(fp);
9891
}
9892
#endif
9893
 
9894
void initialize_reg_file(void)
9895
{
9896
        // Initialize the register file with the correct data
9897
        IOWR_32DIRECT (REG_FILE_SIGNATURE, 0, REG_FILE_INIT_SEQ_SIGNATURE);
9898
        IOWR_32DIRECT (REG_FILE_DEBUG_DATA_ADDR, 0, 0);
9899
        IOWR_32DIRECT (REG_FILE_CUR_STAGE, 0, 0);
9900
        IOWR_32DIRECT (REG_FILE_FOM, 0, 0);
9901
        IOWR_32DIRECT (REG_FILE_FAILING_STAGE, 0, 0);
9902
        IOWR_32DIRECT (REG_FILE_DEBUG1, 0, 0);
9903
        IOWR_32DIRECT (REG_FILE_DEBUG2, 0, 0);
9904
}
9905
 
9906
#if HPS_HW
9907
void initialize_hps_phy(void)
9908
{
9909
        // These may need to be included also:
9910
        // wrap_back_en (false)
9911
        // atpg_en (false)
9912
        // pipelineglobalenable (true) 
9913
 
9914
        alt_u32 reg;
9915
        // Tracking also gets configured here because it's in the same register
9916
        alt_u32 trk_sample_count = 7500;
9917
        alt_u32 trk_long_idle_sample_count = (10 << 16) | 100; // Format is number of outer loops in the 16 MSB, sample count in 16 LSB.
9918
 
9919
        reg = 0;
9920
#if DDR3 || DDR2
9921
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_ACDELAYEN_SET(2);
9922
#else
9923
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_ACDELAYEN_SET(1);
9924
#endif
9925
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_DQDELAYEN_SET(1);
9926
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_DQSDELAYEN_SET(1);
9927
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_DQSLOGICDELAYEN_SET(1);
9928
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_RESETDELAYEN_SET(0);
9929
#if LPDDR2
9930
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_LPDDRDIS_SET(0);
9931
#else
9932
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_LPDDRDIS_SET(1);
9933
#endif
9934
        // Fix for long latency VFIFO
9935
        // This field selects the intrinsic latency to RDATA_EN/FULL path. 00-bypass, 01- add 5 cycles, 10- add 10 cycles, 11- add 15 cycles.
9936
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_ADDLATSEL_SET(0);
9937
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_SAMPLECOUNT_19_0_SET(trk_sample_count);
9938
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_OFFSET, reg);
9939
 
9940
        reg = 0;
9941
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_1_SAMPLECOUNT_31_20_SET(trk_sample_count >> SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_SAMPLECOUNT_19_0_WIDTH);
9942
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_1_LONGIDLESAMPLECOUNT_19_0_SET(trk_long_idle_sample_count);
9943
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_PHYCTRL_PHYCTRL_1_OFFSET, reg);
9944
 
9945
        reg = 0;
9946
        reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_2_LONGIDLESAMPLECOUNT_31_20_SET(trk_long_idle_sample_count >> SDR_CTRLGRP_PHYCTRL_PHYCTRL_1_LONGIDLESAMPLECOUNT_19_0_WIDTH);
9947
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_PHYCTRL_PHYCTRL_2_OFFSET, reg);
9948
}
9949
#endif
9950
 
9951
#if USE_DQS_TRACKING
9952
 
9953
#if HHP_HPS
9954
void initialize_tracking(void)
9955
{
9956
    alt_u32 concatenated_longidle = 0x0;
9957
    alt_u32 concatenated_delays = 0x0;
9958
    alt_u32 concatenated_rw_addr = 0x0;
9959
    alt_u32 concatenated_refresh = 0x0;
9960
    alt_u32 dtaps_per_ptap;
9961
    alt_u32 tmp_delay;
9962
 
9963
    // compute usable version of value in case we skip full computation later
9964
    dtaps_per_ptap = 0;
9965
    tmp_delay = 0;
9966
    while (tmp_delay < IO_DELAY_PER_OPA_TAP) {
9967
        dtaps_per_ptap++;
9968
        tmp_delay += IO_DELAY_PER_DCHAIN_TAP;
9969
    }
9970
    dtaps_per_ptap--;
9971
 
9972
#if BFM_MODE
9973
    concatenated_longidle = concatenated_longidle ^ (bfm_gbl.trk_long_idle_updates > 0 ? bfm_gbl.trk_long_idle_updates : 10); //longidle outer loop
9974
    concatenated_longidle = concatenated_longidle << 16;
9975
    concatenated_longidle = concatenated_longidle ^ (bfm_gbl.trk_sample_count > 0 ? bfm_gbl.trk_sample_count : 100); //longidle sample count
9976
#else
9977
    concatenated_longidle = concatenated_longidle ^ 10; //longidle outer loop
9978
    concatenated_longidle = concatenated_longidle << 16;
9979
    concatenated_longidle = concatenated_longidle ^ 100; //longidle sample count
9980
#endif
9981
 
9982
    concatenated_delays = concatenated_delays ^ 243; // trfc, worst case of 933Mhz 4Gb
9983
    concatenated_delays = concatenated_delays << 8;
9984
    concatenated_delays = concatenated_delays ^ 14; // trcd, worst case
9985
    concatenated_delays = concatenated_delays << 8;
9986
    concatenated_delays = concatenated_delays ^ 10; // vfifo wait
9987
    concatenated_delays = concatenated_delays << 8;
9988
    concatenated_delays = concatenated_delays ^ 4; // mux delay
9989
 
9990
#if DDR3 || LPDDR2
9991
    concatenated_rw_addr = concatenated_rw_addr ^ __RW_MGR_IDLE;
9992
    concatenated_rw_addr = concatenated_rw_addr << 8;
9993
    concatenated_rw_addr = concatenated_rw_addr ^ __RW_MGR_ACTIVATE_1;
9994
    concatenated_rw_addr = concatenated_rw_addr << 8;
9995
    concatenated_rw_addr = concatenated_rw_addr ^ __RW_MGR_SGLE_READ;
9996
    concatenated_rw_addr = concatenated_rw_addr << 8;
9997
    concatenated_rw_addr = concatenated_rw_addr ^ __RW_MGR_PRECHARGE_ALL;
9998
#endif
9999
 
10000
#if DDR3 || LPDDR2
10001
    concatenated_refresh = concatenated_refresh ^ __RW_MGR_REFRESH_ALL;
10002
#else
10003
    concatenated_refresh = concatenated_refresh ^ 0;
10004
#endif
10005
    concatenated_refresh = concatenated_refresh << 24;
10006
    concatenated_refresh = concatenated_refresh ^ 1000; // trefi
10007
 
10008
        // Initialize the register file with the correct data
10009
        IOWR_32DIRECT (REG_FILE_DTAPS_PER_PTAP, 0, dtaps_per_ptap);
10010
#if BFM_MODE
10011
        IOWR_32DIRECT (REG_FILE_TRK_SAMPLE_COUNT, 0, bfm_gbl.trk_sample_count > 0 ? bfm_gbl.trk_sample_count : 7500);
10012
#else
10013
        IOWR_32DIRECT (REG_FILE_TRK_SAMPLE_COUNT, 0, 7500);
10014
#endif
10015
        IOWR_32DIRECT (REG_FILE_TRK_LONGIDLE, 0, concatenated_longidle);
10016
        IOWR_32DIRECT (REG_FILE_DELAYS, 0, concatenated_delays);
10017
        IOWR_32DIRECT (REG_FILE_TRK_RW_MGR_ADDR, 0, concatenated_rw_addr);
10018
        IOWR_32DIRECT (REG_FILE_TRK_READ_DQS_WIDTH, 0, RW_MGR_MEM_IF_READ_DQS_WIDTH);
10019
        IOWR_32DIRECT (REG_FILE_TRK_RFSH, 0, concatenated_refresh);
10020
}
10021
 
10022
#else
10023
 
10024
void initialize_tracking(void)
10025
{
10026
    alt_u32 concatenated_longidle = 0x0;
10027
    alt_u32 concatenated_delays = 0x0;
10028
    alt_u32 concatenated_rw_addr = 0x0;
10029
    alt_u32 concatenated_refresh = 0x0;
10030
    alt_u32 dtaps_per_ptap;
10031
    alt_u32 tmp_delay;
10032
 
10033
    // compute usable version of value in case we skip full computation later
10034
    dtaps_per_ptap = 0;
10035
    tmp_delay = 0;
10036
    while (tmp_delay < IO_DELAY_PER_OPA_TAP) {
10037
        dtaps_per_ptap++;
10038
        tmp_delay += IO_DELAY_PER_DCHAIN_TAP;
10039
    }
10040
    dtaps_per_ptap--;
10041
 
10042
#if BFM_MODE
10043
    concatenated_longidle = concatenated_longidle ^ (bfm_gbl.trk_long_idle_updates > 0 ? bfm_gbl.trk_long_idle_updates : 10); //longidle outer loop
10044
    concatenated_longidle = concatenated_longidle << 16;
10045
    concatenated_longidle = concatenated_longidle ^ (bfm_gbl.trk_sample_count > 0 ? bfm_gbl.trk_sample_count : 100); //longidle sample count
10046
#else
10047
    concatenated_longidle = concatenated_longidle ^ 10; //longidle outer loop
10048
    concatenated_longidle = concatenated_longidle << 16;
10049
    concatenated_longidle = concatenated_longidle ^ 100; //longidle sample count
10050
#endif
10051
 
10052
#if FULL_RATE
10053
    concatenated_delays = concatenated_delays ^ 60; // trfc
10054
#endif
10055
#if HALF_RATE
10056
    concatenated_delays = concatenated_delays ^ 30; // trfc
10057
#endif
10058
#if QUARTER_RATE
10059
    concatenated_delays = concatenated_delays ^ 15; // trfc
10060
#endif
10061
    concatenated_delays = concatenated_delays << 8;
10062
#if FULL_RATE
10063
    concatenated_delays = concatenated_delays ^ 4; // trcd
10064
#endif
10065
#if HALF_RATE
10066
    concatenated_delays = concatenated_delays ^ 2; // trcd
10067
#endif
10068
#if QUARTER_RATE
10069
    concatenated_delays = concatenated_delays ^ 0; // trcd
10070
#endif
10071
    concatenated_delays = concatenated_delays << 8;
10072
#if FULL_RATE
10073
    concatenated_delays = concatenated_delays ^ 5; // vfifo wait
10074
#endif
10075
#if HALF_RATE
10076
    concatenated_delays = concatenated_delays ^ 3; // vfifo wait
10077
#endif
10078
#if QUARTER_RATE
10079
    concatenated_delays = concatenated_delays ^ 1; // vfifo wait
10080
#endif
10081
    concatenated_delays = concatenated_delays << 8;
10082
#if FULL_RATE
10083
    concatenated_delays = concatenated_delays ^ 4; // mux delay
10084
#endif
10085
#if HALF_RATE
10086
    concatenated_delays = concatenated_delays ^ 2; // mux delay
10087
#endif
10088
#if QUARTER_RATE
10089
    concatenated_delays = concatenated_delays ^ 0; // mux delay
10090
#endif
10091
 
10092
#if DDR3 || LPDDR2
10093
    concatenated_rw_addr = concatenated_rw_addr ^ __RW_MGR_IDLE;
10094
    concatenated_rw_addr = concatenated_rw_addr << 8;
10095
    concatenated_rw_addr = concatenated_rw_addr ^ __RW_MGR_ACTIVATE_1;
10096
    concatenated_rw_addr = concatenated_rw_addr << 8;
10097
    concatenated_rw_addr = concatenated_rw_addr ^ __RW_MGR_SGLE_READ;
10098
    concatenated_rw_addr = concatenated_rw_addr << 8;
10099
    concatenated_rw_addr = concatenated_rw_addr ^ __RW_MGR_PRECHARGE_ALL;
10100
#endif
10101
 
10102
#if DDR3 || LPDDR2
10103
    concatenated_refresh = concatenated_refresh ^ __RW_MGR_REFRESH_ALL;
10104
#else
10105
    concatenated_refresh = concatenated_refresh ^ 0;
10106
#endif
10107
    concatenated_refresh = concatenated_refresh << 24;
10108
    concatenated_refresh = concatenated_refresh ^ 546; // trefi
10109
 
10110
        IOWR_32DIRECT (TRK_DTAPS_PER_PTAP, 0, dtaps_per_ptap);
10111
#if BFM_MODE
10112
        IOWR_32DIRECT (TRK_SAMPLE_COUNT, 0, bfm_gbl.trk_sample_count > 0 ? bfm_gbl.trk_sample_count : 7500);
10113
#else
10114
        IOWR_32DIRECT (TRK_SAMPLE_COUNT, 0, 7500);
10115
#endif
10116
        IOWR_32DIRECT (TRK_LONGIDLE, 0, concatenated_longidle);
10117
        IOWR_32DIRECT (TRK_DELAYS, 0, concatenated_delays);
10118
        IOWR_32DIRECT (TRK_RW_MGR_ADDR, 0, concatenated_rw_addr);
10119
        IOWR_32DIRECT (TRK_READ_DQS_WIDTH, 0, RW_MGR_MEM_IF_READ_DQS_WIDTH);
10120
        IOWR_32DIRECT (TRK_RFSH, 0, concatenated_refresh);
10121
}
10122
#endif  /* HHP_HPS */
10123
#endif  /* USE_DQS_TRACKING */
10124
 
10125
#if HHP_HPS_SIMULATION
10126
void initialize_hps_controller(void)
10127
{
10128
        alt_u32 reg;
10129
        alt_u32 memtype;
10130
        alt_u32 ecc;
10131
        alt_u32 ctrl_width;
10132
        alt_u32 mem_bl;
10133
 
10134
        if (DDR2) {
10135
                memtype = 1;
10136
        } else if (DDR3) {
10137
                memtype = 2;
10138
        } else if (LPDDR1) {
10139
                memtype = 3;
10140
        } else if (LPDDR2) {
10141
                memtype = 4;
10142
        } else {
10143
                // should never happen
10144
                memtype = 0;
10145
        }
10146
 
10147
        if (RW_MGR_MEM_DATA_WIDTH == 24 || RW_MGR_MEM_DATA_WIDTH == 40) {
10148
                // we have ecc
10149
                ecc = 1;
10150
        } else {
10151
                ecc = 0;
10152
        }
10153
 
10154
        reg = 0;
10155
        reg |= SDR_CTRLGRP_CTRLCFG_MEMTYPE_SET(memtype);
10156
        reg |= SDR_CTRLGRP_CTRLCFG_MEMBL_SET(MEM_BURST_LENGTH);
10157
        reg |= SDR_CTRLGRP_CTRLCFG_ADDRORDER_SET(ADDR_ORDER);
10158
        reg |= SDR_CTRLGRP_CTRLCFG_ECCEN_SET(ecc);
10159
        reg |= SDR_CTRLGRP_CTRLCFG_ECCCORREN_SET(0);
10160
        reg |= SDR_CTRLGRP_CTRLCFG_CFG_ENABLE_ECC_CODE_OVERWRITES_SET(0);
10161
        reg |= SDR_CTRLGRP_CTRLCFG_GENSBE_SET(0);
10162
        reg |= SDR_CTRLGRP_CTRLCFG_GENDBE_SET(0);
10163
        reg |= SDR_CTRLGRP_CTRLCFG_REORDEREN_SET(1);
10164
        reg |= SDR_CTRLGRP_CTRLCFG_STARVELIMIT_SET(0x8);
10165
        reg |= SDR_CTRLGRP_CTRLCFG_DQSTRKEN_SET(USE_DQS_TRACKING); // Do we want this?
10166
#if DM_PINS_ENABLED
10167
    reg |= SDR_CTRLGRP_CTRLCFG_NODMPINS_SET(0);
10168
#else
10169
    reg |= SDR_CTRLGRP_CTRLCFG_NODMPINS_SET(1);
10170
#endif
10171
        reg |= SDR_CTRLGRP_CTRLCFG_BURSTINTREN_SET(0);
10172
        reg |= SDR_CTRLGRP_CTRLCFG_BURSTTERMEN_SET(0);
10173
        reg |= SDR_CTRLGRP_CTRLCFG_OUTPUTREG_SET(0);
10174
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_CTRLCFG_OFFSET, reg);
10175
 
10176
        reg = 0;
10177
        reg |= SDR_CTRLGRP_DRAMTIMING1_TCWL_SET(MEM_WTCL_INT);
10178
        reg |= SDR_CTRLGRP_DRAMTIMING1_TAL_SET(MEM_ATCL_INT);
10179
        reg |= SDR_CTRLGRP_DRAMTIMING1_TCL_SET(MEM_TCL);
10180
        reg |= SDR_CTRLGRP_DRAMTIMING1_TRRD_SET(MEM_TRRD);
10181
        reg |= SDR_CTRLGRP_DRAMTIMING1_TFAW_SET(MEM_TFAW);
10182
        reg |= SDR_CTRLGRP_DRAMTIMING1_TRFC_SET(MEM_TRFC);
10183
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_DRAMTIMING1_OFFSET, reg);
10184
 
10185
        reg = 0;
10186
        reg |= SDR_CTRLGRP_DRAMTIMING2_TREFI_SET(MEM_TREFI);
10187
        reg |= SDR_CTRLGRP_DRAMTIMING2_TRCD_SET(MEM_TRCD);
10188
        reg |= SDR_CTRLGRP_DRAMTIMING2_TRP_SET(MEM_TRP);
10189
        reg |= SDR_CTRLGRP_DRAMTIMING2_TWTR_SET(MEM_TWTR);
10190
        reg |= SDR_CTRLGRP_DRAMTIMING2_TWR_SET(MEM_TWR);
10191
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_DRAMTIMING2_OFFSET, reg);
10192
 
10193
        reg = 0;
10194
        reg |= SDR_CTRLGRP_DRAMTIMING3_TRTP_SET(MEM_TRTP);
10195
        reg |= SDR_CTRLGRP_DRAMTIMING3_TRAS_SET(MEM_TRAS);
10196
        reg |= SDR_CTRLGRP_DRAMTIMING3_TRC_SET(MEM_TRC);
10197
        reg |= SDR_CTRLGRP_DRAMTIMING3_TMRD_SET(MEM_TMRD_CK);
10198
        reg |= SDR_CTRLGRP_DRAMTIMING3_TCCD_SET(CFG_TCCD);
10199
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_DRAMTIMING3_OFFSET, reg);
10200
 
10201
 
10202
        // These values don't really matter for the HPS simulation
10203
        reg = 0;
10204
        reg |= SDR_CTRLGRP_DRAMTIMING4_SELFRFSHEXIT_SET(512);
10205
        reg |= SDR_CTRLGRP_DRAMTIMING4_PWRDOWNEXIT_SET(10);
10206
        reg |= SDR_CTRLGRP_DRAMTIMING4_MINPWRSAVECYCLES_SET(0);
10207
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_DRAMTIMING4_OFFSET, reg);
10208
 
10209
        // These values don't really matter for the HPS simulation
10210
        reg = 0;
10211
        reg |= SDR_CTRLGRP_LOWPWRTIMING_AUTOPDCYCLES_SET(0);
10212
        reg |= SDR_CTRLGRP_LOWPWRTIMING_CLKDISABLECYCLES_SET(0);
10213
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_LOWPWRTIMING_OFFSET, reg);
10214
 
10215
 
10216
        // These values don't really matter for the HPS simulation
10217
        reg = 0;
10218
        reg |= SDR_CTRLGRP_DRAMODT_CFG_WRITE_ODT_CHIP_SET(0);
10219
        reg |= SDR_CTRLGRP_DRAMODT_CFG_READ_ODT_CHIP_SET(0);
10220
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_DRAMODT_OFFSET, reg);
10221
 
10222
 
10223
        reg = 0;
10224
        reg |= SDR_CTRLGRP_EXTRATIME1_CFG_EXTRA_CTL_CLK_ACT_TO_RDWR_SET(INTG_EXTRA_CTL_CLK_ACT_TO_RDWR);
10225
        reg |= SDR_CTRLGRP_EXTRATIME1_CFG_EXTRA_CTL_CLK_ACT_TO_PCH_SET(INTG_EXTRA_CTL_CLK_RD_TO_PCH);
10226
        reg |= SDR_CTRLGRP_EXTRATIME1_CFG_EXTRA_CTL_CLK_ACT_TO_ACT_SET(INTG_EXTRA_CTL_CLK_ACT_TO_ACT);
10227
        reg |= SDR_CTRLGRP_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_RD_SET(INTG_EXTRA_CTL_CLK_RD_TO_RD);
10228
        reg |= SDR_CTRLGRP_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_RD_DIFF_CHIP_SET(INTG_EXTRA_CTL_CLK_RD_TO_RD_DIFF_CHIP);
10229
        reg |= SDR_CTRLGRP_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_SET(INTG_EXTRA_CTL_CLK_RD_TO_WR);
10230
        reg |= SDR_CTRLGRP_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_BC_SET(INTG_EXTRA_CTL_CLK_RD_TO_WR_BC);
10231
        reg |= SDR_CTRLGRP_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_DIFF_CHIP_SET(INTG_EXTRA_CTL_CLK_RD_TO_WR_DIFF_CHIP);
10232
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_EXTRATIME1_OFFSET, reg);
10233
 
10234
        reg = 0;
10235
        reg |= SDR_CTRLGRP_EXTRATIME2_CFG_EXTRA_CTL_CLK_RD_TO_PCH_SET(INTG_EXTRA_CTL_CLK_RD_TO_PCH);
10236
        reg |= SDR_CTRLGRP_EXTRATIME2_CFG_EXTRA_CTL_CLK_RD_AP_TO_VALID_SET(INTG_EXTRA_CTL_CLK_RD_AP_TO_VALID);
10237
        reg |= SDR_CTRLGRP_EXTRATIME2_CFG_EXTRA_CTL_CLK_WR_TO_WR_SET(INTG_EXTRA_CTL_CLK_WR_TO_WR);
10238
        reg |= SDR_CTRLGRP_EXTRATIME2_CFG_EXTRA_CTL_CLK_WR_TO_WR_DIFF_CHIP_SET(INTG_EXTRA_CTL_CLK_WR_TO_WR_DIFF_CHIP);
10239
        reg |= SDR_CTRLGRP_EXTRATIME2_CFG_EXTRA_CTL_CLK_WR_TO_RD_SET(INTG_EXTRA_CTL_CLK_WR_TO_RD);
10240
        reg |= SDR_CTRLGRP_EXTRATIME2_CFG_EXTRA_CTL_CLK_WR_TO_RD_BC_SET(INTG_EXTRA_CTL_CLK_WR_TO_RD_BC);
10241
        reg |= SDR_CTRLGRP_EXTRATIME2_CFG_EXTRA_CTL_CLK_WR_TO_RD_DIFF_CHIP_SET(INTG_EXTRA_CTL_CLK_WR_TO_RD_DIFF_CHIP);
10242
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_EXTRATIME2_OFFSET, reg);
10243
 
10244
        reg = 0;
10245
        reg |= SDR_CTRLGRP_EXTRATIME3_CFG_EXTRA_CTL_CLK_WR_TO_PCH_SET(INTG_EXTRA_CTL_CLK_WR_TO_PCH);
10246
        reg |= SDR_CTRLGRP_EXTRATIME3_CFG_EXTRA_CTL_CLK_WR_AP_TO_VALID_SET(INTG_EXTRA_CTL_CLK_WR_AP_TO_VALID);
10247
        reg |= SDR_CTRLGRP_EXTRATIME3_CFG_EXTRA_CTL_CLK_PCH_TO_VALID_SET(INTG_EXTRA_CTL_CLK_PCH_TO_VALID);
10248
        reg |= SDR_CTRLGRP_EXTRATIME3_CFG_EXTRA_CTL_CLK_PCH_ALL_TO_VALID_SET(INTG_EXTRA_CTL_CLK_PCH_ALL_TO_VALID);
10249
        reg |= SDR_CTRLGRP_EXTRATIME3_CFG_EXTRA_CTL_CLK_ACT_TO_ACT_DIFF_BANK_SET(INTG_EXTRA_CTL_CLK_ACT_TO_ACT_DIFF_BANK);
10250
        reg |= SDR_CTRLGRP_EXTRATIME3_CFG_EXTRA_CTL_CLK_FOUR_ACT_TO_ACT_SET(INTG_EXTRA_CTL_CLK_FOUR_ACT_TO_ACT);
10251
        reg |= SDR_CTRLGRP_EXTRATIME3_CFG_EXTRA_CTL_CLK_ARF_TO_VALID_SET(INTG_EXTRA_CTL_CLK_ARF_TO_VALID);
10252
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_EXTRATIME3_OFFSET, reg);
10253
 
10254
 
10255
        reg = 0;
10256
        reg |= SDR_CTRLGRP_EXTRATIME4_CFG_EXTRA_CTL_CLK_PDN_TO_VALID_SET(INTG_EXTRA_CTL_CLK_PDN_TO_VALID);
10257
        reg |= SDR_CTRLGRP_EXTRATIME4_CFG_EXTRA_CTL_CLK_SRF_TO_VALID_SET(INTG_EXTRA_CTL_CLK_SRF_TO_VALID);
10258
        reg |= SDR_CTRLGRP_EXTRATIME4_CFG_EXTRA_CTL_CLK_SRF_TO_ZQ_CAL_SET(INTG_EXTRA_CTL_CLK_SRF_TO_ZQ_CAL);
10259
        reg |= SDR_CTRLGRP_EXTRATIME4_CFG_EXTRA_CTL_CLK_ARF_PERIOD_SET(INTG_EXTRA_CTL_CLK_ARF_PERIOD);
10260
        reg |= SDR_CTRLGRP_EXTRATIME4_CFG_EXTRA_CTL_CLK_PDN_PERIOD_SET(INTG_EXTRA_CTL_CLK_PDN_PERIOD);
10261
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_EXTRATIME4_OFFSET, reg);
10262
 
10263
        reg = 0;
10264
        reg |= SDR_CTRLGRP_DRAMADDRW_COLBITS_SET(MEM_IF_COL_ADDR_WIDTH);
10265
        reg |= SDR_CTRLGRP_DRAMADDRW_ROWBITS_SET(MEM_IF_ROW_ADDR_WIDTH);
10266
        reg |= SDR_CTRLGRP_DRAMADDRW_BANKBITS_SET(MEM_IF_BANKADDR_WIDTH);
10267
        reg |= SDR_CTRLGRP_DRAMADDRW_CSBITS_SET(MEM_IF_CS_WIDTH > 1 ? MEM_IF_CHIP_BITS : 0);
10268
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_DRAMADDRW_OFFSET, reg);
10269
 
10270
        reg = 0;
10271
        reg |= SDR_CTRLGRP_DRAMIFWIDTH_IFWIDTH_SET(RW_MGR_MEM_DATA_WIDTH);
10272
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_DRAMIFWIDTH_OFFSET, reg);
10273
 
10274
        reg = 0;
10275
        reg |= SDR_CTRLGRP_DRAMDEVWIDTH_DEVWIDTH_SET(RW_MGR_MEM_DQ_PER_READ_DQS); // should always be 8
10276
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_DRAMDEVWIDTH_OFFSET, reg);
10277
 
10278
        switch (RW_MGR_MEM_DATA_WIDTH) {
10279
        case 8: ctrl_width = 0; break;
10280
        case 16: // FALLTHROUGH
10281
        case 24: ctrl_width = 1; break;
10282
        case 32: // FALLTHROUGH
10283
        case 40: ctrl_width = 2; break;
10284
        default: ctrl_width = 0; break; /* shouldn't happen */
10285
        }
10286
 
10287
        reg = 0;
10288
        reg |= SDR_CTRLGRP_CTRLWIDTH_CTRLWIDTH_SET(ctrl_width);
10289
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_CTRLWIDTH_OFFSET, reg);
10290
 
10291
        // hard-coded values taken from test bench
10292
        reg = 0;
10293
        // 30'b111111111111010001000010001000
10294
        reg |= SDR_CTRLGRP_MPPRIORITY_USERPRIORITY_SET(0x3FFD1088);
10295
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_MPPRIORITY_OFFSET, reg);
10296
 
10297
        // hard-coded values taken from test bench
10298
        reg = 0;
10299
        // first 32 bits of 50'b01111011111000010000100001000010000100001000010000
10300
        reg |= SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_0_STATICWEIGHT_31_0_SET(0x21084210);
10301
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_0_OFFSET, reg);
10302
 
10303
        // hard-coded values taken from test bench
10304
        reg = 0;
10305
        // first next 18 bits of 50'b01111011111000010000100001000010000100001000010000
10306
        reg |= SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_STATICWEIGHT_49_32_SET(0x1EF84);
10307
        // first 14 of 64'b0011111000000000000000000000000000000000001000000010000000100000
10308
        reg |= SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_SUMOFWEIGHTS_13_0_SET(0x2002);
10309
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_OFFSET, reg);
10310
 
10311
        // hard-coded values taken from test bench
10312
        reg = 0;
10313
        // next 32 bits of 64'b0011111000000000000000000000000000000000001000000010000000100000
10314
        reg |= SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_2_SUMOFWEIGHTS_45_14_SET(0x80);
10315
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_2_OFFSET, reg);
10316
 
10317
        // hard-coded values taken from test bench
10318
        reg = 0;
10319
        // next 18 bits of 64'b0011111000000000000000000000000000000000001000000010000000100000
10320
        reg |= SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_3_SUMOFWEIGHTS_63_46_SET(0xF800);
10321
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_3_OFFSET, reg);
10322
 
10323
        switch (MEM_BURST_LENGTH) {
10324
        case 2: mem_bl = 0; break;
10325
        case 4: mem_bl = 1; break;
10326
        case 8: mem_bl = 2; break;
10327
        default: mem_bl = 2; break; // should never happen
10328
        }
10329
        reg = 0;
10330
        reg |= SDR_CTRLGRP_STATICCFG_MEMBL_SET(mem_bl);
10331
        reg |= SDR_CTRLGRP_STATICCFG_USEECCASDATA_SET(0); /* allow fpga to access ecc bits; not supported */
10332
        reg |= SDR_CTRLGRP_STATICCFG_APPLYCFG_SET(1);     /* apply all of the configs here and above */
10333
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_STATICCFG_OFFSET, reg);
10334
 
10335
        reg = 0;
10336
        reg |= SDR_CTRLGRP_FPGAPORTRST_PORTRSTN_SET(~0);
10337
        IOWR_32DIRECT (BASE_MMR, SDR_CTRLGRP_FPGAPORTRST_OFFSET, reg);
10338
}
10339
#endif
10340
 
10341
void user_init_cal_req(void)
10342
{
10343
        alt_u32 scc_afi_reg;
10344
 
10345
        scc_afi_reg = IORD_32DIRECT (SCC_MGR_AFI_CAL_INIT, 0);
10346
 
10347
        if (scc_afi_reg == 1 || scc_afi_reg == 16) {// 1 is initialization request
10348
            initialize();
10349
            rw_mgr_mem_initialize ();
10350
            rw_mgr_mem_handoff ();
10351
            IOWR_32DIRECT (PHY_MGR_MUX_SEL, 0, 0);
10352
            IOWR_32DIRECT (PHY_MGR_CAL_STATUS, 0, PHY_MGR_CAL_SUCCESS);
10353
        } else if (scc_afi_reg == 2 || scc_afi_reg == 32) {
10354
#if ENABLE_NON_DES_CAL          
10355
            run_mem_calibrate (0);
10356
#else
10357
            run_mem_calibrate();
10358
#endif
10359
        }
10360
#if ENABLE_NON_DES_CAL
10361
        else if (scc_afi_reg == 4) {
10362
                //non destructive mem init
10363
                IOWR_32DIRECT (SCC_MGR_AFI_CAL_INIT, 0, scc_afi_reg & ~(1 << 2));
10364
 
10365
                rw_mgr_mem_initialize_no_init();
10366
 
10367
 
10368
        } else if (scc_afi_reg == 8) {
10369
                //non destructive mem calibrate
10370
                IOWR_32DIRECT (SCC_MGR_AFI_CAL_INIT, 0, scc_afi_reg & ~(1 << 3));
10371
 
10372
                run_mem_calibrate (1);
10373
                IOWR_32DIRECT (RW_MGR_ENABLE_REFRESH, 0, 0);  // Disable refresh engine  
10374
        }
10375
#endif
10376
 
10377
}
10378
 
10379
#if TRACKING_WATCH_TEST || TRACKING_ERROR_TEST
10380
void decrement_dqs_en_phase (alt_u32 group) {
10381
        alt_u32 phase = 0;
10382
        alt_u32 v;
10383
        phase = READ_SCC_DQS_EN_PHASE(group);
10384
 
10385
        if (phase == 0) {
10386
                rw_mgr_decr_vfifo(group, &v);
10387
                scc_mgr_set_dqs_en_phase(group, IO_DQS_EN_PHASE_MAX);
10388
                scc_mgr_set_dqs_en_delay(group, IO_DQS_EN_DELAY_MAX);
10389
                return;
10390
        }
10391
 
10392
        scc_mgr_set_dqs_en_phase(group, phase - 1);
10393
        scc_mgr_set_dqs_en_delay(group, IO_DQS_EN_DELAY_MAX);
10394
}
10395
 
10396
void read_samples (void)
10397
{
10398
        alt_u32 group = 0;
10399
        alt_32 sample_count = 0;
10400
        alt_u32 delay = 0;
10401
        alt_u32 phase = 0;
10402
 
10403
        alt_u32 dtaps_per_ptap = 0;
10404
 
10405
        dtaps_per_ptap = IORD_32DIRECT(0xD0000, 0);
10406
        TCLRPT_SET(debug_cal_report->cal_dqs_in_settings[curr_shadow_reg][group].dtaps_per_ptap, dtaps_per_ptap);
10407
 
10408
#if TRACKING_WATCH_TEST 
10409
        for (;;) {
10410
                // Stall tracking to ensure accurate reading
10411
                IOWR_32DIRECT (TRK_STALL, 0, TRK_STALL_REQ_VAL);
10412
                // Wait for tracking manager to ack stall request
10413
                while (IORD_32DIRECT (TRK_STALL, 0) != TRK_STALL_ACKED_VAL) {
10414
                }
10415
 
10416
                for (group = 0; group < RW_MGR_MEM_IF_READ_DQS_WIDTH; group++) {
10417
                        // Read sample counter
10418
                        sample_count = IORD_32DIRECT(0x58F00, group << 2);
10419
                        TCLRPT_SET(debug_cal_report->cal_dqs_in_settings[curr_shadow_reg][group].sample_count, sample_count);
10420
                        delay = READ_SCC_DQS_EN_DELAY(group);
10421
                        phase = READ_SCC_DQS_EN_PHASE(group);
10422
                        TCLRPT_SET(debug_cal_report->cal_dqs_in_settings[curr_shadow_reg][group].dqs_en_phase, (delay | (phase << 16)));
10423
                }
10424
 
10425
                // Release stall        
10426
                IOWR_32DIRECT(TRK_STALL, 0, 0);
10427
        }
10428
#endif
10429
 
10430
#if TRACKING_ERROR_TEST
10431
        for (group = 0; group < RW_MGR_MEM_IF_READ_DQS_WIDTH; group++) {
10432
                // Read sample counter
10433
                sample_count = IORD_32DIRECT(0x58F00, group << 2);
10434
                TCLRPT_SET(debug_cal_report->cal_dqs_in_settings[curr_shadow_reg][group].sample_count, sample_count);
10435
                delay = READ_SCC_DQS_EN_DELAY(group);
10436
                TCLRPT_SET(debug_cal_report->cal_dqs_in_settings[curr_shadow_reg][group].dqs_en_delay, delay);
10437
                phase = READ_SCC_DQS_EN_PHASE(group);
10438
                TCLRPT_SET(debug_cal_report->cal_dqs_in_settings[curr_shadow_reg][group].dqs_en_phase, phase);
10439
        }
10440
#endif
10441
}
10442
 
10443
void tracking_sample_check (void)
10444
{
10445
        alt_u32 group = 0;
10446
        alt_u32 t11_d = 0;
10447
        alt_u32 read_val = 0;
10448
 
10449
        alt_u32 num_samples = 0;
10450
        alt_u32 num_samples_max = 7500;
10451
 
10452
        alt_u32 bit_chk = 0;
10453
        alt_u32 test_status = 0;
10454
 
10455
        for (group = 0; group < RW_MGR_MEM_IF_READ_DQS_WIDTH; group++)
10456
        {
10457
                // TODO: Figure out whether the sample counter and sample run
10458
                // values should be defined somewhere, or just leave them
10459
                // hardcoded.
10460
                IOWR_32DIRECT(0x58F00, group << 2, 0x00);
10461
        }
10462
 
10463
        for (num_samples = 0; num_samples < num_samples_max; num_samples++) {
10464
                //do a read
10465
                //test_status = rw_mgr_mem_calibrate_read_test_all_ranks (group, 1, PASS_ONE_BIT, &bit_chk, 0);
10466
                //do a write
10467
                test_status = rw_mgr_mem_calibrate_write_test_all_ranks (group, 0, PASS_ONE_BIT, &bit_chk);
10468
 
10469
                // do a sample
10470
                IOWR_32DIRECT(0x58FFC, 0, 0xFF);
10471
        }
10472
 
10473
        read_samples();
10474
}
10475
 
10476
void poll_for_sample_check (void)
10477
{
10478
        alt_u32 check_status = 2;
10479
        alt_u32 delay = 0;
10480
        alt_u32 group = 0;
10481
 
10482
        alt_u32 READY_FOR_READ = 0xFE;
10483
        alt_u32 READ_FINISHED = 0xFD;
10484
        alt_u32 EXIT_LOOP = 0x00;
10485
        alt_u32 FINISHED_SIGNAL = 0xFF;
10486
 
10487
        for (;;) {
10488
                check_status = IORD_32DIRECT(REG_FILE_TRK_SAMPLE_CHECK, 0);
10489
 
10490
                if (check_status == READY_FOR_READ) {
10491
                        for (group = 0; group < RW_MGR_MEM_IF_READ_DQS_WIDTH; group++) {
10492
 
10493
                                delay = READ_SCC_DQS_EN_DELAY(group);
10494
 
10495
                                if (delay == 0) {
10496
                                        decrement_dqs_en_phase(group);
10497
                                } else {
10498
                                        delay--;
10499
                                        scc_mgr_set_dqs_en_delay(group, delay);
10500
                                }
10501
 
10502
                                IOWR_32DIRECT (SCC_MGR_DQS_ENA, 0, group);
10503
                        }
10504
 
10505
                        IOWR_32DIRECT (SCC_MGR_UPD, 0, 0);
10506
 
10507
                        tracking_sample_check();
10508
                        check_status = IORD_32DIRECT(REG_FILE_TRK_SAMPLE_CHECK, 0);
10509
                        if (check_status != EXIT_LOOP) {
10510
                                IOWR_32DIRECT(REG_FILE_TRK_SAMPLE_CHECK, 0, READ_FINISHED);
10511
                        }
10512
                }
10513
                if (check_status == EXIT_LOOP) {
10514
                        IOWR_32DIRECT(REG_FILE_TRK_SAMPLE_CHECK, 0, FINISHED_SIGNAL);
10515
                        break;
10516
                }
10517
        }
10518
}
10519
#endif // TRACKING_WATCH_TEST || TRACKING_ERROR_TEST
10520
 
10521
#if BFM_MODE
10522
int seq_main(void)
10523
#elif HPS_HW
10524
int sdram_calibration(void)
10525
#else
10526
int main(void)
10527
#endif
10528
{
10529
        param_t my_param;
10530
        gbl_t my_gbl;
10531
        alt_u32 pass;
10532
        alt_u32 i;
10533
 
10534
        param = &my_param;
10535
        gbl = &my_gbl;
10536
 
10537
        // Initialize the debug mode flags
10538
        gbl->phy_debug_mode_flags = 0;
10539
        // Set the calibration enabled by default
10540
        gbl->phy_debug_mode_flags |= PHY_DEBUG_ENABLE_CAL_RPT;
10541
        // Only enable margining by default if requested
10542
#if ENABLE_MARGIN_REPORT_GEN
10543
        gbl->phy_debug_mode_flags |= PHY_DEBUG_ENABLE_MARGIN_RPT;
10544
#endif
10545
        // Only sweep all groups (regardless of fail state) by default if requested 
10546
#if ENABLE_SWEEP_ALL_GROUPS
10547
        gbl->phy_debug_mode_flags |= PHY_DEBUG_SWEEP_ALL_GROUPS;
10548
#endif
10549
        //Set enabled read test by default
10550
#if DISABLE_GUARANTEED_READ
10551
        gbl->phy_debug_mode_flags |= PHY_DEBUG_DISABLE_GUARANTEED_READ;
10552
#endif
10553
#if ENABLE_NON_DESTRUCTIVE_CALIB
10554
        gbl->phy_debug_mode_flags |= PHY_DEBUG_ENABLE_NON_DESTRUCTIVE_CALIBRATION;
10555
#endif
10556
 
10557
#if BFM_MODE
10558
        init_outfile();
10559
        bfm_set_globals_from_config();
10560
#endif
10561
 
10562
        // Initialize the register file
10563
        initialize_reg_file();
10564
 
10565
#if HPS_HW
10566
        // Initialize any PHY CSR
10567
        initialize_hps_phy();
10568
#endif
10569
 
10570
#if HHP_HPS
10571
        scc_mgr_initialize();
10572
#endif
10573
 
10574
#if USE_DQS_TRACKING
10575
        initialize_tracking();
10576
#endif
10577
 
10578
        // Initialize the TCL report. This must occur before any printf
10579
        // but after the debug mode flags and register file
10580
#if ENABLE_TCL_DEBUG
10581
        tclrpt_initialize(&my_debug_data);
10582
#endif
10583
 
10584
   // USER Enable all ranks, groups
10585
   for (i = 0; i < RW_MGR_MEM_NUMBER_OF_RANKS; i++) {
10586
                param->skip_ranks[i] = 0;
10587
        }
10588
        for (i = 0; i < NUM_SHADOW_REGS; ++i) {
10589
                param->skip_shadow_regs[i] = 0;
10590
        }
10591
        param->skip_groups = 0;
10592
 
10593
        IPRINT("Preparing to start memory calibration");
10594
 
10595
        TRACE_FUNC();
10596
        DPRINT(1, "%s%s %s ranks=%lu cs/dimm=%lu dq/dqs=%lu,%lu vg/dqs=%lu,%lu dqs=%lu,%lu dq=%lu dm=%lu "
10597
               "ptap_delay=%lu dtap_delay=%lu dtap_dqsen_delay=%lu, dll=%lu",
10598
               RDIMM ? "r" : (LRDIMM ? "l" : ""),
10599
               DDR2 ? "DDR2" : (DDR3 ? "DDR3" : (QDRII ? "QDRII" : (RLDRAMII ? "RLDRAMII" : (RLDRAM3 ? "RLDRAM3" : "??PROTO??")))),
10600
               FULL_RATE ? "FR" : (HALF_RATE ? "HR" : (QUARTER_RATE ? "QR" : "??RATE??")),
10601
               (long unsigned int)RW_MGR_MEM_NUMBER_OF_RANKS,
10602
               (long unsigned int)RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM,
10603
               (long unsigned int)RW_MGR_MEM_DQ_PER_READ_DQS,
10604
               (long unsigned int)RW_MGR_MEM_DQ_PER_WRITE_DQS,
10605
               (long unsigned int)RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS,
10606
               (long unsigned int)RW_MGR_MEM_VIRTUAL_GROUPS_PER_WRITE_DQS,
10607
               (long unsigned int)RW_MGR_MEM_IF_READ_DQS_WIDTH,
10608
               (long unsigned int)RW_MGR_MEM_IF_WRITE_DQS_WIDTH,
10609
               (long unsigned int)RW_MGR_MEM_DATA_WIDTH,
10610
               (long unsigned int)RW_MGR_MEM_DATA_MASK_WIDTH,
10611
               (long unsigned int)IO_DELAY_PER_OPA_TAP,
10612
               (long unsigned int)IO_DELAY_PER_DCHAIN_TAP,
10613
               (long unsigned int)IO_DELAY_PER_DQS_EN_DCHAIN_TAP,
10614
               (long unsigned int)IO_DLL_CHAIN_LENGTH);
10615
        DPRINT(1, "max values: en_p=%lu dqdqs_p=%lu en_d=%lu dqs_in_d=%lu io_in_d=%lu io_out1_d=%lu io_out2_d=%lu"
10616
               "dqs_in_reserve=%lu dqs_out_reserve=%lu",
10617
               (long unsigned int)IO_DQS_EN_PHASE_MAX,
10618
               (long unsigned int)IO_DQDQS_OUT_PHASE_MAX,
10619
               (long unsigned int)IO_DQS_EN_DELAY_MAX,
10620
               (long unsigned int)IO_DQS_IN_DELAY_MAX,
10621
               (long unsigned int)IO_IO_IN_DELAY_MAX,
10622
               (long unsigned int)IO_IO_OUT1_DELAY_MAX,
10623
               (long unsigned int)IO_IO_OUT2_DELAY_MAX,
10624
               (long unsigned int)IO_DQS_IN_RESERVE,
10625
               (long unsigned int)IO_DQS_OUT_RESERVE);
10626
 
10627
#if HCX_COMPAT_MODE || ENABLE_INST_ROM_WRITE
10628
        hc_initialize_rom_data();
10629
#endif  
10630
 
10631
#if !HARD_PHY
10632
        // Hard PHY does not support soft reset
10633
        IOWR_32DIRECT (RW_MGR_SOFT_RESET, 0, 0);
10634
#endif
10635
 
10636
        //USER update info for sims
10637
        reg_file_set_stage(CAL_STAGE_NIL);
10638
        reg_file_set_group(0);
10639
 
10640
        // Load global needed for those actions that require
10641
        // some dynamic calibration support
10642
#if HARD_PHY
10643
        dyn_calib_steps = STATIC_CALIB_STEPS;
10644
#else
10645
        dyn_calib_steps = IORD_32DIRECT(PHY_MGR_CALIB_SKIP_STEPS, 0);
10646
#endif
10647
 
10648
        // Load global to allow dynamic selection of delay loop settings
10649
        // based on calibration mode
10650
        if (!((DYNAMIC_CALIB_STEPS) & CALIB_SKIP_DELAY_LOOPS)) {
10651
                skip_delay_mask = 0xff;
10652
        } else {
10653
                skip_delay_mask = 0x0;
10654
        }
10655
 
10656
 
10657
#ifdef TEST_SIZE
10658
        if (!check_test_mem(1)) {
10659
                IOWR_32DIRECT (PHY_MGR_CAL_DEBUG_INFO, 0, 0x9090);
10660
                IOWR_32DIRECT (PHY_MGR_CAL_STATUS, 0, PHY_MGR_CAL_FAIL);
10661
        }
10662
        write_test_mem();
10663
        if (!check_test_mem(0)) {
10664
                IOWR_32DIRECT (PHY_MGR_CAL_DEBUG_INFO, 0, 0x9191);
10665
                IOWR_32DIRECT (PHY_MGR_CAL_STATUS, 0, PHY_MGR_CAL_FAIL);
10666
        }
10667
#endif
10668
 
10669
 
10670
#if HHP_HPS_SIMULATION
10671
        // configure controller
10672
        initialize_hps_controller();
10673
#endif
10674
 
10675
#if ENABLE_TCL_DEBUG && USE_USER_RDIMM_VALUE
10676
        tclrpt_loop();
10677
#endif
10678
 
10679
 
10680
#if ENABLE_NON_DES_CAL_TEST
10681
        rw_mgr_mem_initialize ();
10682
 
10683
//      IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_IDLE);
10684
//      IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_SELF_REFRESH);
10685
 
10686
        pass = run_mem_calibrate (1);
10687
 
10688
#else
10689
 
10690
#if ENABLE_NON_DES_CAL
10691
#if ENABLE_TCL_DEBUG
10692
        tclrpt_loop();
10693
#else
10694
        pass = run_mem_calibrate (1);
10695
#endif
10696
#else
10697
        pass = run_mem_calibrate ();
10698
#endif
10699
 
10700
#endif
10701
 
10702
#if TRACKING_WATCH_TEST
10703
        if (IORD_32DIRECT(REG_FILE_TRK_SAMPLE_CHECK, 0) == 0xEE) {
10704
                read_samples();
10705
        }
10706
#endif
10707
 
10708
#if ENABLE_PRINTF_LOG
10709
        IPRINT("Calibration complete");
10710
        // Send the end of transmission character
10711
        IPRINT("%c", 0x4);
10712
#endif
10713
 
10714
 
10715
 
10716
 
10717
#if BFM_MODE
10718
#if ENABLE_TCL_DEBUG
10719
        tclrpt_dump_internal_data();
10720
#endif
10721
        bfm_sequencer_is_done();
10722
#elif HHP_HPS_SIMULATION
10723
        // nothing to do for HPS simulation following calibration
10724
        while (1) {
10725
        }
10726
#elif ENABLE_TCL_DEBUG
10727
  #if HPS_HW
10728
        // EMPTY
10729
  #else
10730
        tclrpt_loop();
10731
  #endif
10732
#else
10733
  #if HPS_HW
10734
        // EMPTY
10735
  #else
10736
        while (1) {
10737
            user_init_cal_req();
10738
        }
10739
 
10740
  #endif
10741
#endif
10742
 
10743
 
10744
return pass;
10745
}
10746
 
10747
 
10748
#if ENABLE_BRINGUP_DEBUGGING
10749
 
10750
///////////////////////////////////////////////////////////////////////////////////////
10751
// Bring-Up test Support
10752
///////////////////////////////////////////////////////////////////////////////////////
10753
 
10754
 
10755
void do_bringup_test_guaranteed_write (void)
10756
{
10757
        alt_u32 r;
10758
 
10759
        TRACE_FUNC();
10760
 
10761
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
10762
                if (param->skip_ranks[r]) {
10763
                        //USER request to skip the rank
10764
 
10765
                        continue;
10766
                }
10767
 
10768
                //USER set rank
10769
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_READ_WRITE);
10770
 
10771
                //USER Load up a constant bursts
10772
 
10773
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 0x20);
10774
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_GUARANTEED_WRITE_0_1_A_5_WAIT0);
10775
 
10776
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 0x20);
10777
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_GUARANTEED_WRITE_0_1_A_5_WAIT1);
10778
 
10779
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_2, 0, 0x20);
10780
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_2, 0, __RW_MGR_GUARANTEED_WRITE_0_1_A_5_WAIT2);
10781
 
10782
                IOWR_32DIRECT (RW_MGR_LOAD_CNTR_3, 0, 0x20);
10783
                IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_3, 0, __RW_MGR_GUARANTEED_WRITE_0_1_A_5_WAIT3);
10784
 
10785
                IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, 0, __RW_MGR_GUARANTEED_WRITE_0_1_A_5);
10786
        }
10787
 
10788
        set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
10789
}
10790
 
10791
void do_bringup_test_clear_di_buf (alt_u32 group)
10792
{
10793
        IOWR_32DIRECT (PHY_MGR_CMD_FIFO_RESET, 0, 0);
10794
        IOWR_32DIRECT (RW_MGR_RESET_READ_DATAPATH, 0, 0);
10795
 
10796
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 128);
10797
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_DO_CLEAR_DI_BUF);
10798
 
10799
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, group << 2, __RW_MGR_DO_CLEAR_DI_BUF);
10800
}
10801
 
10802
void do_bringup_test_guaranteed_read (alt_u32 group)
10803
{
10804
        IOWR_32DIRECT (PHY_MGR_CMD_FIFO_RESET, 0, 0);
10805
        IOWR_32DIRECT (RW_MGR_RESET_READ_DATAPATH, 0, 0);
10806
 
10807
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_0, 0, 16);
10808
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_0, 0, __RW_MGR_DO_TEST_READ);
10809
        IOWR_32DIRECT (RW_MGR_LOAD_CNTR_1, 0, 16);
10810
        IOWR_32DIRECT (RW_MGR_LOAD_JUMP_ADD_1, 0, __RW_MGR_DO_TEST_READ_POST_WAIT);
10811
 
10812
        IOWR_32DIRECT (RW_MGR_RUN_SINGLE_GROUP, group << 2, __RW_MGR_DO_TEST_READ);
10813
}
10814
 
10815
void do_bringup_test ()
10816
{
10817
        int i;
10818
        alt_u32 group;
10819
        alt_u32 v = 0;
10820
 
10821
        group = 0;
10822
 
10823
        mem_config ();
10824
 
10825
        // 15 is the maximum latency (should make dependent on actual design
10826
        IOWR_32DIRECT (PHY_MGR_PHY_RLAT, 0, 15); /* lfifo setting */
10827
 
10828
#if ARRIAV || CYCLONEV
10829
        for (i = 0; i < RW_MGR_MEM_IF_READ_DQS_WIDTH; i++) {
10830
                IOWR_32DIRECT (SCC_MGR_GROUP_COUNTER, 0, i);
10831
                scc_set_bypass_mode(i, 0);
10832
        }
10833
#endif
10834
 
10835
        // initialize global buffer to something known
10836
        for (i = 0; i < sizeof(di_buf_gbl); i++) {
10837
                di_buf_gbl[i] = 0xee;
10838
        }
10839
 
10840
        // pre-increment vfifo to ensure not at max value
10841
        rw_mgr_incr_vfifo(group, &v);
10842
        rw_mgr_incr_vfifo(group, &v);
10843
 
10844
        do_bringup_test_clear_di_buf(group);
10845
 
10846
        while (1) {
10847
                do_bringup_test_guaranteed_write();
10848
                do_bringup_test_guaranteed_read(group);
10849
                load_di_buf_gbl();
10850
                rw_mgr_incr_vfifo(group, &v);
10851
        }
10852
}
10853
 
10854
 
10855
#endif // ENABLE_BRINGUP_DEBUGGING
10856
 
10857
#if ENABLE_ASSERT
10858
void err_report_internal_error
10859
(
10860
    const char* description,
10861
    const char* module,
10862
    const char* file,
10863
    int line
10864
)
10865
{
10866
    void *array[10];
10867
    size_t size;
10868
    char **strings;
10869
    size_t i;
10870
 
10871
    fprintf(stderr, ERR_IE_TEXT, module, file, line, description, "\n");
10872
 
10873
        size = backtrace (array, 10);
10874
        strings = backtrace_symbols (array, size);
10875
 
10876
        fprintf (stderr, "Obtained %zd stack frames.\n", size);
10877
 
10878
        for (i = 0; i < size; i++)
10879
        {
10880
                fprintf (stderr, "%s\n", strings[i]);
10881
        }
10882
 
10883
        free (strings);
10884
}
10885
#endif

powered by: WebSVN 2.1.0

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