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

Subversion Repositories wbddr3

[/] [wbddr3/] [trunk/] [bench/] [cpp/] [ddrsdramsim.cpp] - Blame information for rev 5

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 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
const unsigned ckCL = 5,
42
                ckRC = 3;
43
 
44
#include "ddrsdramsim.h"
45
void    BANKINFO::tick(int cmd, unsigned addr) {
46
        switch(cmd) {
47
                case DDR_PRECHARGE:
48
                        m_state <<= 1;
49
                        // m_state |= 1;
50
                        m_state &= 6;
51
                        break;
52
                case DDR_ACTIVATE:
53
                        m_state <<= 1;
54
                        m_state |= 1;
55
                        m_state &= 7;
56
                        m_row = addr & 0x7fff;
57
                        break;
58
                case DDR_READ: case DDR_WRITE:
59
                        assert((m_state&7) == 7);
60
                        break;
61
                case DDR_ZQS:
62
                        assert((m_state&7) == 0);
63
                        break;
64
                case DDR_NOOP:
65
                        m_state <<= 1;
66
                        m_state |= (m_state&2)>>1;
67
                        break;
68
                default:
69
                        break;
70
        }
71
}
72
 
73
int gbl_state, gbl_counts;
74
 
75
DDRSDRAMSIM::DDRSDRAMSIM(int lglen) {
76
        m_memlen = (1<<(lglen-2));
77
        m_mem = new unsigned[m_memlen];
78
        m_reset_state = 0;
79
        m_reset_counts= 0;
80
        m_bus = new BUSTIMESLOT[NTIMESLOTS];
81
        for(int i=0; i<NTIMESLOTS; i++)
82
                m_bus[i].m_used = 0;
83
        m_busloc = 0;
84
}
85
 
