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

Subversion Repositories xulalx25soc

[/] [xulalx25soc/] [trunk/] [rtl/] [wbsdram.v] - Blame information for rev 38

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

Line No. Rev Author Line
1 2 dgisselq
///////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    wbsdram.v
4
//
5
// Project:     XuLA2 board
6
//
7
// Purpose:     Provide 32-bit wishbone access to the SDRAM memory on a XuLA2
8
//              LX-25 board.  Specifically, on each access, the controller will
9
//      activate an appropriate bank of RAM (the SDRAM has four banks), and
10
//      then issue the read/write command.  In the case of walking off the
11
//      bank, the controller will activate the next bank before you get to it.
12
//      Upon concluding any wishbone access, all banks will be precharged and
13
//      returned to idle.
14
//
15
//      This particular implementation represents a second generation version
16
//      because my first version was too complex.  To speed things up, this
17
//      version includes an extra wait state where the wishbone inputs are
18
//      clocked into a flip flop before any action is taken on them.
19
//
20
// Creator:     Dan Gisselquist, Ph.D.
21
//              Gisselquist Technology, LLC
22
//
23
///////////////////////////////////////////////////////////////////////////
24
//
25
// Copyright (C) 2015, Gisselquist Technology, LLC
26
//
27
// This program is free software (firmware): you can redistribute it and/or
28
// modify it under the terms of  the GNU General Public License as published
29
// by the Free Software Foundation, either version 3 of the License, or (at
30
// your option) any later version.
31
//
32
// This program is distributed in the hope that it will be useful, but WITHOUT
33
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
34
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
35
// for more details.
36
//
37
// You should have received a copy of the GNU General Public License along
38
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
39
// target there if the PDF file isn't present.)  If not, see
40
// <http://www.gnu.org/licenses/> for a copy.
41
//
42
// License:     GPL, v3, as defined and found on www.gnu.org,
43
//              http://www.gnu.org/licenses/gpl.html
44
//
45
//
46
/////////////////////////////////////////////////////////////////////////////
47
//
48
`define DMOD_GETINPUT   1'b0
49
`define DMOD_PUTOUTPUT  1'b1
50
`define RAM_OPERATIONAL 2'b00
51
`define RAM_POWER_UP    2'b01
52
`define RAM_SET_MODE    2'b10
53
`define RAM_INITIAL_REFRESH     2'b11
54
 
55
module  wbsdram(i_clk,
56
                i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
57
                        o_wb_ack, o_wb_stall, o_wb_data,
58
                o_ram_cs_n, o_ram_cke, o_ram_ras_n, o_ram_cas_n, o_ram_we_n,
59
                        o_ram_bs, o_ram_addr,
60
                        o_ram_dmod, i_ram_data, o_ram_data, o_ram_dqm,
61
                o_debug);
62
        parameter       RDLY = 6;
63
        input                   i_clk;
64
        // Wishbone
65
        //      inputs
66
        input                   i_wb_cyc, i_wb_stb, i_wb_we;
67
        input           [22:0]   i_wb_addr;
68
        input           [31:0]   i_wb_data;
69
        //      outputs
70
        output  wire            o_wb_ack;
71
        output  reg             o_wb_stall;
72
        output  wire [31:0]      o_wb_data;
73
        // SDRAM control
74
        output  wire            o_ram_cke;
75
        output  reg             o_ram_cs_n,
76
                                o_ram_ras_n, o_ram_cas_n, o_ram_we_n;
77
        output  reg     [1:0]    o_ram_bs;
78
        output  reg     [12:0]   o_ram_addr;
79
        output  reg             o_ram_dmod;
80
        input           [15:0]   i_ram_data;
81
        output  reg     [15:0]   o_ram_data;
82
        output  reg     [1:0]    o_ram_dqm;
83
        output  wire    [31:0]   o_debug;
84
 
85
 
86
        // Calculate some metrics
87
 
88
        //
89
        // First, do we *need* a refresh now --- i.e., must we break out of
90
        // whatever we are doing to issue a refresh command?
91
        //
92
        // The step size here must be such that 8192 charges may be done in
93
        // 64 ms.  Thus for a clock of:
