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

Subversion Repositories openarty

[/] [openarty/] [trunk/] [sim/] [verilated/] [ddrsdramsim.cpp] - Blame information for rev 58

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 58 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    ddrsdramsim.cpp
4
//
5
// Project:     A wishbone controlled DDR3 SDRAM memory controller.
6
//
7
// Purpose:     
8
//
9
// Creator:     Dan Gisselquist, Ph.D.
10
//              Gisselquist Technology, LLC
11
//
12
////////////////////////////////////////////////////////////////////////////////
13
//
14
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
15
//
16
// This program is free software (firmware): you can redistribute it and/or
17
// modify it under the terms of  the GNU General Public License as published
18
// by the Free Software Foundation, either version 3 of the License, or (at
19
// your option) any later version.
20
//
21
// This program is distributed in the hope that it will be useful, but WITHOUT
22
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
23
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24
// for more details.
25
//
26
// You should have received a copy of the GNU General Public License along
27
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
28
// target there if the PDF file isn't present.)  If not, see
29
// <http://www.gnu.org/licenses/> for a copy.
30
//
31
// License:     GPL, v3, as defined and found on www.gnu.org,
32
//              http://www.gnu.org/licenses/gpl.html
33
//
34
//
35
////////////////////////////////////////////////////////////////////////////////
36
//
37
//
38
#include <stdio.h>
39
#include <assert.h>
40
 
41
#define PREFIX  "DDR3-SDRAM"
42
const unsigned ckCL = 11,
43
                ckRP = 11,
44
                ckRC = 10,
45
                ckRAS = 7,
46
                ckRFC = 320, // Clocks from refresh to activate
47
                ckREFI = 1560, // 7.8us @ 200MHz = 7.8e-6 * 200e6 = 1560
48
                DDR_MR2 = 0x040 | (((ckCL-5)&7)<<3),
49
                DDR_MR1 = 0x0844,
50
                DDR_MR0 = 0x0200 | (((ckCL-4)&0x07)<<4) | ((ckCL>11)?0x4:0);
51
/*
52
const unsigned  nREF = 4,
53
                ckREFIn = nREF*ckREFI - (nREF-1) * ckRFC;
54
*/
55
const unsigned  nREF = 1,
56
                ckREFIn = ckREFI;
57
 
58
#include "ddrsdramsim.h"
59
 
60
BANKINFO::BANKINFO(void) {
61
        m_state = 0; m_row = 0; m_wcounter = 0; m_min_time_before_precharge=0;
62
}
63
 
