-
Notifications
You must be signed in to change notification settings - Fork 4
/
sdram_sdram.v
722 lines (644 loc) · 23.8 KB
/
sdram_sdram.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
//Legal Notice: (C)2019 Altera Corporation. All rights reserved. Your
//use of Altera Corporation's design tools, logic functions and other
//software and tools, and its AMPP partner logic functions, and any
//output files any of the foregoing (including device programming or
//simulation files), and any associated documentation or information are
//expressly subject to the terms and conditions of the Altera Program
//License Subscription Agreement or other applicable license agreement,
//including, without limitation, that your use is for the sole purpose
//of programming logic devices manufactured by Altera and sold by Altera
//or its authorized distributors. Please refer to the applicable
//agreement for further details.
// synthesis translate_off
`timescale 1ns / 1ps
// synthesis translate_on
// turn off superfluous verilog processor warnings
// altera message_level Level1
// altera message_off 10034 10035 10036 10037 10230 10240 10030
module sdram_sdram_input_efifo_module (
// inputs:
clk,
rd,
reset_n,
wr,
wr_data,
// outputs:
almost_empty,
almost_full,
empty,
full,
rd_data
)
;
output almost_empty;
output almost_full;
output empty;
output full;
output [ 57: 0] rd_data;
input clk;
input rd;
input reset_n;
input wr;
input [ 57: 0] wr_data;
wire almost_empty;
wire almost_full;
wire empty;
reg [ 1: 0] entries;
reg [ 57: 0] entry_0;
reg [ 57: 0] entry_1;
wire full;
reg rd_address;
reg [ 57: 0] rd_data;
wire [ 1: 0] rdwr;
reg wr_address;
assign rdwr = {rd, wr};
assign full = entries == 2;
assign almost_full = entries >= 1;
assign empty = entries == 0;
assign almost_empty = entries <= 1;
always @(entry_0 or entry_1 or rd_address)
begin
case (rd_address) // synthesis parallel_case full_case
1'd0: begin
rd_data = entry_0;
end // 1'd0
1'd1: begin
rd_data = entry_1;
end // 1'd1
default: begin
end // default
endcase // rd_address
end
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 0)
begin
wr_address <= 0;
rd_address <= 0;
entries <= 0;
end
else
case (rdwr) // synthesis parallel_case full_case
2'd1: begin
// Write data
if (!full)
begin
entries <= entries + 1;
wr_address <= (wr_address == 1) ? 0 : (wr_address + 1);
end
end // 2'd1
2'd2: begin
// Read data
if (!empty)
begin
entries <= entries - 1;
rd_address <= (rd_address == 1) ? 0 : (rd_address + 1);
end
end // 2'd2
2'd3: begin
wr_address <= (wr_address == 1) ? 0 : (wr_address + 1);
rd_address <= (rd_address == 1) ? 0 : (rd_address + 1);
end // 2'd3
default: begin
end // default
endcase // rdwr
end
always @(posedge clk)
begin
//Write data
if (wr & !full)
case (wr_address) // synthesis parallel_case full_case
1'd0: begin
entry_0 <= wr_data;
end // 1'd0
1'd1: begin
entry_1 <= wr_data;
end // 1'd1
default: begin
end // default
endcase // wr_address
end
endmodule
// synthesis translate_off
`timescale 1ns / 1ps
// synthesis translate_on
// turn off superfluous verilog processor warnings
// altera message_level Level1
// altera message_off 10034 10035 10036 10037 10230 10240 10030
module sdram_sdram (
// inputs:
az_addr,
az_be_n,
az_cs,
az_data,
az_rd_n,
az_wr_n,
clk,
reset_n,
// outputs:
za_data,
za_valid,
za_waitrequest,
zs_addr,
zs_ba,
zs_cas_n,
zs_cke,
zs_cs_n,
zs_dq,
zs_dqm,
zs_ras_n,
zs_we_n,
init_done
)
;
output [ 31: 0] za_data;
output za_valid;
output za_waitrequest;
output [ 10: 0] zs_addr;
output [ 1: 0] zs_ba;
output zs_cas_n;
output zs_cke;
output zs_cs_n;
inout [ 31: 0] zs_dq;
output [ 3: 0] zs_dqm;
output zs_ras_n;
output zs_we_n;
input [ 20: 0] az_addr;
input [ 3: 0] az_be_n;
input az_cs;
input [ 31: 0] az_data;
input az_rd_n;
input az_wr_n;
input clk;
input reset_n;
output init_done;
wire [ 23: 0] CODE;
reg ack_refresh_request;
reg [ 20: 0] active_addr;
wire [ 1: 0] active_bank;
reg active_cs_n;
reg [ 31: 0] active_data;
reg [ 3: 0] active_dqm;
reg active_rnw;
wire almost_empty;
wire almost_full;
wire bank_match;
wire [ 7: 0] cas_addr;
wire clk_en;
wire [ 3: 0] cmd_all;
wire [ 2: 0] cmd_code;
wire cs_n;
wire csn_decode;
wire csn_match;
wire [ 20: 0] f_addr;
wire [ 1: 0] f_bank;
wire f_cs_n;
wire [ 31: 0] f_data;
wire [ 3: 0] f_dqm;
wire f_empty;
reg f_pop;
wire f_rnw;
wire f_select;
wire [ 57: 0] fifo_read_data;
reg [ 10: 0] i_addr;
reg [ 3: 0] i_cmd;
reg [ 2: 0] i_count;
reg [ 2: 0] i_next;
reg [ 2: 0] i_refs;
reg [ 2: 0] i_state;
reg init_done;
reg [ 10: 0] m_addr /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON" */;
reg [ 1: 0] m_bank /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON" */;
reg [ 3: 0] m_cmd /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON" */;
reg [ 2: 0] m_count;
reg [ 31: 0] m_data /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON ; FAST_OUTPUT_ENABLE_REGISTER=ON" */;
reg [ 3: 0] m_dqm /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_REGISTER=ON" */;
reg [ 8: 0] m_next;
reg [ 8: 0] m_state;
reg oe /* synthesis ALTERA_ATTRIBUTE = "FAST_OUTPUT_ENABLE_REGISTER=ON" */;
wire pending;
wire rd_strobe;
reg [ 2: 0] rd_valid;
reg [ 14: 0] refresh_counter;
reg refresh_request;
wire rnw_match;
wire row_match;
wire [ 23: 0] txt_code;
reg za_cannotrefresh;
reg [ 31: 0] za_data /* synthesis ALTERA_ATTRIBUTE = "FAST_INPUT_REGISTER=ON" */;
reg za_valid;
wire za_waitrequest;
wire [ 10: 0] zs_addr;
wire [ 1: 0] zs_ba;
wire zs_cas_n;
wire zs_cke;
wire zs_cs_n;
wire [ 31: 0] zs_dq;
wire [ 3: 0] zs_dqm;
wire zs_ras_n;
wire zs_we_n;
assign clk_en = 1;
//s1, which is an e_avalon_slave
assign {zs_cs_n, zs_ras_n, zs_cas_n, zs_we_n} = m_cmd;
assign zs_addr = m_addr;
assign zs_cke = clk_en;
assign zs_dq = oe?m_data:{32{1'bz}};
assign zs_dqm = m_dqm;
assign zs_ba = m_bank;
assign f_select = f_pop & pending;
assign f_cs_n = 1'b0;
assign cs_n = f_select ? f_cs_n : active_cs_n;
assign csn_decode = cs_n;
assign {f_rnw, f_addr, f_dqm, f_data} = fifo_read_data;
sdram_sdram_input_efifo_module the_sdram_sdram_input_efifo_module
(
.almost_empty (almost_empty),
.almost_full (almost_full),
.clk (clk),
.empty (f_empty),
.full (za_waitrequest),
.rd (f_select),
.rd_data (fifo_read_data),
.reset_n (reset_n),
.wr ((~az_wr_n | ~az_rd_n) & !za_waitrequest),
.wr_data ({az_wr_n, az_addr, az_wr_n ? 4'b0 : az_be_n, az_data})
);
assign f_bank = {f_addr[20],f_addr[8]};
// Refresh/init counter.
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 0)
refresh_counter <= 25000;
else if (refresh_counter == 0)
refresh_counter <= 976;
else
refresh_counter <= refresh_counter - 1'b1;
end
// Refresh request signal.
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 0)
refresh_request <= 0;
else if (1)
refresh_request <= ((refresh_counter == 0) | refresh_request) & ~ack_refresh_request & init_done;
end
// Generate an Interrupt if two ref_reqs occur before one ack_refresh_request
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 0)
za_cannotrefresh <= 0;
else if (1)
za_cannotrefresh <= (refresh_counter == 0) & refresh_request;
end
// Initialization-done flag.
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 0)
init_done <= 0;
else if (1)
init_done <= init_done | (i_state == 3'b101);
end
// **** Init FSM ****
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 0)
begin
i_state <= 3'b000;
i_next <= 3'b000;
i_cmd <= 4'b1111;
i_addr <= {11{1'b1}};
i_count <= {3{1'b0}};
end
else
begin
i_addr <= {11{1'b1}};
case (i_state) // synthesis parallel_case full_case
3'b000: begin
i_cmd <= 4'b1111;
i_refs <= 3'b0;
//Wait for refresh count-down after reset
if (refresh_counter == 0)
i_state <= 3'b001;
end // 3'b000
3'b001: begin
i_state <= 3'b011;
i_cmd <= {{1{1'b0}},3'h2};
i_count <= 2;
i_next <= 3'b010;
end // 3'b001
3'b010: begin
i_cmd <= {{1{1'b0}},3'h1};
i_refs <= i_refs + 1'b1;
i_state <= 3'b011;
i_count <= 7;
// Count up init_refresh_commands
if (i_refs == 3'h7)
i_next <= 3'b111;
else
i_next <= 3'b010;
end // 3'b010
3'b011: begin
i_cmd <= {{1{1'b0}},3'h7};
//WAIT til safe to Proceed...
if (i_count > 1)
i_count <= i_count - 1'b1;
else
i_state <= i_next;
end // 3'b011
3'b101: begin
i_state <= 3'b101;
end // 3'b101
3'b111: begin
i_state <= 3'b011;
i_cmd <= {{1{1'b0}},3'h0};
i_addr <= {{1{1'b0}},1'b0,2'b00,3'h3,4'h0};
i_count <= 4;
i_next <= 3'b101;
end // 3'b111
default: begin
i_state <= 3'b000;
end // default
endcase // i_state
end
end
assign active_bank = {active_addr[20],active_addr[8]};
assign csn_match = active_cs_n == f_cs_n;
assign rnw_match = active_rnw == f_rnw;
assign bank_match = active_bank == f_bank;
assign row_match = {active_addr[19 : 9]} == {f_addr[19 : 9]};
assign pending = csn_match && rnw_match && bank_match && row_match && !f_empty;
assign cas_addr = f_select ? { {3{1'b0}},f_addr[7 : 0] } : { {3{1'b0}},active_addr[7 : 0] };
// **** Main FSM ****
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 0)
begin
m_state <= 9'b000000001;
m_next <= 9'b000000001;
m_cmd <= 4'b1111;
m_bank <= 2'b00;
m_addr <= 11'b00000000000;
m_data <= 32'b00000000000000000000000000000000;
m_dqm <= 4'b0000;
m_count <= 3'b000;
ack_refresh_request <= 1'b0;
f_pop <= 1'b0;
oe <= 1'b0;
end
else
begin
f_pop <= 1'b0;
oe <= 1'b0;
case (m_state) // synthesis parallel_case full_case
9'b000000001: begin
//Wait for init-fsm to be done...
if (init_done)
begin
//Hold bus if another cycle ended to arf.
if (refresh_request)
m_cmd <= {{1{1'b0}},3'h7};
else
m_cmd <= 4'b1111;
ack_refresh_request <= 1'b0;
//Wait for a read/write request.
if (refresh_request)
begin
m_state <= 9'b001000000;
m_next <= 9'b010000000;
m_count <= 2;
active_cs_n <= 1'b1;
end
else if (!f_empty)
begin
f_pop <= 1'b1;
active_cs_n <= f_cs_n;
active_rnw <= f_rnw;
active_addr <= f_addr;
active_data <= f_data;
active_dqm <= f_dqm;
m_state <= 9'b000000010;
end
end
else
begin
m_addr <= i_addr;
m_state <= 9'b000000001;
m_next <= 9'b000000001;
m_cmd <= i_cmd;
end
end // 9'b000000001
9'b000000010: begin
m_state <= 9'b000000100;
m_cmd <= {csn_decode,3'h3};
m_bank <= active_bank;
m_addr <= active_addr[19 : 9];
m_data <= active_data;
m_dqm <= active_dqm;
m_count <= 3;
m_next <= active_rnw ? 9'b000001000 : 9'b000010000;
end // 9'b000000010
9'b000000100: begin
// precharge all if arf, else precharge csn_decode
if (m_next == 9'b010000000)
m_cmd <= {{1{1'b0}},3'h7};
else
m_cmd <= {csn_decode,3'h7};
//Count down til safe to Proceed...
if (m_count > 1)
m_count <= m_count - 1'b1;
else
m_state <= m_next;
end // 9'b000000100
9'b000001000: begin
m_cmd <= {csn_decode,3'h5};
m_bank <= f_select ? f_bank : active_bank;
m_dqm <= f_select ? f_dqm : active_dqm;
m_addr <= cas_addr;
//Do we have a transaction pending?
if (pending)
begin
//if we need to ARF, bail, else spin
if (refresh_request)
begin
m_state <= 9'b000000100;
m_next <= 9'b000000001;
m_count <= 2;
end
else
begin
f_pop <= 1'b1;
active_cs_n <= f_cs_n;
active_rnw <= f_rnw;
active_addr <= f_addr;
active_data <= f_data;
active_dqm <= f_dqm;
end
end
else
begin
//correctly end RD spin cycle if fifo mt
if (~pending & f_pop)
m_cmd <= {csn_decode,3'h7};
m_state <= 9'b100000000;
end
end // 9'b000001000
9'b000010000: begin
m_cmd <= {csn_decode,3'h4};
oe <= 1'b1;
m_data <= f_select ? f_data : active_data;
m_dqm <= f_select ? f_dqm : active_dqm;
m_bank <= f_select ? f_bank : active_bank;
m_addr <= cas_addr;
//Do we have a transaction pending?
if (pending)
begin
//if we need to ARF, bail, else spin
if (refresh_request)
begin
m_state <= 9'b000000100;
m_next <= 9'b000000001;
m_count <= 3;
end
else
begin
f_pop <= 1'b1;
active_cs_n <= f_cs_n;
active_rnw <= f_rnw;
active_addr <= f_addr;
active_data <= f_data;
active_dqm <= f_dqm;
end
end
else
begin
//correctly end WR spin cycle if fifo empty
if (~pending & f_pop)
begin
m_cmd <= {csn_decode,3'h7};
oe <= 1'b0;
end
m_state <= 9'b100000000;
end
end // 9'b000010000
9'b000100000: begin
m_cmd <= {csn_decode,3'h7};
//Count down til safe to Proceed...
if (m_count > 1)
m_count <= m_count - 1'b1;
else
begin
m_state <= 9'b001000000;
m_count <= 2;
end
end // 9'b000100000
9'b001000000: begin
m_state <= 9'b000000100;
m_addr <= {11{1'b1}};
// precharge all if arf, else precharge csn_decode
if (refresh_request)
m_cmd <= {{1{1'b0}},3'h2};
else
m_cmd <= {csn_decode,3'h2};
end // 9'b001000000
9'b010000000: begin
ack_refresh_request <= 1'b1;
m_state <= 9'b000000100;
m_cmd <= {{1{1'b0}},3'h1};
m_count <= 7;
m_next <= 9'b000000001;
end // 9'b010000000
9'b100000000: begin
m_cmd <= {csn_decode,3'h7};
//if we need to ARF, bail, else spin
if (refresh_request)
begin
m_state <= 9'b000000100;
m_next <= 9'b000000001;
m_count <= 2;
end
else //wait for fifo to have contents
if (!f_empty)
//Are we 'pending' yet?
if (csn_match && rnw_match && bank_match && row_match)
begin
m_state <= f_rnw ? 9'b000001000 : 9'b000010000;
f_pop <= 1'b1;
active_cs_n <= f_cs_n;
active_rnw <= f_rnw;
active_addr <= f_addr;
active_data <= f_data;
active_dqm <= f_dqm;
end
else
begin
m_state <= 9'b000100000;
m_next <= 9'b000000001;
m_count <= 2;
end
end // 9'b100000000
// synthesis translate_off
default: begin
m_state <= m_state;
m_cmd <= 4'b1111;
f_pop <= 1'b0;
oe <= 1'b0;
end // default
// synthesis translate_on
endcase // m_state
end
end
assign rd_strobe = m_cmd[2 : 0] == 3'h5;
//Track RD Req's based on cas_latency w/shift reg
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 0)
rd_valid <= {3{1'b0}};
else
rd_valid <= (rd_valid << 1) | { {2{1'b0}}, rd_strobe };
end
// Register dq data.
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 0)
za_data <= 0;
else
za_data <= zs_dq;
end
// Delay za_valid to match registered data.
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 0)
za_valid <= 0;
else if (1)
za_valid <= rd_valid[2];
end
assign cmd_code = m_cmd[2 : 0];
assign cmd_all = m_cmd;
//synthesis translate_off
//////////////// SIMULATION-ONLY CONTENTS
initial
begin
$write("\n");
$write("This reference design requires a vendor simulation model.\n");
$write("To simulate accesses to SDRAM, you must:\n");
$write(" - Download the vendor model\n");
$write(" - Install the model in the system_sim directory\n");
$write(" - `include the vendor model in the the top-level system file,\n");
$write(" - Instantiate sdram simulation models and wire them to testbench signals\n");
$write(" - Be aware that you may have to disable some timing checks in the vendor model\n");
$write(" (because this simulation is zero-delay based)\n");
$write("\n");
end
assign txt_code = (cmd_code == 3'h0)? 24'h4c4d52 :
(cmd_code == 3'h1)? 24'h415246 :
(cmd_code == 3'h2)? 24'h505245 :
(cmd_code == 3'h3)? 24'h414354 :
(cmd_code == 3'h4)? 24'h205752 :
(cmd_code == 3'h5)? 24'h205244 :
(cmd_code == 3'h6)? 24'h425354 :
(cmd_code == 3'h7)? 24'h4e4f50 :
24'h424144;
assign CODE = &(cmd_all|4'h7) ? 24'h494e48 : txt_code;
//////////////// END SIMULATION-ONLY CONTENTS
//synthesis translate_on
endmodule