94
        //      ClkRate(MHz)    (64ms/1000(ms/s)*ClkRate)/8192
95
        //      100 MHz         781
96
        //       96 MHz         750
97
        //       92 MHz         718
98
        //       88 MHz         687
99
        //       84 MHz         656
100
        //       80 MHz         625
101
        //
102
        reg             need_refresh;
103
        reg     [9:0]    refresh_clk;
104
        wire    refresh_cmd;
105
        assign  refresh_cmd = (~o_ram_cs_n)&&(~o_ram_ras_n)&&(~o_ram_cas_n)&&(o_ram_we_n);
106
        initial refresh_clk = 0;
107
        always @(posedge i_clk)
108
        begin
109
                if (refresh_cmd)
110
                        refresh_clk <= 10'd625; // Make suitable for 80 MHz clk
111
                else if (|refresh_clk)
112
                        refresh_clk <= refresh_clk - 10'h1;
113
        end
114
        initial need_refresh = 1'b0;
115
        always @(posedge i_clk)
116
                need_refresh <= (refresh_clk == 10'h00)&&(~refresh_cmd);
117
 
118
        reg     in_refresh;
119
        reg     [2:0]    in_refresh_clk;
120
        initial in_refresh_clk = 3'h0;
121
        always @(posedge i_clk)
122
                if (refresh_cmd)
123
                        in_refresh_clk <= 3'h6;
124
                else if (|in_refresh_clk)
125
                        in_refresh_clk <= in_refresh_clk - 3'h1;
126
        always @(posedge i_clk)
127
                in_refresh <= (in_refresh_clk != 3'h0)||(refresh_cmd);
128
 
129
 
130
        reg     [2:0]    bank_active     [0:3];
131
        reg     [(RDLY-1):0]     r_barrell_ack;
132
        reg             r_pending;
133
        reg             r_we;
134
        reg     [22:0]   r_addr;
135
        reg     [31:0]   r_data;
136
        reg     [12:0]   bank_row        [0:3];
137
 
138
 
139
        //
140
        // Second, do we *need* a precharge now --- must be break out of 
141
        // whatever we are doing to issue a precharge command?
142
        //
143
        // Keep in mind, the number of clocks to wait has to be reduced by
144
        // the amount of time it may take us to go into a precharge state.
145
        //
146
        reg     [3:0]    need_precharge;
147
        genvar  k;
148
        generate
149
        for(k=0; k<4; k=k+1)
150
        begin : precharge_genvar_loop
151
                wire    precharge_cmd;
152
                assign  precharge_cmd = ((~o_ram_cs_n)&&(~o_ram_ras_n)&&(o_ram_cas_n)&&(~o_ram_we_n)
153
                                &&((o_ram_addr[10])||(o_ram_bs == k[1:0])))
154
                        // Also on read or write with precharge
155
                        ||(~o_ram_cs_n)&&(o_ram_ras_n)&&(~o_ram_cas_n)&&(o_ram_addr[10]);
156
 
157
                reg     [9:0]    precharge_clk;
158
                initial precharge_clk = 0;
159
                always @(posedge i_clk)
160
                begin
161
                        if ((precharge_cmd)||(bank_active[k] == 0))
162
                                precharge_clk <= 10'd1000;
163
                        else if (|precharge_clk)
164
                                precharge_clk <= precharge_clk - 10'h1;
165
                end
166
                initial need_precharge[k] = 1'b0;
167
                always @(posedge i_clk)
168
                        need_precharge[k] <= ~(|precharge_clk);
169
        end // precharge_genvar_loop
170
        endgenerate
171
 
172
 
173
 
174
        reg     [15:0]   clocks_til_idle;
175
        reg     [1:0]    r_state;
176
        wire            bus_cyc;
177
        assign  bus_cyc  = ((i_wb_cyc)&&(i_wb_stb)&&(~o_wb_stall));
178
        reg     nxt_dmod;
179
 
180
        // Pre-process pending operations
181
        wire    pending;
182
        initial r_pending = 1'b0;
183
        reg     [22:5]  fwd_addr;
184
        always @(posedge i_clk)
185
                if (bus_cyc)
186
                begin
187
                        r_pending <= 1'b1;
188
                        r_we      <= i_wb_we;
189
                        r_addr    <= i_wb_addr;
190
                        r_data    <= i_wb_data;
191
                        fwd_addr  <= i_wb_addr[22:5] + 18'h01;
192
                end else if ((~o_ram_cs_n)&&(o_ram_ras_n)&&(~o_ram_cas_n))
193
                        r_pending <= 1'b0;
194
                else if (~i_wb_cyc)
195
                        r_pending <= 1'b0;
196
 
197
        reg     r_bank_valid;
198
        initial r_bank_valid = 1'b0;
199
        always @(posedge i_clk)
200
                if (bus_cyc)
201
                        r_bank_valid <=((bank_active[i_wb_addr[9:8]][2])
202
                                        &&(bank_row[i_wb_addr[9:8]]==r_addr[22:10]));
203
                else
204
                        r_bank_valid <= ((bank_active[r_addr[9:8]][2])
205
                                        &&(bank_row[r_addr[9:8]]==r_addr[22:10]));
206
        reg     fwd_bank_valid;
207
        initial fwd_bank_valid = 0;
208
        always @(posedge i_clk)
209
                fwd_bank_valid <= ((bank_active[fwd_addr[9:8]][2])
210
                                        &&(bank_row[fwd_addr[9:8]]==fwd_addr[22:10]));
211
 
212
        assign  pending = (r_pending)&&(o_wb_stall);
213
 
214
        // Address MAP:
215
        //      23-bits bits in, 24-bits out
216
        //
217
        //      222 1111 1111 1100 0000 0000
218
        //      210 9876 5432 1098 7654 3210
219
        //      rrr rrrr rrrr rrBB cccc cccc 0
220
        //                         8765 4321 0
221
        //
222
        initial r_barrell_ack = 0;
223
        initial r_state = `RAM_POWER_UP;
224
        initial clocks_til_idle = 16'd20500;
225
        initial o_wb_stall = 1'b1;
226
        initial o_ram_dmod = `DMOD_GETINPUT;
227
        initial nxt_dmod = `DMOD_GETINPUT;
228
        initial o_ram_cs_n  = 1'b0;
229
        initial o_ram_ras_n = 1'b1;
230
        initial o_ram_cas_n = 1'b1;
231
        initial o_ram_we_n  = 1'b1;
232
        initial o_ram_dqm   = 2'b11;
233
        assign  o_ram_cke   = 1'b1;
234
        initial bank_active[0] = 3'b000;
235
        initial bank_active[1] = 3'b000;
236
        initial bank_active[2] = 3'b000;
237
        initial bank_active[3] = 3'b000;
238
        always @(posedge i_clk)
239
        if (r_state == `RAM_OPERATIONAL)
240
        begin
241
                o_wb_stall <= (r_pending)||(bus_cyc);
242
                r_barrell_ack <= r_barrell_ack >> 1;
243
                nxt_dmod <= `DMOD_GETINPUT;
244
                o_ram_dmod <= nxt_dmod;
245
 
246
                //
247
                bank_active[0] <= { bank_active[0][2], bank_active[0][2:1] };
248
                bank_active[1] <= { bank_active[1][2], bank_active[1][2:1] };
249
                bank_active[2] <= { bank_active[2][2], bank_active[2][2:1] };
250
                bank_active[3] <= { bank_active[3][2], bank_active[3][2:1] };
251
                //
252
                o_ram_cs_n <= (~i_wb_cyc);
253
                // o_ram_cke  <= 1'b1;
254
                o_ram_dqm  <= 2'b0;
255
                if (|clocks_til_idle[2:0])
256
                        clocks_til_idle[2:0] <= clocks_til_idle[2:0] - 3'h1;
257
 
258
                // Default command is a
259
                //      NOOP if (i_wb_cyc)
260
                //      Device deselect if (~i_wb_cyc)
261
                // o_ram_cs_n  <= (~i_wb_cyc) above, NOOP
262
                o_ram_ras_n <= 1'b1;
263
                o_ram_cas_n <= 1'b1;
264
                o_ram_we_n  <= 1'b1;
265
 
266
                // Don't drive the bus normally, let it float unless we wish
267
                // to give it a command
268
                o_ram_data <= r_data[15:0];
269
 
270
                if ((~i_wb_cyc)||(|need_precharge)||(need_refresh))
271
                begin // Issue a precharge all command (if any banks are open),
272
                // otherwise an autorefresh command
273
                        if ((bank_active[0][2:1]==2'b10)
274
                                        ||(bank_active[1][2:1]==2'b10)
275
                                        ||(bank_active[2][2:1]==2'b10)
276
                                        ||(bank_active[3][2:1]==2'b10))
277
                        begin
278
                                // Do nothing this clock
279
                                // Can't precharge a bank immediately after
280
                                // activating it
281
                        end else if (bank_active[0][2]
282
                                ||(bank_active[1][2])
283
                                ||(bank_active[2][2])
284
                                ||(bank_active[3][2]))
285
                        begin  // Close all active banks
286
                                o_ram_cs_n  <= 1'b0;
287
                                o_ram_ras_n <= 1'b0;
288
                                o_ram_cas_n <= 1'b1;
289
                                o_ram_we_n  <= 1'b0;
290
                                o_ram_addr[10] <= 1'b1;
291
                                bank_active[0][2] <= 1'b0;
292
                                bank_active[1][2] <= 1'b0;
293
                                bank_active[2][2] <= 1'b0;
294
                                bank_active[3][2] <= 1'b0;
295
                        end else if ((|bank_active[0])
296
                                        ||(|bank_active[1])
297
                                        ||(|bank_active[2])
298
                                        ||(|bank_active[3]))
299
                                // Can't precharge yet, the bus is still busy
300
                        begin end else if ((~in_refresh)&&((refresh_clk[9:8]==2'b00)||(need_refresh)))
301
                        begin // Send autorefresh command
302
                                o_ram_cs_n  <= 1'b0;
303
                                o_ram_ras_n <= 1'b0;
304
                                o_ram_cas_n <= 1'b0;
305
                                o_ram_we_n  <= 1'b1;
306
                        end // Else just send NOOP's, the default command
307
                end else if (nxt_dmod)
308
                begin
309
                        // Last half of a two cycle write
310
                        o_ram_data <= r_data[15:0];
311
                end else if (in_refresh)
312
                begin
313
                        // NOOPS only here, until we are out of refresh
314
                end else if ((pending)&&(~r_bank_valid)&&(bank_active[r_addr[9:8]]==3'h0))
315
                begin // Need to activate the requested bank
316
                        o_ram_cs_n  <= 1'b0;
317
                        o_ram_ras_n <= 1'b0;
318
                        o_ram_cas_n <= 1'b1;
319
                        o_ram_we_n  <= 1'b1;
320
                        o_ram_addr  <= r_addr[22:10];
321
                        o_ram_bs    <= r_addr[9:8];
322
                        // clocks_til_idle[2:0] <= 1;
323
                        bank_active[r_addr[9:8]][2] <= 1'b1;
324
                        bank_row[r_addr[9:8]] <= r_addr[22:10];
325
                        //
326
                end else if ((pending)&&(~r_bank_valid)
327
                                &&(bank_active[r_addr[9:8]]==3'b111))
328
                begin // Need to close an active bank
329
                        o_ram_cs_n  <= 1'b0;
330
                        o_ram_ras_n <= 1'b0;
331
                        o_ram_cas_n <= 1'b1;
332
                        o_ram_we_n  <= 1'b0;
333
                        // o_ram_addr  <= r_addr[22:10];
334
                        o_ram_addr[10]<= 1'b0;
335
                        o_ram_bs    <= r_addr[9:8];
336
                        // clocks_til_idle[2:0] <= 1;
337
                        bank_active[r_addr[9:8]][2] <= 1'b0;
338
                        // bank_row[r_addr[9:8]] <= r_addr[22:10];
339
                end else if ((pending)&&(~r_we)
340
                                &&(bank_active[r_addr[9:8]][2])
341
                                &&(r_bank_valid)
342
                                &&(clocks_til_idle[2:0] < 4))
343
                begin // Issue the read command
344
                        o_ram_cs_n  <= 1'b0;
345
                        o_ram_ras_n <= 1'b1;
346
                        o_ram_cas_n <= 1'b0;
347
                        o_ram_we_n  <= 1'b1;
348
                        o_ram_addr  <= { 4'h0, r_addr[7:0], 1'b0 };
349
                        o_ram_bs    <= r_addr[9:8];
350
                        clocks_til_idle[2:0] <= 4;
351
 
352
                        o_wb_stall <= 1'b0;
353
                        r_barrell_ack[(RDLY-1)] <= 1'b1;
354
                end else if ((pending)&&(r_we)
355
                        &&(bank_active[r_addr[9:8]][2])
356
                        &&(r_bank_valid)
357
                        &&(clocks_til_idle[2:0] == 0))
358
                begin // Issue the write command
359
                        o_ram_cs_n  <= 1'b0;
360
                        o_ram_ras_n <= 1'b1;
361
                        o_ram_cas_n <= 1'b0;
362
                        o_ram_we_n  <= 1'b0;
363
                        o_ram_addr  <= { 4'h0, r_addr[7:0], 1'b0 };
364
                        o_ram_bs    <= r_addr[9:8];
365
                        clocks_til_idle[2:0] <= 3'h1;
366
 
367
                        o_wb_stall <= 1'b0;
368
                        r_barrell_ack[1] <= 1'b1;
369
                        o_ram_data <= r_data[31:16];
370
                        //
371
                        o_ram_dmod <= `DMOD_PUTOUTPUT;
372
                        nxt_dmod <= `DMOD_PUTOUTPUT;
373
                end else if ((r_pending)&&(r_addr[7:0] >= 8'hf0)
374
                                &&(~fwd_bank_valid))
375
                begin
376
                        // Do I need to close the next bank I'll need?
377
                        if (bank_active[fwd_addr[9:8]][2:1]==2'b11)
378
                        begin // Need to close the bank first
379
                                o_ram_cs_n <= 1'b0;
380
                                o_ram_ras_n <= 1'b0;
381
                                o_ram_cas_n <= 1'b1;
382
                                o_ram_we_n  <= 1'b0;
383
                                o_ram_addr[10] <= 1'b0;
384
                                o_ram_bs       <= fwd_addr[9:8];
385
                                bank_active[fwd_addr[9:8]][2] <= 1'b0;
386
                        end else if (bank_active[fwd_addr[9:8]]==3'b000)
387
                        begin
388
                                // Need to (pre-)activate the next bank
389
                                o_ram_cs_n  <= 1'b0;
390
                                o_ram_ras_n <= 1'b0;
391
                                o_ram_cas_n <= 1'b1;
392
                                o_ram_we_n  <= 1'b1;
393
                                o_ram_addr  <= fwd_addr[22:10];
394
                                o_ram_bs    <= fwd_addr[9:8];
395
                                // clocks_til_idle[3:0] <= 1;
396
                                bank_active[fwd_addr[9:8]] <= 3'h4;
397
                                bank_row[fwd_addr[9:8]] <= fwd_addr[22:10];
398
                        end
399
                end
400
        end else if (r_state == `RAM_POWER_UP)