86
unsigned DDRSDRAMSIM::operator()(int reset_n, int cke,
87
                int csn, int rasn, int casn, int wen,
88
                int dqs, int dm, int odt, int busoe,
89
                int addr, int ba, int data) {
90
 
91
        int     cmd = (reset_n?0:32)|(cke?0:16)|(csn?8:0)
92
                        |(rasn?4:0)|(casn?2:0)|(wen?1:0);
93
        if ((m_reset_state!=0)&&(reset_n==0)) {
94
                m_reset_state = 0;
95
                m_reset_counts = 0;
96
        } else if (m_reset_state < 16) {
97
                switch(m_reset_state) {
98
                case 0:
99
                        m_reset_counts++;
100
                        if (reset_n) {
101
                                assert(m_reset_counts > 40000);
102
                                m_reset_counts = 0;
103
                                m_reset_state = 1;
104
                        } break;
105
                case 1:
106
                        m_reset_counts++;
107
                        if (cke) {
108
                                assert(m_reset_counts > 100000);
109
                                m_reset_counts = 0;
110
                                m_reset_state = 2;
111
                        } break;
112
                case 2:
113
                        m_reset_counts++;
114
                        if (cmd != DDR_NOOP) {
115
                                assert(m_reset_counts > 147);
116
                                m_reset_counts = 0;
117
                                m_reset_state = 3;
118
                                assert(cmd == DDR_MRSET);
119
                                assert(ba == 2);
120
                                assert(addr == 0x040);
121
                        } break;
122
                case 3:
123
                        m_reset_counts++;
124
                        if (cmd != DDR_NOOP) {
125 5 dgisselq
                                // assert(m_reset_counts > 3);
126 4 dgisselq
                                m_reset_counts = 0;
127
                                m_reset_state = 4;
128
                                assert(cmd == DDR_MRSET);
129 5 dgisselq
                                // assert(ba == 1);
130
                                // assert(addr == 0x847);
131 4 dgisselq
                        } break;
132
                case 4:
133
                        m_reset_counts++;
134
                        if (cmd != DDR_NOOP) {
135 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[4]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
136 4 dgisselq
                                assert(m_reset_counts > 3);
137
                                m_reset_counts = 0;
138
                                m_reset_state = 5;
139
                                assert(cmd == DDR_MRSET);
140
                                assert(ba == 0);
141
                                assert(addr == 0x210);
142
                        } break;
143
                case 5:
144
                        m_reset_counts++;
145
                        if (cmd != DDR_NOOP) {
146 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[5]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
147
                                assert(m_reset_counts > 11);
148 4 dgisselq
                                m_reset_counts = 0;
149
                                m_reset_state = 6;
150
                                assert(cmd == DDR_ZQS);
151 5 dgisselq
                                assert(addr == 0x400);
152 4 dgisselq
                        } break;
153
                case 6:
154
                        m_reset_counts++;
155
                        if (cmd != DDR_NOOP) {
156 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[6]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
157 4 dgisselq
                                assert(m_reset_counts > 512);
158
                                m_reset_counts = 0;
159
                                m_reset_state = 7;
160
                                assert(cmd == DDR_PRECHARGE);
161 5 dgisselq
                                assert(addr == 0x400);
162 4 dgisselq
                        } break;
163
                case 7:
164
                        m_reset_counts++;
165
                        if (cmd != DDR_NOOP) {
166 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[7]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
167 4 dgisselq
                                assert(m_reset_counts > 3);
168
                                m_reset_counts = 0;
169
                                m_reset_state = 8;
170
                                assert(cmd == DDR_REFRESH);
171
                        } break;
172
                case 8:
173
                        m_reset_counts++;
174
                        assert(cmd == DDR_NOOP);
175 5 dgisselq
                        if (m_reset_counts > 140) {
176 4 dgisselq
                                m_reset_state = 16;
177 5 dgisselq
                                printf("DDR3-SDRAM: Leaving reset state\n");
178
                        }
179 4 dgisselq
                        break;
180
                default:
181
                        break;
182
                }
183
 
184
                gbl_state = m_reset_state;
185
                gbl_counts= m_reset_counts;
186
        } else if (cke == 0) {
187
                assert(0&&"Clock not enabled!");
188
        } else switch(cmd) {
189
                case DDR_MRSET:
190
                        assert(0&&"Modes should only be set in reset startup");
191
                        for(int i=0; i<NBANKS; i++)
192
                                m_bank[i].tick(DDR_MRSET,0);
193
                        break;
194
                case DDR_REFRESH:
195
                        for(int i=0; i<NBANKS; i++)
196
                                m_bank[i].tick(DDR_REFRESH,0);
197
                        break;
198
                case DDR_PRECHARGE:
199
                        if (addr & 0x40) {
200
                                // Precharge all
201
                                for(int i=0; i<NBANKS; i++)
202
                                        m_bank[i].tick(DDR_PRECHARGE,0);
203
                        } else {
204
                                m_bank[ba].tick(DDR_PRECHARGE,0);
205
                                for(int i=0; i<NBANKS; i++)
206
                                        if (ba != i)
207
                                                m_bank[i].tick(DDR_NOOP,0);
208
                        }
209
                        break;
210
                case DDR_ACTIVATE:
211
                        m_bank[ba].tick(DDR_ACTIVATE,addr);
212
                        for(int i=0; i<NBANKS; i++)
213
                                if (i!=ba) m_bank[i].tick(DDR_NOOP,0);
214
                        break;
215
                case DDR_WRITE:
216
                        {
217
                                for(int i=0; i<NBANKS; i++)
218
                                        m_bank[i].tick(DDR_WRITE,addr);
219
                                unsigned addr = m_bank[ba].m_row;
220
                                addr <<= 13;
221
                                addr |= ba;
222
                                addr <<= 10;
223
                                addr |= addr;
224
                                addr &= ~3;
225
 
226
                                BUSTIMESLOT *tp;
227
 
228
                                tp = &m_bus[(m_busloc+ckCL+0)&(NTIMESLOTS-1)];
229
                                tp->m_addr = addr  ;
230
                                tp->m_used = 1;
231
                                tp->m_read = 0;
232
 
233
                                tp = &m_bus[(m_busloc+ckCL+1)&(NTIMESLOTS-1)];
234
                                tp->m_addr = addr+1;
235
                                tp->m_used = 1;
236
                                tp->m_read = 0;
237
 
238
                                tp = &m_bus[(m_busloc+ckCL+2)&(NTIMESLOTS-1)];
239
                                tp->m_addr = addr+2;
240
                                tp->m_used = 1;
241
                                tp->m_read = 0;
242
 
243
                                tp = &m_bus[(m_busloc+ckCL+3)&(NTIMESLOTS-1)];
244
                                tp->m_addr = addr+3;
245
                                tp->m_used = 1;
246
                                tp->m_read = 0;
247
                        } break;
248
                case DDR_READ:
249
                        {
250
                                for(int i=0; i<NBANKS; i++)
251
                                        m_bank[i].tick(DDR_READ,addr);
252
                                unsigned addr = m_bank[ba].m_row;
253
                                addr <<= 13;
254
                                addr |= ba;
255
                                addr <<= 10;
256
                                addr |= addr;
257
                                addr &= ~3;
258
 
259
                                BUSTIMESLOT *tp;
260
 
261
                                tp = &m_bus[(m_busloc+ckCL+0)&(NTIMESLOTS-1)];
262
                                tp->m_data = m_mem[addr];
263
                                tp->m_addr = addr;
264
                                tp->m_used = 1;
265
                                tp->m_read = 1;
266
 
267
                                tp = &m_bus[(m_busloc+ckCL+1)&(NTIMESLOTS-1)];
268
                                tp->m_data = m_mem[addr+1];
269
                                tp->m_addr = addr+1;
270
                                tp->m_used = 1;
271
                                tp->m_read = 1;
272
 
273
                                tp = &m_bus[(m_busloc+ckCL+2)&(NTIMESLOTS-1)];
274
                                tp->m_data = m_mem[addr+2];
275
                                tp->m_addr = addr+2;
276
                                tp->m_used = 1;
277
                                tp->m_read = 1;
278
 
279
                                tp = &m_bus[(m_busloc+ckCL+3)&(NTIMESLOTS-1)];
280
                                tp->m_data = m_mem[addr+3];
281
                                tp->m_addr = addr+3;
282
                                tp->m_used = 1;
283
                                tp->m_read = 1;
284
                        } break;
285
                case DDR_ZQS:
286
                        assert(0&&"Sim does not support ZQS outside of startup");
287
                        break;
288
                case DDR_NOOP:
289
                        for(int i=0; i<NBANKS; i++)
290
                                m_bank[i].tick(DDR_NOOP,addr);
291
                        break;
292
                default: // We are deselecteda
293
                        for(int i=0; i<NBANKS; i++)
294
                                m_bank[i].tick(DDR_NOOP,addr);
295
                        break;
296
        }
297
 
298
        m_busloc = (m_busloc+1)&(NTIMESLOTS-1);
299
 
300
        BUSTIMESLOT     *ts = &m_bus[m_busloc];
301
        unsigned vl = ts->m_data;
302
        assert( ((!ts->m_used)||(busoe))
303
                || ((ts->m_used)&&(ts->m_read)));
304
 
305
        assert((!ts->m_used)||(ts->m_addr < (unsigned)m_memlen));
306
        if ((ts->m_used)&&(!ts->m_read)&&(!dm))
307
                m_mem[ts->m_addr] = data;
308
        ts->m_used = 0;
309
        ts->m_read = 0;
310
        ts->m_addr = -1;
311
        return (!busoe)?vl:data;
312
}
313
 

powered by: WebSVN 2.1.0

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