64
void    BANKINFO::tick(int cmd, unsigned addr) {
65
        if (m_wcounter)
66
                m_wcounter--;
67
        switch(cmd) {
68
                case DDR_REFRESH:
69
                        assert(m_state == 0);
70
                        break;
71
                case DDR_PRECHARGE:
72
                        // assert((m_state&((1<<ckRP)-1)) == ((1<<ckRP)-1));
73
                        m_state &= -2;
74
                        // While the specification allows precharging an already
75
                        // precharged bank, we can keep that from happening
76
                        // here:
77
                        // assert(m_state&7);
78
                        // Only problem is, this will currently break our
79
                        // refresh logic.
80
                        /*
81
                        if (m_min_time_before_precharge != 0) {
82
                                printf("BANK-FAIL: TIME-BEFORE-PRECHARGE = %d (should be zero)\n", m_min_time_before_precharge);
83
                                assert(m_min_time_before_precharge == 0);
84
                        } if (m_min_time_before_activate != 0) {
85
                                printf("BANK-FAIL: TIME-BEFORE-ACTIVATE = %d (should be zero)\n", m_min_time_before_activate);
86
                                assert(m_min_time_before_activate==0);
87
                        }
88
                        */
89
                        break;
90
                case DDR_ACTIVATE:
91
                        assert((m_state&((1<<ckRP)-1)) == 0);
92
                        if (((m_state&7)!=0)&&((addr&0x7fff) != m_row)) {
93
                                printf("BANK-FAIL: Attempt to Activate an already active bank without closing it first (m_state = %x)\n", m_state);
94
                                assert((m_state&7)==0);
95
                        }
96
 
97
                        /*
98
                        if (m_wcounter != 0) {
99
                                printf("BANK-FAIL: ACTIVATE too soon after write (wcounter = %d)\n", m_wcounter);
100
                                assert(m_wcounter == 0);
101
                        } if (m_min_time_before_activate!=0) {
102
                                printf("BANK-FAIL: ACTIVATE too soon after last activate, (ctr=%d)\n", m_min_time_before_activate);
103
                                assert(m_min_time_before_activate==0);
104
                        }
105
                        */
106
                        m_state = 1;
107
                        m_row = addr & 0x7fff;
108
                        m_min_time_before_precharge = ckRAS;
109
                        m_min_time_before_activate = ckRC;
110
                        break;
111
                case DDR_READ: case DDR_WRITE:
112
                        if (DDR_READ)
113
                                assert(m_wcounter == 0);
114
                        else
115
                                m_wcounter = 3+4+4;
116
                        if ((m_state&((1<<ckRP)-1)) != ((1<<ckRP)-1)) {
117
                                printf(PREFIX "::R/W Error: m_state = %08x, ckRP = %d (%08x)\n",
118
                                        m_state, ckRP, ((1<<ckRP)-1));
119
                                assert((m_state&((1<<ckRP)-1)) == ((1<<ckRP)-1));
120
                        }
121
                        if (m_min_time_before_precharge)
122
                                m_min_time_before_precharge--;
123
                        if (m_min_time_before_activate)
124
                                m_min_time_before_activate--;
125
                        break;
126
                case DDR_ZQS:
127
                        assert((m_state&((1<<ckRP)-1)) == 0);
128
                        if (m_min_time_before_precharge)
129
                                m_min_time_before_precharge--;
130
                        if (m_min_time_before_activate)
131
                                m_min_time_before_activate--;
132
                        break;
133
                case DDR_NOOP:
134
                        m_state <<= 1;
135
                        m_state |= (m_state&2)>>1;
136
                        m_state &= ((1<<ckRP)-1);
137
                        if (m_min_time_before_precharge)
138
                                m_min_time_before_precharge--;
139
                        if (m_min_time_before_activate)
140
                                m_min_time_before_activate--;
141
                        break;
142
                default:
143
                        break;
144
        }
145
}
146
 
147
int gbl_state, gbl_counts;
148
 
149
DDRSDRAMSIM::DDRSDRAMSIM(int lglen) {
150
        m_memlen = (1<<(lglen-2));
151
        m_mem = new unsigned[m_memlen];
152
        m_reset_state = 0;
153
        m_reset_counts= 0;
154
        assert(NTIMESLOTS > ckCL+3);
155
        m_bus = new BUSTIMESLOT[NTIMESLOTS];
156
        for(int i=0; i<NTIMESLOTS; i++)
157
                m_bus[i].m_used = 0;
158
        for(int i=0; i<NTIMESLOTS; i++)
159
                m_bus[i].m_rtt = 0;
160
        m_busloc = 0;
161
}
162
 