401
        begin
402
                // All signals must be held in NOOP state during powerup
403
                o_ram_dqm <= 2'b11;
404
                // o_ram_cke <= 1'b1;
405
                o_ram_cs_n  <= 1'b0;
406
                o_ram_ras_n <= 1'b1;
407
                o_ram_cas_n <= 1'b1;
408
                o_ram_we_n  <= 1'b1;
409
                o_ram_dmod  <= `DMOD_GETINPUT;
410
                if (clocks_til_idle == 0)
411
                begin
412
                        r_state <= `RAM_INITIAL_REFRESH;
413
                        clocks_til_idle[3:0] <= 4'ha;
414
                        o_ram_cs_n  <= 1'b0;
415
                        o_ram_ras_n <= 1'b0;
416
                        o_ram_cas_n <= 1'b1;
417
                        o_ram_we_n  <= 1'b0;
418
                        o_ram_addr[10] <= 1'b1;
419
                end else
420
                        clocks_til_idle <= clocks_til_idle - 16'h01;
421
 
422
                o_wb_stall  <= 1'b1;
423
                r_barrell_ack[(RDLY-1):0] <= 0;
424
        end else if (r_state == `RAM_INITIAL_REFRESH)
425
        begin
426
                //
427
                o_ram_cs_n  <= 1'b0;
428
                o_ram_ras_n <= 1'b0;
429
                o_ram_cas_n <= 1'b0;
430
                o_ram_we_n  <= 1'b1;
431
                o_ram_dmod  <= `DMOD_GETINPUT;
432
                o_ram_addr  <= { 3'b000, 1'b0, 2'b00, 3'b010, 1'b0, 3'b001 };
433
                if (clocks_til_idle[3:0] == 4'h0)
434
                begin
435
                        r_state <= `RAM_SET_MODE;
436
                        o_ram_we_n <= 1'b0;
437
                        clocks_til_idle[3:0] <= 4'h2;
438
                end else
439
                        clocks_til_idle[3:0] <= clocks_til_idle[3:0] - 4'h1;
440
 
441
                o_wb_stall  <= 1'b1;
442
                r_barrell_ack[(RDLY-1):0] <= 0;
443
        end else if (r_state == `RAM_SET_MODE)
444
        begin
445
                // Set mode cycle
446
                o_ram_cs_n  <= 1'b1;
447
                o_ram_ras_n <= 1'b0;
448
                o_ram_cas_n <= 1'b0;
449
                o_ram_we_n  <= 1'b0;
450
                o_ram_dmod  <= `DMOD_GETINPUT;
451
 
452
                if (clocks_til_idle[3:0] == 4'h0)
453
                        r_state <= `RAM_OPERATIONAL;
454
                else
455
                        clocks_til_idle[3:0] <= clocks_til_idle[3:0]-4'h1;
456
 
457
                o_wb_stall  <= 1'b1;
458
                r_barrell_ack[(RDLY-1):0] <= 0;
459
        end
460
 
461 37 dgisselq
`ifdef  VERILATOR
462
        // While I hate to build something that works one way under Verilator
463
        // and another way in practice, this really isn't that.  The problem
464
        // Verilator is having is resolved in toplevel.v--one file that
465
        // Verilator doesn't implement.  In toplevel.v, there's not only a
466
        // single clocked latch but two taking place.  Here, we replicate one
467
        // of those.  The second takes place (somehow) within the sdramsim.cpp
468
        // file.
469
        reg     [15:0]   ram_data, last_ram_data;
470
        always @(posedge i_clk)
471
                ram_data <= i_ram_data;
472
        always @(posedge i_clk)
473
                last_ram_data <= ram_data;
474
`else
475 2 dgisselq
        reg     [15:0]   last_ram_data;
476
        always @(posedge i_clk)
477
                last_ram_data <= i_ram_data;
478 37 dgisselq
`endif
479 2 dgisselq
        assign  o_wb_ack  = r_barrell_ack[0];
480
        assign  o_wb_data = { last_ram_data, i_ram_data };
481
 
482
        //
483
        // The following outputs are not necessary for the functionality of
484
        // the SDRAM, but they can be used to feed an external "scope" to
485
        // get an idea of what the internals of this SDRAM are doing.
486
        //
487
        // Just be aware of the r_we: it is set based upon the currently pending
488
        // transaction, or (if none is pending) based upon the last transaction.
489
        // If you want to capture the first value "written" to the device,
490
        // you'll need to write a nothing value to the device to set r_we.
491
        // The first value "written" to the device can be caught in the next
492
        // interaction after that.
493
        //
494
        assign  o_debug = { i_wb_cyc, i_wb_stb, i_wb_we, o_wb_ack, o_wb_stall,
495
                o_ram_cs_n, o_ram_ras_n, o_ram_cas_n, o_ram_we_n, o_ram_bs,
496
                        o_ram_dmod, r_pending,
497
                                                // 13 of 32
498
                        o_ram_addr[10:0],        // 11 more
499
                        (r_we) ? { i_wb_data[23:20], i_wb_data[3:0] }
500
                                : { o_wb_data[23:20], o_wb_data[3:0] }
501
                        // i_ram_data[7:0]
502
                         };
503
endmodule

powered by: WebSVN 2.1.0

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