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

Subversion Repositories wbddr3

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

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
                                assert(m_reset_counts > 3);
126
                                m_reset_counts = 0;
127
                                m_reset_state = 4;
128
                                assert(cmd == DDR_MRSET);
129
                                assert(ba == 1);
130
                                assert(addr == 0x847);
131
                        } break;
132
                case 4:
133
                        m_reset_counts++;
134
                        if (cmd != DDR_NOOP) {
135
                                assert(m_reset_counts > 3);
136
                                m_reset_counts = 0;
137
                                m_reset_state = 5;
138
                                assert(cmd == DDR_MRSET);
139
                                assert(ba == 0);
140
                                assert(addr == 0x210);
141
                        } break;
142
                case 5:
143
                        m_reset_counts++;
144
                        if (cmd != DDR_NOOP) {
145
                                assert(m_reset_counts > 12);
146
                                m_reset_counts = 0;
147
                                m_reset_state = 6;
148
                                assert(cmd == DDR_ZQS);
149
                                assert(addr == 0x40);
150
                        } break;
151
                case 6:
152
                        m_reset_counts++;
153
                        if (cmd != DDR_NOOP) {
154
                                assert(m_reset_counts > 512);
155
                                m_reset_counts = 0;
156
                                m_reset_state = 7;
157
                                assert(cmd == DDR_PRECHARGE);
158
                                assert(addr == 0x40);
159
                        } break;
160
                case 7:
161
                        m_reset_counts++;
162
                        if (cmd != DDR_NOOP) {
163
                                assert(m_reset_counts > 3);
164
                                m_reset_counts = 0;
165
                                m_reset_state = 8;
166
                                assert(cmd == DDR_REFRESH);
167
                        } break;
168
                case 8:
169
                        m_reset_counts++;
170
                        assert(cmd == DDR_NOOP);
171
                        if (m_reset_counts > 140)
172
                                m_reset_state = 16;
173
                        break;
174
                default:
175
                        break;
176
                }
177
 
178
                gbl_state = m_reset_state;
179
                gbl_counts= m_reset_counts;