163
unsigned DDRSDRAMSIM::operator()(int reset_n, int cke,
164
                int csn, int rasn, int casn, int wen,
165
                int dqs, int dm, int odt, int busoe,
166
                int addr, int ba, int data) {
167
        BUSTIMESLOT     *ts, *nxtts;
168
        int     cmd = (reset_n?0:32)|(cke?0:16)|(csn?8:0)
169
                        |(rasn?4:0)|(casn?2:0)|(wen?1:0);
170
 
171
        if ((m_reset_state!=0)&&(reset_n==0)) {
172
                m_reset_state = 0;
173
                m_reset_counts = 0;
174
        } else if (m_reset_state < 16) {
175
                switch(m_reset_state) {
176
                case 0:
177
                        m_reset_counts++;
178
                        if (reset_n) {
179
                                assert(m_reset_counts > 40000);
180
                                m_reset_counts = 0;
181
                                m_reset_state = 1;
182
                        } break;
183
                case 1:
184
                        m_reset_counts++;
185
                        if (cke) {
186
                                assert(m_reset_counts > 100000);
187
                                m_reset_counts = 0;
188
                                m_reset_state = 2;
189
                        } break;
190
                case 2:
191
                        m_reset_counts++;
192
                        assert(cke);
193
                        if (cmd != DDR_NOOP) {
194
                                assert(m_reset_counts > 147);
195
                                m_reset_counts = 0;
196
                                m_reset_state = 3;
197
                                assert(cmd == DDR_MRSET);
198
                                // Set MR2
199
                                assert(ba == 2);
200
                                assert(addr == DDR_MR2);
201
                        } break;
202
                case 3:
203
                        m_reset_counts++;
204
                        assert(cke);
205
                        if (cmd != DDR_NOOP) {
206
                                // assert(m_reset_counts > 3);
207
                                m_reset_counts = 0;
208
                                m_reset_state = 4;
209
                                assert(cmd == DDR_MRSET);
210
                                // Set MR1
211
                                assert(ba == 1);
212
                                assert(addr == DDR_MR1);
213
                        } break;
214
                case 4:
215
                        m_reset_counts++;
216
                        assert(cke);
217
                        if (cmd != DDR_NOOP) {
218
                                printf(PREFIX "::RESET-CMD[4]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
219
                                assert(m_reset_counts > 3);
220
                                m_reset_counts = 0;
221
                                m_reset_state = 5;
222
                                assert(cmd == DDR_MRSET);
223
                                // Set MR0
224
                                assert(ba == 0);
225
                                assert(addr == DDR_MR0);
226
                        } break;
227
                case 5:
228
                        m_reset_counts++;
229
                        assert(cke);
230
                        if (cmd != DDR_NOOP) {
231
                                printf(PREFIX "::RESET-CMD[5]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
232
                                assert(m_reset_counts > 11);
233
                                m_reset_counts = 0;
234
                                m_reset_state = 6;
235
                                assert(cmd == DDR_ZQS);
236
                                assert(addr == 0x400);
237
                        } break;
238
                case 6:
239
                        m_reset_counts++;
240
                        assert(cke);
241
                        if (cmd != DDR_NOOP) {
242
                                printf(PREFIX "::RESET-CMD[6]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
243
                                assert(m_reset_counts > 512);
244
                                m_reset_counts = 0;
245
                                m_reset_state = 7;
246
                                assert(cmd == DDR_PRECHARGE);
247
                                assert(addr == 0x400);
248
                        } break;
249
                case 7:
250
                        m_reset_counts++;
251
                        assert(cke);
252
                        if (cmd != DDR_NOOP) {
253
                                printf(PREFIX "::RESET-CMD[7]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
254
                                assert(m_reset_counts > 3);
255
                                m_reset_counts = 0;
256
                                m_reset_state = 8;
257
                                assert(cmd == DDR_REFRESH);
258
                                m_clocks_since_refresh = 0;
259
                        } break;
260
                case 8:
261
                        m_reset_counts++;
262
                        assert(cke);
263
                        assert(cmd == DDR_NOOP);
264
                        if (m_reset_counts > 140) {
265
                                m_reset_state = 16;
266
                                printf(PREFIX ": Leaving reset state\n");
267
                        }
268
                        break;
269
                default:
270
                        break;
271
                }
272
 
273
                gbl_state = m_reset_state;
274
                gbl_counts= m_reset_counts;
275
                m_nrefresh_issued = nREF;
276
                m_clocks_since_refresh++;
277
                for(int i=0; i<NBANKS; i++)
278
                        m_bank[i].tick(cmd, 0);
279
        } else if (!cke) {
280
                assert(0&&"Clock not enabled!");
281
        } else if ((cmd == DDR_REFRESH)||(m_nrefresh_issued < (int)nREF)) {
282
                if (DDR_REFRESH == cmd) {
283
                        m_clocks_since_refresh = 0;
284
                        if (m_nrefresh_issued >= (int)nREF)
285
                                m_nrefresh_issued = 1;
286
                        else
287
                                m_nrefresh_issued++;
288
                } else {
289
                        m_clocks_since_refresh++;
290
                        assert(DDR_NOOP == cmd);
291
                }
292
                for(int i=0; i<NBANKS; i++)
293
                        m_bank[i].tick(cmd,0);
294
 
295
                if (m_nrefresh_issued == nREF)
296
                        printf(PREFIX "::Refresh cycle complete\n");
297
        } else {
298
                // In operational mode!!
299
 
300
                m_clocks_since_refresh++;
301
                assert(m_clocks_since_refresh < (int)ckREFIn);
302
                switch(cmd) {
303
                case DDR_MRSET:
304
                        assert(0&&"Modes should only be set in reset startup");
305
                        for(int i=0; i<NBANKS; i++)
306
                                m_bank[i].tick(DDR_MRSET,0);
307
                        break;
308
                case DDR_REFRESH:
309
                        for(int i=0; i<NBANKS; i++)
310
                                m_bank[i].tick(DDR_REFRESH,0);
311
                        m_clocks_since_refresh = 0;
312
                        assert(0 && "Internal err: Refresh should be handled above");
313
                        break;
314
                case DDR_PRECHARGE:
315
                        if (addr & 0x400) {
316
                                // Precharge all
317
                                for(int i=0; i<NBANKS; i++)
318
                                        m_bank[i].tick(DDR_PRECHARGE,0);
319
                        } else {
320
                                m_bank[ba].tick(DDR_PRECHARGE,0);
321
                                for(int i=0; i<NBANKS; i++)
322
                                        if (ba != i)
323
                                                m_bank[i].tick(DDR_NOOP,0);
324
                        }
325
                        break;
326
                case DDR_ACTIVATE:
327
                        if (m_clocks_since_refresh < (int)ckRFC) {
328
                                printf(PREFIX "::ACTIVATE -- not enough clocks since refresh, %d < %d should be true\n", m_clocks_since_refresh, ckRFC);
329
                                assert(m_clocks_since_refresh >= (int)ckRFC);
330
                        }
331
                        printf(PREFIX "::Activating bank %d, address %08x\n", ba, addr);
332
                        m_bank[ba].tick(DDR_ACTIVATE,addr);
333
                        for(int i=0; i<NBANKS; i++)
334
                                if (i!=ba) m_bank[i].tick(DDR_NOOP,0);
335
                        break;
336
                case DDR_WRITE:
337
                        {
338
                                // This SIM doesn't handle out of order writes
339
                                assert((addr&7)==0);
340
                                m_bank[ba].tick(DDR_WRITE, addr);
341
                                for(int i=0; i<NBANKS; i++)
342
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
343
                                unsigned caddr = m_bank[ba].m_row;
344
                                caddr <<= 3;
345
                                caddr |= ba;
346
                                caddr <<= 10;
347
                                caddr |= addr;
348
                                caddr &= ~7;
349
                                caddr >>= 1;
350
 
351
                                BUSTIMESLOT *tp;
352
                                int     offset = m_busloc+ckCL+1;
353
 
354
                                tp = &m_bus[(offset+0)&(NTIMESLOTS-1)];
355
                                // printf("Setting bus timeslots from (now=%d)+%d=%d to now+%d+3\n", m_busloc, ckCL,(m_busloc+ckCL)&(NTIMESLOTS-1), ckCL);
356
                                tp->m_addr = caddr  ;
357
                                tp->m_used = 1;
358
                                tp->m_read = 0;
359
 
360
                                tp = &m_bus[(offset+1)&(NTIMESLOTS-1)];
361
                                tp->m_addr = caddr+1;
362
                                tp->m_used = 1;
363
                                tp->m_read = 0;
364
 
365
                                tp = &m_bus[(offset+2)&(NTIMESLOTS-1)];
366
                                tp->m_addr = caddr+2;
367
                                tp->m_used = 1;
368
                                tp->m_read = 0;
369
 
370
                                tp = &m_bus[(offset+3)&(NTIMESLOTS-1)];
371
                                tp->m_addr = caddr+3;
372
                                tp->m_used = 1;
373
                                tp->m_read = 0;
374
                        } break;
375
                case DDR_READ:
376
                        {
377
                                // This SIM doesn't handle out of order reads
378
                                assert((addr&7)==0);
379
                                m_bank[ba].tick(DDR_READ, addr);
380
                                for(int i=0; i<NBANKS; i++)
381
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
382
                                unsigned caddr = m_bank[ba].m_row;
383
                                caddr <<= 3;
384
                                caddr |= ba;
385
                                caddr <<= 10;
386
                                caddr |= addr;
387
                                caddr &= ~7;
388
                                caddr >>= 1;
389
 
390
                                BUSTIMESLOT *tp;
391
 
392
                                int offset = (m_busloc+ckCL+1)&(NTIMESLOTS-1);
393
                                tp = &m_bus[(offset)&(NTIMESLOTS-1)];
394
                                tp->m_data = m_mem[caddr];
395
                                tp->m_addr = caddr;
396
                                tp->m_used = 1;
397
                                tp->m_read = 1;
398
 
399
                                tp = &m_bus[(offset+1)&(NTIMESLOTS-1)];
400
                                tp->m_data = m_mem[caddr+1];
401
                                tp->m_addr = caddr+1;
402
                                tp->m_used = 1;
403
                                tp->m_read = 1;
404
 
405
                                tp = &m_bus[(offset+2)&(NTIMESLOTS-1)];
406
                                tp->m_data = m_mem[caddr+2];
407
                                tp->m_addr = caddr+2;
408
                                tp->m_used = 1;
409
                                tp->m_read = 1;
410
 
411
                                tp = &m_bus[(offset+3)&(NTIMESLOTS-1)];
412
                                tp->m_data = m_mem[caddr+3];
413
                                tp->m_addr = caddr+3;
414
                                tp->m_used = 1;
415
                                tp->m_read = 1;
416
                        } break;
417
                case DDR_ZQS:
418
                        assert(0&&"Sim does not support ZQS outside of startup");
419
                        break;
420
                case DDR_NOOP:
421
                        for(int i=0; i<NBANKS; i++)
422
                                m_bank[i].tick(DDR_NOOP,addr);
423
                        break;
424
                default: // We are deselecteda
425
                        for(int i=0; i<NBANKS; i++)
426
                                m_bank[i].tick(DDR_NOOP,addr);
427
                        break;
428
                }
429
 
430
                if (false) {
431
                        bool flag = false;
432
                        for(int i=0; i<5; i++) {
433
                                int bl = (m_busloc+1+i)&(NTIMESLOTS-1);
434
                                nxtts = &m_bus[bl];
435
                                if (nxtts->m_used) {
436
                                        flag = true;
437
                                        break;
438
                                }
439
                        } if (flag) {
440
                        printf("DQS = %d BUSLOC = %d\n", dqs, (m_busloc+1)&(NTIMESLOTS-1));
441
                        for(int i=0; i<5; i++) {
442
                                int bl = (m_busloc+1+i)&(NTIMESLOTS-1);
443
                                nxtts = &m_bus[bl];
444
                                printf("BUS[%2d] ", bl);
445
                                if (nxtts->m_used)
446
                                        printf(" USED");
447
                                if (nxtts->m_read)
448
                                        printf(" READ");
449
                                if (nxtts->m_rtt)
450
                                        printf(" RTT");
451
                                printf("\n");
452
                        }}
453
                }
454
 
455
                ts = &m_bus[(m_busloc+1)&(NTIMESLOTS-1)];
456
                if (dqs)
457
                        assert((ts->m_rtt)&&(m_last_rtt));
458
                else if (!m_last_dqs)
459
                        assert(!m_last_rtt);
460
        }
461
 
462
        m_busloc = (m_busloc+1)&(NTIMESLOTS-1);
463
 
464
        ts = &m_bus[m_busloc];
465
        nxtts = &m_bus[(m_busloc+1)&(NTIMESLOTS-1)];
466
        unsigned vl = ts->m_data;
467
        assert( ((!ts->m_used)||(busoe))
468
                || ((ts->m_used)&&(ts->m_read)&&(!busoe))
469
                || ((ts->m_used)&&(!ts->m_read)&&(busoe))
470
                );
471
 
472
        m_last_dqs = dqs;
473
        m_last_rtt = ts->m_rtt;
474
 
475
        if (ts->m_used) {
476
                if (ts->m_read)
477
                        assert((!dqs)&&(!m_last_dqs));
478
                else
479
                        assert((dqs) && (m_last_dqs));
480
        } else if (!nxtts->m_used)
481
                assert(!dqs);
482
 
483
        assert((!ts->m_used)||(ts->m_addr < (unsigned)m_memlen));
484
        if ((ts->m_used)&&(!ts->m_read)&&(!dm)) {
485
                printf(PREFIX "::Setting MEM[%08x] = %08x\n", ts->m_addr, data);
486
                m_mem[ts->m_addr] = data;
487
        }
488
 
489
        m_bus[(m_busloc+3)&(NTIMESLOTS-1)].m_rtt = (odt)&&(reset_n);
490
        ts->m_used = 0;
491
        ts->m_read = 0;
492
        ts->m_addr = -1;
493
        ts->m_rtt  = 0;
494
        return (!busoe)?vl:data;
495
}
496
 

powered by: WebSVN 2.1.0

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