180
        } else if (cke == 0) {
181
                assert(0&&"Clock not enabled!");
182
        } else switch(cmd) {
183
                case DDR_MRSET:
184
                        assert(0&&"Modes should only be set in reset startup");
185
                        for(int i=0; i<NBANKS; i++)
186
                                m_bank[i].tick(DDR_MRSET,0);
187
                        break;
188
                case DDR_REFRESH:
189
                        for(int i=0; i<NBANKS; i++)
190
                                m_bank[i].tick(DDR_REFRESH,0);
191
                        break;
192
                case DDR_PRECHARGE:
193
                        if (addr & 0x40) {
194
                                // Precharge all
195
                                for(int i=0; i<NBANKS; i++)
196
                                        m_bank[i].tick(DDR_PRECHARGE,0);
197
                        } else {
198
                                m_bank[ba].tick(DDR_PRECHARGE,0);
199
                                for(int i=0; i<NBANKS; i++)
200
                                        if (ba != i)
201
                                                m_bank[i].tick(DDR_NOOP,0);
202
                        }
203
                        break;
204
                case DDR_ACTIVATE:
205
                        m_bank[ba].tick(DDR_ACTIVATE,addr);
206
                        for(int i=0; i<NBANKS; i++)
207
                                if (i!=ba) m_bank[i].tick(DDR_NOOP,0);
208
                        break;
209
                case DDR_WRITE:
210
                        {
211
                                for(int i=0; i<NBANKS; i++)
212
                                        m_bank[i].tick(DDR_WRITE,addr);
213
                                unsigned addr = m_bank[ba].m_row;
214
                                addr <<= 13;
215
                                addr |= ba;
216
                                addr <<= 10;
217
                                addr |= addr;
218
                                addr &= ~3;
219
 
220
                                BUSTIMESLOT *tp;
221
 
222
                                tp = &m_bus[(m_busloc+ckCL+0)&(NTIMESLOTS-1)];
223
                                tp->m_addr = addr  ;
224
                                tp->m_used = 1;
225
                                tp->m_read = 0;
226
 
227
                                tp = &m_bus[(m_busloc+ckCL+1)&(NTIMESLOTS-1)];
228
                                tp->m_addr = addr+1;
229
                                tp->m_used = 1;
230
                                tp->m_read = 0;
231
 
232
                                tp = &m_bus[(m_busloc+ckCL+2)&(NTIMESLOTS-1)];
233
                                tp->m_addr = addr+2;
234
                                tp->m_used = 1;
235
                                tp->m_read = 0;
236
 
237
                                tp = &m_bus[(m_busloc+ckCL+3)&(NTIMESLOTS-1)];
238
                                tp->m_addr = addr+3;
239
                                tp->m_used = 1;
240
                                tp->m_read = 0;
241
                        } break;
242
                case DDR_READ:
243
                        {
244
                                for(int i=0; i<NBANKS; i++)
245
                                        m_bank[i].tick(DDR_READ,addr);
246
                                unsigned addr = m_bank[ba].m_row;
247
                                addr <<= 13;
248
                                addr |= ba;
249
                                addr <<= 10;
250
                                addr |= addr;
251
                                addr &= ~3;
252
 
253
                                BUSTIMESLOT *tp;
254
 
255
                                tp = &m_bus[(m_busloc+ckCL+0)&(NTIMESLOTS-1)];
256
                                tp->m_data = m_mem[addr];
257
                                tp->m_addr = addr;
258
                                tp->m_used = 1;
259
                                tp->m_read = 1;
260
 
261
                                tp = &m_bus[(m_busloc+ckCL+1)&(NTIMESLOTS-1)];
262
                                tp->m_data = m_mem[addr+1];
263
                                tp->m_addr = addr+1;
264
                                tp->m_used = 1;
265
                                tp->m_read = 1;
266
 
267
                                tp = &m_bus[(m_busloc+ckCL+2)&(NTIMESLOTS-1)];
268
                                tp->m_data = m_mem[addr+2];
269
                                tp->m_addr = addr+2;
270
                                tp->m_used = 1;
271
                                tp->m_read = 1;
272
 
273
                                tp = &m_bus[(m_busloc+ckCL+3)&(NTIMESLOTS-1)];
274
                                tp->m_data = m_mem[addr+3];
275
                                tp->m_addr = addr+3;
276
                                tp->m_used = 1;
277
                                tp->m_read = 1;
278
                        } break;
279
                case DDR_ZQS:
280
                        assert(0&&"Sim does not support ZQS outside of startup");
281
                        break;
282
                case DDR_NOOP:
283
                        for(int i=0; i<NBANKS; i++)
284
                                m_bank[i].tick(DDR_NOOP,addr);
285
                        break;
286
                default: // We are deselecteda
287
                        for(int i=0; i<NBANKS; i++)
288
                                m_bank[i].tick(DDR_NOOP,addr);
289
                        break;
290
        }
291
 
292
        m_busloc = (m_busloc+1)&(NTIMESLOTS-1);
293
 
294
        BUSTIMESLOT     *ts = &m_bus[m_busloc];
295
        unsigned vl = ts->m_data;
296
        assert( ((!ts->m_used)||(busoe))
297
                || ((ts->m_used)&&(ts->m_read)));
298
 
299
        assert((!ts->m_used)||(ts->m_addr < (unsigned)m_memlen));
300
        if ((ts->m_used)&&(!ts->m_read)&&(!dm))
301
                m_mem[ts->m_addr] = data;
302
        ts->m_used = 0;
303
        ts->m_read = 0;
304
        ts->m_addr = -1;
305
        return (!busoe)?vl:data;
306
}
307
 

powered by: WebSVN 2.1.0

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