-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathddr3_controller.v
5241 lines (4851 loc) · 312 KB
/
ddr3_controller.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
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
////////////////////////////////////////////////////////////////////////////////
//
// Filename: ddr3_controller.v
// Project: UberDDR3 - An Open Source DDR3 Controller
//
// Purpose: This DDR3 controller was originally designed to be used on the
// Network Switch Project (https://github.com/ZipCPU/eth10g). The Network Switch
// project uses a Kintex 7 FPGA (XC7K160T-3FFG676E).
// The goal will be to:
// - Run this at 1600Mbps (Maximum Physical Interface (PHY) Rate for a 4:1
// memory controller based on "DC and AC Switching Characteristics" for Kintex 7)
// - Parameterize everything
// - Interface should be (nearly) bus agnostic
// - High (sustained) data throughput. Sequential writes should be able to continue without interruption
//
// Engineer: Angelo C. Jacobo
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023-2025 Angelo Jacobo
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////
// NOTE TO SELF are questions which I still need to answer
// Comments are continuously added on this RTL for better readability
//`define FORMAL_COVER //skip reset sequence during formal verification to fit in cover depth
`default_nettype none
`timescale 1ps / 1ps
//
// speed bin
`define DDR3_1600_11_11_11
//`define DDR3_1333_9_9_9
//`define DDR3_1066_7_7_7
//
module ddr3_controller #(
parameter integer CONTROLLER_CLK_PERIOD = 10_000, //ps, clock period of the controller interface
DDR3_CLK_PERIOD = 2_500, //ps, clock period of the DDR3 RAM device (must be 1/4 of the CONTROLLER_CLK_PERIOD)
ROW_BITS = 14, //width of DDR3 row address
COL_BITS = 10, //width of DDR3 column address
BA_BITS = 3, //width of bank address
DQ_BITS = 8, //device width
LANES = 2, //number of DDR3 device to be controlled
AUX_WIDTH = 16, //width of aux line (must be >= 4)
WB2_ADDR_BITS = 7, //width of 2nd wishbone address bus
WB2_DATA_BITS = 32, //width of 2nd wishbone data bus
DUAL_RANK_DIMM = 0, // enable dual rank DIMM (1 = enable, 0 = disable)
// DDR3 timing parameter values
parameter SPEED_BIN = 3, // 0 = Use top-level parameters , 1 = DDR3-1066 (7-7-7) , 2 = DR3-1333 (9-9-9) , 3 = DDR3-1600 (11-11-11)
SDRAM_CAPACITY = 5, // 0 = 256Mb, 1 = 512Mb, 2 = 1Gb, 3 = 2Gb, 4 = 4Gb, 5 = 8Gb, 6 = 16Gb
TRCD = 13_750, // ps Active to Read/Write command time (only used if SPEED_BIN = 0)
TRP = 13_750, // ps Precharge command period (only used if SPEED_BIN = 0)
TRAS = 35_000, // ps ACT to PRE command period (only used if SPEED_BIN = 0)
parameter[0:0] MICRON_SIM = 0, //enable faster simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW)
ODELAY_SUPPORTED = 1, //set to 1 when ODELAYE2 is supported
SECOND_WISHBONE = 0, //set to 1 if 2nd wishbone is needed
WB_ERROR = 0, // set to 1 to support Wishbone error (asserts at ECC double bit error)
SKIP_INTERNAL_TEST = 1, // skip built-in self test (would require >2 seconds of internal test right after calibration)
parameter[1:0] ECC_ENABLE = 0, // set to 1 or 2 to add ECC (1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC ) (only change when you know what you are doing)
parameter[1:0] DIC = 2'b00, //Output Driver Impedance Control (2'b00 = RZQ/6, 2'b01 = RZQ/7, RZQ = 240ohms) (only change when you know what you are doing)
parameter[2:0] RTT_NOM = 3'b011, //RTT Nominal (3'b000 = disabled, 3'b001 = RZQ/4, 3'b010 = RZQ/2 , 3'b011 = RZQ/6, RZQ = 240ohms)
parameter // The next parameters act more like a localparam (since user does not have to set this manually) but was added here to simplify port declaration
serdes_ratio = 4, // this controller is fixed as a 4:1 memory controller (CONTROLLER_CLK_PERIOD/DDR3_CLK_PERIOD = 4)
wb_data_bits = DQ_BITS*LANES*serdes_ratio*2,
wb_addr_bits = ROW_BITS + COL_BITS + BA_BITS - $clog2(serdes_ratio*2) + DUAL_RANK_DIMM,
wb_sel_bits = wb_data_bits / 8,
wb2_sel_bits = WB2_DATA_BITS / 8,
//4 is the width of a single ddr3 command {cs_n, ras_n, cas_n, we_n} plus 3 (ck_en, odt, reset_n) plus bank bits plus row bits
cmd_len = 4 + 3 + BA_BITS + ROW_BITS + 2*DUAL_RANK_DIMM,
lanes_clog2 = $clog2(LANES) == 0? 1: $clog2(LANES),
parameter[1:0] row_bank_col = (ECC_ENABLE == 3)? 2 : 1, // memory address mapping: 0 {bank, row, col} , 1 = {row, bank, col} , 2 = {bank[2:1]. row, bank[0], col} FOR ECC
parameter[0:0] ECC_TEST = 0
)
(
input wire i_controller_clk, //i_controller_clk has period of CONTROLLER_CLK_PERIOD
input wire i_rst_n, //200MHz input clock
// Wishbone inputs
input wire i_wb_cyc, //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled)
(* mark_debug = "true" *)input wire i_wb_stb, //request a transfer
(* mark_debug = "true" *)input wire i_wb_we, //write-enable (1 = write, 0 = read)
(* mark_debug = "true" *)input wire[wb_addr_bits - 1:0] i_wb_addr, //burst-addressable {row,bank,col}
(* mark_debug = "true" *)input wire[wb_data_bits - 1:0] i_wb_data, //write data, for a 4:1 controller data width is 8 times the number of pins on the device
input wire[wb_sel_bits - 1:0] i_wb_sel, //byte strobe for write (1 = write the byte)
input wire[AUX_WIDTH - 1:0] i_aux, //for AXI-interface compatibility (given upon strobe)
// Wishbone outputs
(* mark_debug = "true" *)output reg o_wb_stall, //1 = busy, cannot accept requests
(* mark_debug = "true" *)output wire o_wb_ack, //1 = read/write request has completed
output wire o_wb_err, //1 = Error due to ECC double bit error (fixed to 0 if WB_ERROR = 0)
(* mark_debug = "true" *)output reg[wb_data_bits - 1:0] o_wb_data, //read data, for a 4:1 controller data width is 8 times the number of pins on the device
output reg[AUX_WIDTH - 1:0] o_aux, //for AXI-interface compatibility (returned upon ack)
//
// Wishbone 2 (PHY) inputs
input wire i_wb2_cyc, //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled)
input wire i_wb2_stb, //request a transfer
input wire i_wb2_we, //write-enable (1 = write, 0 = read)
input wire[WB2_ADDR_BITS - 1:0] i_wb2_addr, //memory-mapped register to be accessed
input wire[wb2_sel_bits - 1:0] i_wb2_sel, //byte strobe for write (1 = write the byte)
input wire[WB2_DATA_BITS - 1:0] i_wb2_data, //write data
// Wishbone 2 (Controller) outputs
output reg o_wb2_stall, //1 = busy, cannot accept requests
output reg o_wb2_ack, //1 = read/write request has completed
output reg[WB2_DATA_BITS - 1:0] o_wb2_data, //read data
//
// PHY interface
(* mark_debug = "true" *) input wire[DQ_BITS*LANES*8 - 1:0] i_phy_iserdes_data,
(* mark_debug = "true" *) input wire[LANES*serdes_ratio*2 - 1:0] i_phy_iserdes_dqs,
input wire[LANES*serdes_ratio*2 - 1:0] i_phy_iserdes_bitslip_reference,
input wire i_phy_idelayctrl_rdy,
output wire[cmd_len*serdes_ratio-1:0] o_phy_cmd,
output reg o_phy_dqs_tri_control, o_phy_dq_tri_control,
output wire o_phy_toggle_dqs,
output wire[wb_data_bits-1:0] o_phy_data,
output wire[wb_sel_bits-1:0] o_phy_dm,
output wire[4:0] o_phy_odelay_data_cntvaluein, o_phy_odelay_dqs_cntvaluein,
output wire[4:0] o_phy_idelay_data_cntvaluein,
output wire[4:0] o_phy_idelay_dqs_cntvaluein,
output reg[LANES-1:0] o_phy_odelay_data_ld, o_phy_odelay_dqs_ld,
output reg[LANES-1:0] o_phy_idelay_data_ld,
output reg[LANES-1:0] o_phy_idelay_dqs_ld,
output reg[LANES-1:0] o_phy_bitslip,
output reg o_phy_write_leveling_calib,
output wire o_phy_reset,
// Done Calibration pin
output wire o_calib_complete,
// Debug port
output wire [31:0] o_debug1,
// output wire [31:0] o_debug2,
// output wire [31:0] o_debug3
// User enabled self-refresh
input wire i_user_self_refresh
);
/************************************************************* Command Parameters *************************************************************/
//DDR3 commands {cs_n, ras_n, cas_n, we_n} (JEDEC DDR3 doc pg. 33 )
localparam[3:0]CMD_MRS = 4'b0000, // Mode Register Set
CMD_REF = 4'b0001, // Refresh
CMD_PRE = 4'b0010, // Precharge (A10-AP: 0 = Single Bank Precharge, 1 = Precharge All Banks)
CMD_ACT = 4'b0011, // Bank Activate
CMD_WR = 4'b0100, // Write (A10-AP: 0 = no Auto-Precharge) (A12-BC#: 1 = Burst Length 8)
CMD_RD = 4'b0101, //Read (A10-AP: 0 = no Auto-Precharge) (A12-BC#: 1 = Burst Length 8)
CMD_NOP = 4'b0111, // No Operation
CMD_ZQC = 4'b0110, // ZQ Calibration (A10-AP: 0 = ZQ Calibration Short, 1 = ZQ Calibration Long)
CMD_SREF_EN = 4'b0001,
CMD_SREF_XT = 4'b0111;
localparam RST_DONE = 27, // Command bit that determines if reset seqeunce had aready finished. non-persistent (only needs to be toggled once),
REF_IDLE = 27, // No refresh is about to start and no ongoing refresh. (same bit as RST_DONE)
USE_TIMER = 26, // Command bit that determines if timer will be used (if delay is zero, USE_TIMER must be LOW)
A10_CONTROL = 25, //Command bit that determines if A10 AutoPrecharge will be high
CLOCK_EN = 24, //Clock-enable to DDR3
RESET_N = 23, //Reset_n to DDR3
DDR3_CMD_START = 22, //Start of DDR3 command slot
DDR3_CMD_END = 19, //end of DDR3 command slot
MRS_BANK_START = 18; //start of bank value in MRS value
// ddr3 command partitioning
/* verilator lint_off UNUSEDPARAM */
localparam CMD_CS_N_2 = cmd_len - 1,
CMD_CS_N = DUAL_RANK_DIMM[0]? cmd_len - 2 : cmd_len - 1,
CMD_RAS_N = DUAL_RANK_DIMM[0]? cmd_len - 3 : cmd_len - 2,
CMD_CAS_N = DUAL_RANK_DIMM[0]? cmd_len - 4 : cmd_len - 3,
CMD_WE_N = DUAL_RANK_DIMM[0]? cmd_len - 5 : cmd_len - 4,
CMD_ODT = DUAL_RANK_DIMM[0]? cmd_len - 6 : cmd_len - 5,
CMD_CKE_2 = DUAL_RANK_DIMM[0]? cmd_len - 7 : cmd_len - 6,
CMD_CKE = DUAL_RANK_DIMM[0]? cmd_len - 8 : cmd_len - 6,
CMD_RESET_N = DUAL_RANK_DIMM[0]? cmd_len - 9 : cmd_len - 7,
CMD_BANK_START = BA_BITS + ROW_BITS - 1,
CMD_ADDRESS_START = ROW_BITS - 1;
/* verilator lint_on UNUSEDPARAM */
localparam READ_SLOT = get_slot(CMD_RD),
WRITE_SLOT = get_slot(CMD_WR),
ACTIVATE_SLOT = get_slot(CMD_ACT),
PRECHARGE_SLOT = get_slot(CMD_PRE),
REMAINING_SLOT = get_slot(0);
// Data does not have to be delayed (DQS is the on that has to be
// delayed and center-aligned to the center eye of data)
localparam DATA_INITIAL_ODELAY_TAP = 0;
//Posedge of DQS needs to be aligned to the center eye of the data.
//This means DQS needs to be delayed by a quarter of the ddr3
//clk period relative to the data. Subtract by 600ps to include
//the IODELAY insertion delay. Divide by a delay resolution of
//78.125ps per tap to get the needed tap value. Then add the tap
//value used in data to have the delay relative to the data.
localparam DQS_INITIAL_ODELAY_TAP = $rtoi(((DDR3_CLK_PERIOD/4))/78.125 + DATA_INITIAL_ODELAY_TAP);
//Incoming DQS should be 90 degree delayed relative to incoming data
localparam DATA_INITIAL_IDELAY_TAP = 0; //600ps delay
localparam DQS_INITIAL_IDELAY_TAP = $rtoi(((DDR3_CLK_PERIOD/4))/78.125 + DATA_INITIAL_IDELAY_TAP);
/*********************************************************************************************************************************************/
/********************************************************** Timing Parameters ***********************************************************************************/
localparam DELAY_SLOT_WIDTH = 19; //Bitwidth of the delay slot and mode register slot on the reset/refresh rom will be at the same size as the Mode Register
localparam POWER_ON_RESET_HIGH = 200_000_000; // 200_000_000 ps (200 us) reset must be active at initialization
localparam INITIAL_CKE_LOW = 500_000_000; // 500_000_000 ps (500 us) cke must be low before activating
// ps Active to Read/Write command time
localparam tRCD = (SPEED_BIN == 0) ? TRCD : // use top-level parameters
(SPEED_BIN == 1) ? 13_750 : // DDR3-1066 (7-7-7)
(SPEED_BIN == 2) ? 13_500 : // DDR3-1333 (9-9-9)
(SPEED_BIN == 3) ? 13_750 : 13_750; // DDR3-1600 (11-11-11)
// ps Precharge command period
localparam tRP = (SPEED_BIN == 0) ? TRP : // use top-level parameters
(SPEED_BIN == 1) ? 13_750 : // DDR3-1066 (7-7-7)
(SPEED_BIN == 2) ? 13_500 : // DDR3-1333 (9-9-9)
(SPEED_BIN == 3) ? 13_750 : 13_750; // DDR3-1600 (11-11-11)
// ps ACT to PRE command period
localparam tRAS = (SPEED_BIN == 0) ? TRAS : // use top-level parameters
(SPEED_BIN == 1) ? 35_000 : // DDR3-1066 (7-7-7)
(SPEED_BIN == 2) ? 36_000 : // DDR3-1333 (9-9-9)
(SPEED_BIN == 3) ? 35_000 : 35_000; // DDR3-1600 (11-11-11)
// ps Refresh command to ACT or REF
localparam tRFC = ((SDRAM_CAPACITY == 4'b0000) || (SDRAM_CAPACITY == 4'b0001)) ? 90_000 : // 256Mb, 512Mb
(SDRAM_CAPACITY == 4'b0010) ? 110_000 : // 1Gb
(SDRAM_CAPACITY == 4'b0011) ? 160_000 : // 2Gb
(SDRAM_CAPACITY == 4'b0100) ? 300_000 : // 4Gb
(SDRAM_CAPACITY == 4'b0101) ? 350_000 : 350_000; // 8Gb
localparam tREFI = 7_800_000; //ps Average periodic refresh interval
localparam tXPR = max(5*DDR3_CLK_PERIOD, tRFC+10_000); // ps Exit Reset from CKE HIGH to a valid command
localparam tWR = 15_000; // ps Write Recovery Time
localparam tWTR = max(nCK_to_ps(4), 7_500); //ps Delay from start of internal write transaction to internal read command
localparam tWLMRD = nCK_to_cycles(40); // nCK First DQS/DQS# rising edge after write leveling mode is programmed
localparam tWLO = 9_000; //ps Write leveling output delay
localparam tWLOE = 2_000; //ps Write leveling output error
localparam tRTP = max(nCK_to_ps(4), 7_500); //ps Internal Command to PRECHARGE Command delay
localparam tCCD = 4; //nCK CAS to CAS command delay
/* verilator lint_off WIDTHEXPAND */
localparam tMOD = max(nCK_to_cycles(12), ps_to_cycles(15_000)); //cycles (controller) Mode Register Set command update delay
localparam tZQinit = max(nCK_to_cycles(512), ps_to_cycles(640_000));//cycles (controller) Power-up and RESET calibration time
/* verilator lint_on WIDTHEXPAND */
localparam CL_nCK = CL_generator(DDR3_CLK_PERIOD); //read latency (given in JEDEC DDR3 spec)
localparam CWL_nCK = CWL_generator(DDR3_CLK_PERIOD); //write latency (given in JEDEC DDR3 spec)
localparam DELAY_MAX_VALUE = ps_to_cycles(INITIAL_CKE_LOW); //Largest possible delay needed by the reset and refresh sequence
localparam DELAY_COUNTER_WIDTH= $clog2(DELAY_MAX_VALUE); //Bitwidth needed by the maximum possible delay, this will be the delay counter width
localparam CALIBRATION_DELAY = 2; // must be >= 2
localparam tXSDLL = nCK_to_cycles(512); // cycles (controller) Exit Self Refresh to commands requiring a locked DLL
localparam tXSDLL_tRFC = tXSDLL - ps_to_cycles(tRFC); // cycles (controller) Time before refresh after exit from self-refresh
localparam tCKE = max(3, ps_to_nCK(7500) ); // nCK CKE minimum pulse width
localparam tCKESR = nCK_to_cycles(tCKE + 1)+ 5; // cycles (controller) Minimum time that the DDR3 SDRAM must remain in Self-Refresh mode is tCKESR
localparam tCPDED = 5; // cycle (tCPDED is at most 2nCK but we make it to 1cycle or 4nCK) Command pass disable delay , required cycles of NOP after CKE low
/*********************************************************************************************************************************************/
/********************************************************** Computed Delay Parameters **********************************************************/
/* verilator lint_off WIDTHEXPAND */
localparam[3:0] PRECHARGE_TO_ACTIVATE_DELAY = find_delay(ps_to_nCK(tRP), PRECHARGE_SLOT, ACTIVATE_SLOT); //3
localparam[3:0] ACTIVATE_TO_PRECHARGE_DELAY = find_delay(ps_to_nCK(tRAS), ACTIVATE_SLOT, PRECHARGE_SLOT);
localparam[3:0] ACTIVATE_TO_WRITE_DELAY = find_delay(ps_to_nCK(tRCD), ACTIVATE_SLOT, WRITE_SLOT); //3
localparam[3:0] ACTIVATE_TO_READ_DELAY = find_delay(ps_to_nCK(tRCD), ACTIVATE_SLOT, READ_SLOT); //2
localparam[3:0] READ_TO_WRITE_DELAY = find_delay((CL_nCK + tCCD + 2 - CWL_nCK), READ_SLOT, WRITE_SLOT); //2
localparam[3:0] READ_TO_READ_DELAY = 0;
localparam[3:0] READ_TO_PRECHARGE_DELAY = find_delay(ps_to_nCK(tRTP), READ_SLOT, PRECHARGE_SLOT); //1
localparam[3:0] WRITE_TO_WRITE_DELAY = 0;
localparam[3:0] WRITE_TO_READ_DELAY = find_delay((CWL_nCK + 4 + ps_to_nCK(tWTR)), WRITE_SLOT, READ_SLOT); //4
localparam[3:0] WRITE_TO_PRECHARGE_DELAY = find_delay((CWL_nCK + 4 + ps_to_nCK(tWR)), WRITE_SLOT, PRECHARGE_SLOT); //5
/* verilator lint_on WIDTHEXPAND */
localparam PRE_REFRESH_DELAY = WRITE_TO_PRECHARGE_DELAY + 1;
`ifdef FORMAL
(*keep*) wire[3:0] f_PRECHARGE_TO_ACTIVATE_DELAY, f_ACTIVATE_TO_PRECHARGE_DELAY, f_ACTIVATE_TO_WRITE_DELAY, f_ACTIVATE_TO_READ_DELAY,
f_READ_TO_WRITE_DELAY, f_READ_TO_READ_DELAY, f_READ_TO_PRECHARGE_DELAY, f_WRITE_TO_WRITE_DELAY,
f_WRITE_TO_READ_DELAY, f_WRITE_TO_PRECHARGE_DELAY;
assign f_PRECHARGE_TO_ACTIVATE_DELAY = PRECHARGE_TO_ACTIVATE_DELAY;
assign f_ACTIVATE_TO_PRECHARGE_DELAY = ACTIVATE_TO_PRECHARGE_DELAY;
assign f_ACTIVATE_TO_WRITE_DELAY = ACTIVATE_TO_WRITE_DELAY;
assign f_ACTIVATE_TO_READ_DELAY = ACTIVATE_TO_READ_DELAY;
assign f_READ_TO_WRITE_DELAY = READ_TO_WRITE_DELAY;
assign f_READ_TO_READ_DELAY = READ_TO_READ_DELAY;
assign f_READ_TO_PRECHARGE_DELAY = READ_TO_PRECHARGE_DELAY;
assign f_WRITE_TO_WRITE_DELAY = WRITE_TO_WRITE_DELAY;
assign f_WRITE_TO_READ_DELAY = WRITE_TO_READ_DELAY;
assign f_WRITE_TO_PRECHARGE_DELAY = WRITE_TO_PRECHARGE_DELAY;
`endif
//MARGIN_BEFORE_ANTICIPATE is the number of columns before the column
//end when the anticipate can start
//the worst case scenario is when the anticipated bank needs to be precharged
//thus the margin must satisfy tRP (for precharge) and tRCD (for activate).
//Also, worscase is when the anticipated bank still has the leftover of the
//WRITE_TO_PRECHARGE_DELAY thus consider also this.
localparam MARGIN_BEFORE_ANTICIPATE = PRECHARGE_TO_ACTIVATE_DELAY + ACTIVATE_TO_WRITE_DELAY + WRITE_TO_PRECHARGE_DELAY;
// STAGE2_DATA_DEPTH is the number of controller clk cycles of delay before issuing the data after the write command
// depends on the CWL_nCK
/* verilator lint_off WIDTHEXPAND */
localparam STAGE2_DATA_DEPTH = (CWL_nCK - (3 - WRITE_SLOT + 1))/4 + 1; //this is always >= 1 (5 - (3 - 3 + 1))/4.0 -> floor(1) + 1 = floor(4
/* verilator lint_on WIDTHEXPAND */
`ifdef FORMAL
wire stage2_data_depth;
assign stage2_data_depth = STAGE2_DATA_DEPTH;
always @* begin
assert(STAGE2_DATA_DEPTH-2 >= 0);
end
`endif
localparam READ_DELAY = $rtoi($floor((CL_nCK - (3 - READ_SLOT + 1))/4.0 )); // how many controller clk cycles to satisfy CL_nCK of ddr3_clk cycles
// READ_ACK_PIPE_WIDTH is the delay between read command issued (starting from the controller) until the data is received by the controller
//the delays included the ODELAY and OSERDES when issuing the read command
//and the IDELAY and ISERDES when receiving the data (NOTE TO SELF: ELABORATE ON WHY THOSE MAGIC NUMBERS)
localparam READ_ACK_PIPE_WIDTH = READ_DELAY + 1 + 2 + 1 + 1;
localparam MAX_ADDED_READ_ACK_DELAY = 16;
localparam DELAY_BEFORE_WRITE_LEVEL_FEEDBACK = STAGE2_DATA_DEPTH + ps_to_cycles(tWLO+tWLOE) + 10;
//plus 10 controller clocks for possible bus latency and the delay for receiving feedback DQ from IOBUF -> IDELAY -> ISERDES
localparam ECC_INFORMATION_BITS = (ECC_ENABLE == 2)? max_information_bits(wb_data_bits) : max_information_bits(wb_data_bits/8);
/*********************************************************************************************************************************************/
/********************************************************** Read/Write Calibration Parameters **********************************************************/
localparam IDLE = 0,
BITSLIP_DQS_TRAIN_1 = 1,
MPR_READ = 2,
COLLECT_DQS = 3,
ANALYZE_DQS = 4,
CALIBRATE_DQS = 5,
BITSLIP_DQS_TRAIN_2 = 6,
START_WRITE_LEVEL = 7,
WAIT_FOR_FEEDBACK = 8,
ISSUE_WRITE_1 = 9,
ISSUE_WRITE_2 = 10,
ISSUE_READ = 11,
//ISSUE_READ_2 = 12,
READ_DATA = 12,
ANALYZE_DATA = 13,
CHECK_STARTING_DATA = 14,
BITSLIP_DQS_TRAIN_3 = 15,
//WRITE_ZERO = 16,
BURST_WRITE = 17,
BURST_READ = 18,
RANDOM_WRITE = 19,
RANDOM_READ = 20,
ALTERNATE_WRITE_READ = 21,
FINISH_READ = 22,
DONE_CALIBRATE = 23;
localparam STORED_DQS_SIZE = 5, //must be >= 2
REPEAT_DQS_ANALYZE = 1,
REPEAT_CLK_SAMPLING = 5; // repeat DQS read to find the accurate starting position of DQS
/*********************************************************************************************************************************************/
/************************************************************* Set Mode Registers Parameters *************************************************************/
// MR2 (JEDEC DDR3 doc pg. 30)
localparam[2:0] PASR = 3'b000; //Partial Array Self-Refresh: Full Array
localparam[3:0] CWL = CWL_nCK-4'd5; //CAS write Latency
localparam[0:0] ASR = 1'b1; //Auto Self-Refresh: on
localparam[0:0] SRT = 1'b0; //Self-Refresh Temperature Range:0 (If ASR = 1, SRT bit must be set to 0)
localparam[1:0] RTT_WR = 2'b00; //Dynamic ODT: off
localparam[2:0] MR2_SEL = 3'b010; //Selected Mode Register
localparam[18:0] MR2 = {MR2_SEL, 5'b00000, RTT_WR, 1'b0, SRT, ASR, CWL[2:0], PASR};
// MR3 (JEDEC DDR3 doc pg. 32)
localparam[1:0] MPR_LOC = 2'b00; //Data location for MPR Reads: Predefined Pattern 0_1_0_1_0_1_0_1
localparam[0:0] MPR_EN = 1'b1; //MPR Enable: Enable MPR reads and calibration during initialization
localparam[2:0] MR3_SEL = 3'b011; //MPR Selected
localparam[18:0] MR3_MPR_EN = {MR3_SEL, 13'b0_0000_0000_0000, MPR_EN, MPR_LOC};
localparam[18:0] MR3_MPR_DIS = {MR3_SEL, 13'b0_0000_0000_0000, !MPR_EN, MPR_LOC};
// MR1 (JEDEC DDR3 doc pg. 27)
localparam DLL_EN = 1'b0; //DLL Enable/Disable: Enabled(0)
// localparam[1:0] DIC = 2'b01; //Output Driver Impedance Control (RZQ/7) (elevate this to parameter)
// localparam[2:0] RTT_NOM = 3'b001; //RTT Nominal: RZQ/4 (elevate this to parameter)
localparam[0:0] WL_EN = 1'b1; //Write Leveling Enable: Disabled
localparam[1:0] AL = 2'b00; //Additive Latency: Disabled
localparam[0:0] TDQS = 1'b0; //Termination Data Strobe: Disabled (provides additional termination resistance outputs.
//When the TDQS function is disabled, the DM function is provided (vice-versa).TDQS function is only
//available for X8 DRAM and must be disabled for X4 and X16.
localparam[0:0] QOFF = 1'b0; //Output Buffer Control: Enabled
localparam[2:0] MR1_SEL = 3'b001; //Selected Mode Register
localparam[18:0] MR1_WL_EN = {MR1_SEL, 3'b000, QOFF, TDQS, 1'b0, RTT_NOM[2], 1'b0, WL_EN, RTT_NOM[1], DIC[1], AL, RTT_NOM[0], DIC[0], DLL_EN};
localparam[18:0] MR1_WL_DIS = {MR1_SEL, 3'b000, QOFF, TDQS, 1'b0, RTT_NOM[2], 1'b0, !WL_EN, RTT_NOM[1], DIC[1], AL, RTT_NOM[0], DIC[0], DLL_EN};
//MR0 (JEDEC DDR3 doc pg. 24)
localparam[1:0] BL = 2'b00; //Burst Length: 8 (Fixed)
localparam[3:0] CL = (CL_nCK-4)*2; //CAS Read Latency
localparam[0:0] RBT = 1'b0; //Read Burst Type: Nibble Sequential
localparam[0:0] DLL_RST = 1'b1; //DLL Reset: Yes (this is self-clearing and must be applied after DLL enable)
localparam[2:0] WR = WRA_mode_register_value($rtoi($ceil(tWR/DDR3_CLK_PERIOD))); //Write recovery for autoprecharge (
localparam[0:0] PPD = 1'b0; //DLL Control for Precharge PD: Slow exit (DLL off)
localparam[2:0] MR0_SEL = 3'b000;
localparam[18:0] MR0 = {MR0_SEL, 3'b000, PPD, WR, DLL_RST, 1'b0, CL[3:1], RBT, CL[0], BL};
/*********************************************************************************************************************************************/
localparam INITIAL_RESET_INSTRUCTION = {5'b01000 , CMD_NOP , { {(DELAY_SLOT_WIDTH-3){1'b0}} , 3'd5} };
/************************************************************* Registers and Wires *************************************************************/
integer index;
(* mark_debug ="true" *) reg[4:0] instruction_address = 0; //address for accessing rom instruction
reg[27:0] instruction = INITIAL_RESET_INSTRUCTION; //instruction retrieved from reset instruction rom
reg[ DELAY_COUNTER_WIDTH - 1:0] delay_counter = INITIAL_RESET_INSTRUCTION[DELAY_COUNTER_WIDTH - 1:0]; //counter used for delays
reg delay_counter_is_zero = (INITIAL_RESET_INSTRUCTION[DELAY_COUNTER_WIDTH - 1:0] == 0); //counter is now zero so retrieve next delay
reg reset_done = 0; //high if reset has already finished
reg pause_counter = 0;
wire issue_read_command;
reg stage2_update = 1;
reg stage2_stall = 0;
reg stage1_stall = 0;
reg[(1<<(BA_BITS+DUAL_RANK_DIMM))-1:0] bank_status_q, bank_status_d; //bank_status[bank_number]: determine current state of bank (1=active , 0=idle)
//bank_active_row[bank_number] = stores the active row address in the specified bank
reg[ROW_BITS-1:0] bank_active_row_q[(1<<(BA_BITS+DUAL_RANK_DIMM))-1:0], bank_active_row_d[(1<<(BA_BITS+DUAL_RANK_DIMM))-1:0];
// ECC_ENABLE = 3 regs
/* verilator lint_off UNUSEDSIGNAL */
reg[BA_BITS-1:0] ecc_bank_addr = 0, ecc_bank_addr_prev = 0;
reg[ROW_BITS-1:0] ecc_row_addr = 0, ecc_row_addr_prev = 0;
reg[COL_BITS-1:0] ecc_col_addr = 0, ecc_col_addr_prev = 0;
reg we_prev;
reg stage0_pending = 0;
reg[wb_addr_bits - 1:0] stage0_addr = 0;
reg[AUX_WIDTH-1:0] stage0_aux = 0;
reg stage0_we = 0;
reg[wb_data_bits - 1:0] stage0_data = 0;
wire ecc_stage1_stall;
reg ecc_stage2_stall;
wire stage1_update, stage1_update_calib, stage0_update;
reg wb_stb_mux = 0;
reg[AUX_WIDTH-1:0] aux_mux = 0;
reg wb_we_mux = 0;
reg[wb_addr_bits - 1:0] wb_addr_mux = 0;
reg[wb_data_bits - 1:0] wb_data_mux = 0;
reg[wb_addr_bits-1:0] calib_addr_mux;
reg[wb_data_bits-1:0] calib_data_mux;
reg calib_stb_mux;
reg calib_we_mux;
reg[AUX_WIDTH-1:0] calib_aux_mux;
reg write_ecc_stored_to_mem_q, write_ecc_stored_to_mem_d;
reg[wb_data_bits - 1:0] stage2_ecc_write_data_q = 0, stage2_ecc_write_data_d;
reg[wb_data_bits - 1:0] stage2_ecc_read_data_q = 0, stage2_ecc_read_data_d;
reg[wb_sel_bits - 1 : 0] stage2_ecc_write_data_mask_q = 0, stage2_ecc_write_data_mask_d;
wire[wb_data_bits/8 - 1 : 0] decoded_parity;
wire[wb_data_bits/8 - 1 : 0] encoded_parity;
reg[wb_data_bits/8 - 1 : 0] stage2_encoded_parity = 0;
reg ecc_req_stage2 = 0;
/* verilator lint_on UNUSEDSIGNAL */
//pipeline stage 1 regs
reg stage1_pending = 0;
reg[AUX_WIDTH-1:0] stage1_aux = 0;
reg stage1_we = 0;
reg[wb_data_bits - 1:0] stage1_data = 0;
wire[wb_data_bits - 1:0] stage1_data_mux, stage1_data_encoded;
reg[wb_sel_bits - 1:0] stage1_dm = 0;
reg[COL_BITS-1:0] stage1_col = 0;
reg[BA_BITS-1+DUAL_RANK_DIMM:0] stage1_bank = 0;
reg[ROW_BITS-1:0] stage1_row = 0;
reg[BA_BITS-1+DUAL_RANK_DIMM:0] stage1_next_bank = 0;
reg[ROW_BITS-1:0] stage1_next_row = 0;
wire[wb_addr_bits-1:0] wb_addr_plus_anticipate, calib_addr_plus_anticipate;
//pipeline stage 2 regs
reg stage2_pending = 0;
reg[AUX_WIDTH-1:0] stage2_aux = 0;
reg stage2_we = 0;
reg[wb_sel_bits - 1:0] stage2_dm_unaligned = 0, stage2_dm_unaligned_temp = 0;
reg[wb_sel_bits - 1:0] stage2_dm[STAGE2_DATA_DEPTH-1:0];
reg[wb_data_bits - 1:0] stage2_data_unaligned = 0, stage2_data_unaligned_temp = 0;
reg[wb_data_bits - 1:0] stage2_data[STAGE2_DATA_DEPTH-1:0];
reg [DQ_BITS*8 - 1:0] unaligned_data[LANES-1:0];
reg [8 - 1:0] unaligned_dm[LANES-1:0];
reg[COL_BITS-1:0] stage2_col = 0;
reg[BA_BITS-1+DUAL_RANK_DIMM:0] stage2_bank = 0;
reg[ROW_BITS-1:0] stage2_row = 0;
//delay counter for every banks
reg[3:0] delay_before_precharge_counter_q[(1<<(BA_BITS+DUAL_RANK_DIMM))-1:0], delay_before_precharge_counter_d[(1<<(BA_BITS+DUAL_RANK_DIMM))-1:0]; //delay counters
reg[3:0] delay_before_activate_counter_q[(1<<(BA_BITS+DUAL_RANK_DIMM))-1:0], delay_before_activate_counter_d[(1<<(BA_BITS+DUAL_RANK_DIMM))-1:0] ;
reg[3:0] delay_before_write_counter_q[(1<<(BA_BITS+DUAL_RANK_DIMM))-1:0], delay_before_write_counter_d[(1<<(BA_BITS+DUAL_RANK_DIMM))-1:0] ;
reg[3:0] delay_before_read_counter_q[(1<<(BA_BITS+DUAL_RANK_DIMM))-1:0] , delay_before_read_counter_d[(1<<(BA_BITS+DUAL_RANK_DIMM))-1:0] ;
//commands to be sent to PHY (4 slots per controller clk cycle)
reg[cmd_len-1:0] cmd_d[3:0];
initial begin
o_phy_bitslip = 0;
end
reg cmd_odt_q = 0, cmd_odt, cmd_reset_n;
(* mark_debug = "true" *) reg[DUAL_RANK_DIMM:0] cmd_ck_en, prev_cmd_ck_en;
reg o_wb_stall_q = 1, o_wb_stall_d, o_wb_stall_calib = 1;
reg precharge_slot_busy;
reg activate_slot_busy;
reg[1:0] write_dqs_q;
reg write_dqs_d;
reg[STAGE2_DATA_DEPTH:0] write_dqs;
reg[STAGE2_DATA_DEPTH:0] write_dqs_val;
reg[1:0] write_dq_q;
reg write_dq_d;
reg[STAGE2_DATA_DEPTH+1:0] write_dq;
(* mark_debug = "true" *) reg[$clog2(DONE_CALIBRATE)-1:0] state_calibrate;
reg[STORED_DQS_SIZE*8-1:0] dqs_store = 0;
reg[$clog2(STORED_DQS_SIZE)-1:0] dqs_count_repeat = 0;
(* mark_debug ="true" *) reg[$clog2(STORED_DQS_SIZE*8)-1:0] dqs_start_index = 0;
reg[$clog2(STORED_DQS_SIZE*8)-1:0] dqs_start_index_stored = 0;
(* mark_debug ="true" *) reg[$clog2(STORED_DQS_SIZE*8)-1:0] dqs_target_index = 0;
reg[$clog2(STORED_DQS_SIZE*8)-1:0] dqs_target_index_orig = 0;
reg[$clog2(STORED_DQS_SIZE*8):0] dq_target_index[LANES-1:0];
wire[$clog2(STORED_DQS_SIZE*8)-1:0] dqs_target_index_value;
(* mark_debug ="true" *) reg[$clog2(REPEAT_DQS_ANALYZE):0] dqs_start_index_repeat=0;
reg[3:0] train_delay;
reg[3:0] delay_before_read_data = 0;
reg[$clog2(DELAY_BEFORE_WRITE_LEVEL_FEEDBACK):0] delay_before_write_level_feedback = 0;
(* mark_debug = "true" *) reg initial_dqs = 0;
(* mark_debug = "true" *) reg[lanes_clog2-1:0] lane = 0;
reg[$clog2(8*LANES)-1:0] lane_times_8 = 0;
/* verilator lint_off UNUSEDSIGNAL */
reg[15:0] dqs_bitslip_arrangement = 0;
/* verilator lint_off UNUSEDSIGNAL */
reg[3:0] added_read_pipe_max = 0;
reg[3:0] added_read_pipe[LANES - 1:0];
//each lane will have added delay relative to when ISERDES should actually return the data
//this make sure that we will wait until the lane with longest delay (added_read_pipe_max) is received before
//all lanes are sent to wishbone data
//contains the ack shift reg for both read and write
reg[AUX_WIDTH:0] shift_reg_read_pipe_q[READ_ACK_PIPE_WIDTH-1:0];
reg[AUX_WIDTH:0] shift_reg_read_pipe_d[READ_ACK_PIPE_WIDTH-1:0]; //issue ack and AUX value , 1=issue command delay (OSERDES delay), 2 = ISERDES delay
reg index_read_pipe; //tells which delay_read_pipe will be updated (there are two delay_read_pipe)
reg index_wb_data; //tells which o_wb_data_q will be sent to o_wb_data
reg[15:0] delay_read_pipe[1:0]; //delay when each lane will retrieve i_phy_iserdes_data (since different lanes might not be aligned with each other and needs to be retrieved at a different time)
reg[wb_data_bits - 1:0] o_wb_data_q[1:0]; //store data retrieved from i_phy_iserdes_data to be sent to o_wb_data
wire[wb_data_bits - 1:0] o_wb_data_q_current;
reg[wb_data_bits - 1:0] o_wb_data_q_q;
reg[wb_data_bits - 1:0] o_wb_data_uncalibrated;
reg o_wb_ack_q = 0;
reg o_wb_err_q;
reg o_wb_ack_uncalibrated = 0;
reg[AUX_WIDTH:0] o_wb_ack_read_q[MAX_ADDED_READ_ACK_DELAY-1:0];
(* mark_debug = "true" *) reg calib_stb = 0;
reg[wb_sel_bits-1:0] calib_sel = 0;
reg[AUX_WIDTH-1:0] calib_aux = 0;
(* mark_debug = "true" *) reg calib_we = 0;
reg[wb_addr_bits-1:0] calib_addr = 0;
reg[wb_data_bits-1:0] calib_data = 0;
reg write_calib_odt = 0;
reg write_calib_dqs = 0;
reg write_calib_dq = 0;
(* mark_debug = "true" *) reg prev_write_level_feedback = 1;
reg[wb_data_bits-1:0] read_data_store = 0;
reg[127:0] write_pattern = 0;
reg[$clog2(64):0] data_start_index[LANES-1:0];
(* mark_debug = "true" *) reg[4:0] odelay_data_cntvaluein[LANES-1:0];
reg[4:0] odelay_dqs_cntvaluein[LANES-1:0];
reg[4:0] idelay_data_cntvaluein[LANES-1:0];
reg[4:0] idelay_data_cntvaluein_prev;
(* mark_debug = "true" *) reg[4:0] idelay_dqs_cntvaluein[LANES-1:0];
reg[$clog2(REPEAT_CLK_SAMPLING):0] sample_clk_repeat = 0;
(* mark_debug = "true" *) reg stored_write_level_feedback = 0;
reg[5:0] start_index_check = 0;
(* mark_debug = "true" *) reg[63:0] read_lane_data = 0;
(* mark_debug = "true" *) reg odelay_cntvalue_halfway = 0;
reg initial_calibration_done = 0;
reg final_calibration_done = 0;
assign o_calib_complete = final_calibration_done;
// Wishbone 2
reg wb2_stb = 0;
reg wb2_update = 0;
reg wb2_we = 0;
reg[WB2_ADDR_BITS-1:0] wb2_addr = 0;
reg[WB2_DATA_BITS-1:0] wb2_data = 0;
reg[wb2_sel_bits-1:0] wb2_sel = 0;
reg[4:0] wb2_phy_odelay_data_cntvaluein;
reg[4:0] wb2_phy_odelay_dqs_cntvaluein;
reg[4:0] wb2_phy_idelay_data_cntvaluein;
reg[4:0] wb2_phy_idelay_dqs_cntvaluein;
reg[LANES-1:0] wb2_phy_odelay_data_ld;
reg[LANES-1:0] wb2_phy_odelay_dqs_ld;
reg[LANES-1:0] wb2_phy_idelay_data_ld;
reg[LANES-1:0] wb2_phy_idelay_dqs_ld;
(* mark_debug ="true" *)reg[LANES-1:0] write_level_fail = 0;
reg[lanes_clog2-1:0] wb2_write_lane;
reg sync_rst_wb2 = 0, sync_rst_controller = 0, current_rank_rst = 0;
reg reset_from_wb2 = 0, reset_from_calibrate = 0, reset_from_test = 0, repeat_test = 0;
reg reset_after_rank_1 = 0; // reset after calibration rank 1 to switch to rank 2
reg current_rank = 0;
// test calibration
reg[wb_addr_bits-1:0] read_test_address_counter = 0, check_test_address_counter = 0; ////////////////////////////////////////////////////////
reg[31:0] write_test_address_counter = 0;
reg[31:0] correct_read_data = 0, wrong_read_data = 0;
/* verilator lint_off UNDRIVEN */
(* mark_debug = "true" *) wire sb_err_o;
wire db_err_o;
wire[wb_data_bits - 1:0] o_wb_data_q_decoded;
/* verilator lint_on UNDRIVEN */
(* mark_debug ="true" *) reg user_self_refresh_q; // registered i_user_self_refresh
// initial block for all regs
initial begin
o_wb_stall = 1;
for(index = 0; index < MAX_ADDED_READ_ACK_DELAY; index = index + 1) begin
o_wb_ack_read_q[index] = 0;
end
for(index=0; index < (1<<(BA_BITS+DUAL_RANK_DIMM)); index=index+1) begin
bank_status_q[index] = 0;
bank_status_d[index] = 0;
bank_active_row_q[index] = 0;
bank_active_row_d[index] = 0;
end
for(index = 0; index < STAGE2_DATA_DEPTH; index = index+1) begin
stage2_data[index] = 0;
stage2_dm[index] = 0;
end
for(index=0; index <(1<<(BA_BITS+DUAL_RANK_DIMM)); index=index+1) begin
delay_before_precharge_counter_q[index] = 0;
delay_before_activate_counter_q[index] = 0;
delay_before_write_counter_q[index] = 0;
delay_before_read_counter_q[index] = 0;
end
for(index = 0; index < READ_ACK_PIPE_WIDTH; index = index + 1) begin
shift_reg_read_pipe_q[index] = 0;
shift_reg_read_pipe_d[index] = 0;
end
//set all commands to all 1's makig CS_n high (thus commands are initially NOP)
for(index=0; index < 4; index=index+1) begin
cmd_d[index] = -1;
end
for(index = 0; index < LANES; index = index + 1) begin
odelay_data_cntvaluein[index] = DATA_INITIAL_ODELAY_TAP[4:0];
odelay_dqs_cntvaluein[index] = DQS_INITIAL_ODELAY_TAP[4:0];
idelay_data_cntvaluein[index] = DATA_INITIAL_IDELAY_TAP[4:0];
idelay_dqs_cntvaluein[index] = DQS_INITIAL_IDELAY_TAP[4:0];
dq_target_index[index] = 0;
end
end
/*********************************************************************************************************************************************/
/******************************************* Reset Sequence (JEDEC DDR3 doc pg. 19) *******************************************/
// This reset and refresh sequence logic is designed for simplicity. This uses a Read-Only Memory (ROM))
// to store the commands and time delay. A constant function is used store instructions instead of registers
// to ensure that ROM wil not change values during formal verification induction.
// This idea is sourced from https://zipcpu.com/formal/2019/11/18/genuctrlr.html
// Instruction format:
// RST_DONE/REF_IDLE = 27; //RST_DONE = non-persistent, only needs to be toggled once, command bit that determines if reset seqeunce had aready finished
//REF_IDLE = No refresh is about to start and no ongoing refresh.
// USE_TIMER = 26; // Command bit that determines if timer will be used (if delay is zero, USE_TIMER must be LOW)
// A10_CONTROL = 25, //Command bit that determines if A10 Precharge All Bank will be high
// CLOCK_EN = 24; //Clock-enable to DDR3
// RESET_N = 23; //Reset_n to DDR3
// DDR3_CMD = 22:19
// Timer-Delay or MRS = 18:0 //timer delay and MRS shares same slot, thus MRS commands cannot have delays
// NOTE: The timer delay is a delay in clock cycles AFTER EXECUTING COMMAND, not the ACTUAL CYCLES of the command
// (delay of 1 means 2 clock cycles of command execution) //initial reset instruction has low rst_n, low cke, and has delay of 5
function [27:0] read_rom_instruction(input[4:0] func_instruction_address); begin
case(func_instruction_address)
5'd0:
if (MICRON_SIM)
read_rom_instruction = {5'b01000 , CMD_NOP , ps_to_cycles(POWER_ON_RESET_HIGH/500)};
else
read_rom_instruction = {5'b01000 , CMD_NOP , ps_to_cycles(POWER_ON_RESET_HIGH)};
//0. RESET# needs to be maintained low for minimum 200us with power-up initialization. CKE is pulled
//“Low�? anytime before RESET# being de-asserted (min. time 10 ns). .
5'd1:
if (MICRON_SIM)
read_rom_instruction = {5'b01001 , CMD_NOP, ps_to_cycles(INITIAL_CKE_LOW/500)};
else
read_rom_instruction = {5'b01001 , CMD_NOP, ps_to_cycles(INITIAL_CKE_LOW)};
//1. After RESET# is de-asserted, wait for another 500 us until CKE becomes active. During this time, the
//DRAM will start internal state initialization; this will be done independently of external clocks.
// .... Also, a NOP or Deselect command must be registered (with tIS set up time to clock) before
//CKE goes active.
5'd2: read_rom_instruction = {5'b01011 , CMD_NOP, ps_to_cycles(tXPR)};
//2. After CKE is being registered high, wait minimum of Reset CKE Exit time, tXPR.
5'd3: read_rom_instruction = {{2'b00,MR2[10], 2'b11}, CMD_MRS, MR2};
//3. Issue MRS command to load MR2.
5'd4: read_rom_instruction = {{2'b00,MR3_MPR_DIS[10], 2'b11}, CMD_MRS, MR3_MPR_DIS};
//4. All banks must first be in the idle state (all banks precharged and tRP met) before doing MPR calibration, thus issue first disabled MR3
5'd5: read_rom_instruction = {{2'b00,MR1_WL_DIS[10], 2'b11}, CMD_MRS, MR1_WL_DIS};
//5. Issue MRS command to load MR1, enable DLL,and disable WL.
5'd6: read_rom_instruction = {{2'b00,MR0[10], 2'b11}, CMD_MRS, MR0};
//6. Issue MRS command to load MR0 and reset DLL.
5'd7: read_rom_instruction = {5'b01011, CMD_NOP, tMOD[DELAY_SLOT_WIDTH-1:0]};
//7. Delay of tMOD between MRS command to a non-MRS command excluding NOP and DES
5'd8: read_rom_instruction = {5'b01111, CMD_ZQC, tZQinit[DELAY_SLOT_WIDTH-1:0]};
//8. ZQ Calibration command is used to calibrate DRAM Ron & ODT values. ZQCL command triggers the calibration engine
//inside the DRAM and, once calibration is achieved, the calibrated values area transferred from the calibration engine to
//DRAM IO, which gets reflected as updated output driver
// Precharge all banks before enabling MPR
5'd9: read_rom_instruction = {5'b01111, CMD_PRE, ps_to_cycles(tRP)};
//9. All banks must be precharged (A10-AP = high) and idle for a minimum of the precharge time tRP(min) before the Refresh Command can be applied.
5'd10: read_rom_instruction = {{2'b00,MR3_MPR_EN[10], 2'b11}, CMD_MRS, MR3_MPR_EN};
//10. Issue MRS command to load MR3. Prior to enabling the MPR for read calibration, all banks must be in the idle state (all banks
// precharged and tRP met). Once the MPR is enabled, any subsequent RD or RDA commands will be redirected to the MultiPurpose Register.
5'd11: read_rom_instruction = {5'b01011, CMD_NOP, tMOD[DELAY_SLOT_WIDTH-1:0]};
//11. Delay of tMOD between MRS command to a non-MRS command excluding NOP and DES
5'd12: read_rom_instruction = {5'b01011, CMD_NOP, CALIBRATION_DELAY[DELAY_SLOT_WIDTH-1:0]};
//12. Delay for read calibration
5'd13: read_rom_instruction = {{2'b00,MR3_MPR_DIS[10], 2'b11}, CMD_MRS, MR3_MPR_DIS};
//13. Disable MPR after read calibration
5'd14: read_rom_instruction = {{2'b00,MR1_WL_EN[10], 2'b11}, CMD_MRS, MR1_WL_EN};
//14. Issue MRS command to load MR1, and enable WL.
5'd15: read_rom_instruction = {5'b01011, CMD_NOP, tWLMRD[DELAY_SLOT_WIDTH-1:0]};
//15. Delay of tMOD between MRS command to a non-MRS command excluding NOP and DES
5'd16: read_rom_instruction = {5'b01011, CMD_NOP, CALIBRATION_DELAY[DELAY_SLOT_WIDTH-1:0]};
//16. Delay for write calibration
5'd17: read_rom_instruction = {{2'b00,MR1_WL_DIS[10], 2'b11}, CMD_MRS, MR1_WL_DIS};
//17. Issue MRS command to load MR1, and disable WL.
5'd18: read_rom_instruction = {5'b01011, CMD_NOP, tMOD[DELAY_SLOT_WIDTH-1:0]};
//18. Delay of tMOD between MRS command to a non-MRS command excluding NOP and DES
// Perform first refresh and any subsequent refresh (so instruction 19 to 22 will be re-used for the refresh sequence)
5'd19: read_rom_instruction = {5'b01111, CMD_PRE, ps_to_cycles(tRP)};
//19. All banks must be precharged (A10-AP = high) and idle for a minimum of the precharge time tRP(min) before the Refresh Command can be applied.
5'd20: read_rom_instruction = {5'b01011, CMD_REF, ps_to_cycles(tRFC)};
//20. A delay between the Refresh Command and the next valid command, except NOP or DES, must be greater than or equal to the minimum
//Refresh cycle time tRFC(min)
5'd21: read_rom_instruction = {5'b11011, CMD_NOP, ps_to_cycles(tREFI)};
//21. Reset ends now. The refresh interval also starts to count.
5'd22: read_rom_instruction = {5'b01011, CMD_NOP, PRE_REFRESH_DELAY[DELAY_SLOT_WIDTH-1:0]};
// 22. Extra delay needed before starting the refresh sequence.
// (this already sets the wishbone stall high to make sure no user request is on-going when refresh seqeunce starts)
5'd23: read_rom_instruction = {5'b01111, CMD_PRE, ps_to_cycles(tRP)};
// 23. All banks must be precharged (A10-AP = high) and idle for a minimum of the precharge time tRP(min) before the Self-Refresh Command can be applied.
5'd24: read_rom_instruction = {5'b01001, CMD_SREF_EN, tCKESR[DELAY_SLOT_WIDTH-1:0]};
// 24. Self-refresh entry
// JEDEC Standard No. 79-3E Page 79: The minimum time that the DDR3 SDRAM must remain in Self-Refresh mode is tCKESR
5'd25: read_rom_instruction = {5'b01001, CMD_NOP, tCPDED[DELAY_SLOT_WIDTH-1:0]};
// 25. tCPDED cycles of NOP are required after CKE low
5'd26: read_rom_instruction = {5'b01011, CMD_SREF_XT, tXSDLL_tRFC[DELAY_SLOT_WIDTH-1:0]};
// 26. From 25 (Self-refresh entry), wait until user-self_refresh is disabled then wait for tXSDLL - tRFC before going to 20 (Refresh)
// JEDEC Standard No. 79-3E Page 79: Before a command that requires a locked DLL can be applied, a delay of at least tXSDLL must be satisfied.
// JEDEC Standard No. 79-3E Page 80: Upon exit from Self-Refresh, the DDR3 SDRAM requires a minimum of one extra refresh command before it is put back into Self-Refresh Mode.
default: read_rom_instruction = {5'b00011, CMD_NOP, {(DELAY_SLOT_WIDTH){1'b0}}};
endcase
end
endfunction
/*********************************************************************************************************************************************/
/******************************************* Reset Sequence ROM Controller *******************************************/
always @(posedge i_controller_clk) begin
sync_rst_controller <= !i_rst_n || reset_from_wb2 || reset_from_calibrate || reset_from_test || reset_after_rank_1;
current_rank_rst <= !i_rst_n || reset_from_wb2 || reset_from_calibrate || reset_from_test;
sync_rst_wb2 <= !i_rst_n;
end
assign o_phy_reset = current_rank_rst; // PHY will not reset when transitioning from rank 0 to rank 1
always @(posedge i_controller_clk) begin
if(sync_rst_controller) begin
instruction_address <= 0;
`ifdef FORMAL_COVER
instruction_address <= 21;
`endif
instruction <= INITIAL_RESET_INSTRUCTION;
delay_counter <= INITIAL_RESET_INSTRUCTION[DELAY_COUNTER_WIDTH - 1:0];
delay_counter_is_zero <= (INITIAL_RESET_INSTRUCTION[DELAY_COUNTER_WIDTH - 1:0] == 0);
reset_done <= 1'b0;
end
else begin
//update counter after reaching zero
if(delay_counter_is_zero) begin
delay_counter <= instruction[DELAY_COUNTER_WIDTH - 1:0]; //retrieve delay value of current instruction, we count to zero thus minus 1
end
//else: decrement delay counter when current instruction needs delay
//don't decrement (has infinite time) when last bit of
//delay_counter is 1 (for r/w calibration and prestall delay)
//address will only move forward for these kinds of delay only
//when skip_reset_seq_delay is toggled
else if(instruction[USE_TIMER] /*&& delay_counter != {(DELAY_COUNTER_WIDTH){1'b1}}*/ && !pause_counter && delay_counter != 0) delay_counter <= delay_counter - 1;
//delay_counter of 1 means we will need to update the delay_counter next clock cycle (delay_counter of zero) so we need to retrieve
//now the next instruction. The same thing needs to be done when current instruction does not need the timer delay.
if( ((delay_counter == 1) && !pause_counter) || !instruction[USE_TIMER]/* || skip_reset_seq_delay*/) begin
delay_counter_is_zero <= 1;
instruction <= read_rom_instruction(instruction_address);
if(instruction_address == 5'd22) begin // if user_self_refresh is disabled, wrap back to 19 (Precharge All before Refresh)
instruction_address <= 5'd19;
end
else if(instruction_address == 5'd26) begin // self-refresh exit always wraps back to 20 (Refresh)
instruction_address <= 5'd20;
end
else begin
instruction_address <= instruction_address + 5'd1; // just increment address
end
end
//we are now on the middle of a delay
else begin
delay_counter_is_zero <=0;
end
if(instruction_address == 5'd22 && user_self_refresh_q) begin // if user_self_refresh is enabled, go straight to 23
instruction_address <= 23; // go to Precharge All for Self-refresh
delay_counter_is_zero <= 1;
delay_counter <= 0;
instruction <= read_rom_instruction(instruction_address);
end
//instruction[RST_DONE] is non-persistent thus we need to register it once it goes high
reset_done <= instruction[RST_DONE]? 1'b1:reset_done;
end
end
// register user-enabled self-refresh
always @(posedge i_controller_clk) begin
user_self_refresh_q <= i_user_self_refresh && (user_self_refresh_q || (instruction_address != 5'd26)) && final_calibration_done; //will not go high again if already at instruction_address 26 (self-refresh exit), only go high when calibration is done
if(DUAL_RANK_DIMM[0]) begin // if dual rank enabled, then enable self refresh right after completing calibration
if(state_calibrate == FINISH_READ) begin
user_self_refresh_q <= 1'b1;
end
end
end
/*********************************************************************************************************************************************/
/******************************************************* Track Bank Status and Issue Command *******************************************************/
//process request transaction
always @(posedge i_controller_clk) begin
if(sync_rst_controller) begin
o_wb_stall <= 1'b1;
o_wb_stall_q <= 1'b1;
o_wb_stall_calib <= 1'b1;
//set stage 1 to 0
stage1_pending <= 0;
stage1_aux <= 0;
stage1_we <= 0;
stage1_dm <= 0;
stage1_col <= 0;
stage1_bank <= 0;
stage1_row <= 0;
stage1_next_bank <= 0;
stage1_next_row <= 0;
stage1_data <= 0;
//set stage2 to 0
stage2_pending <= 0;
stage2_aux <= 0;
stage2_we <= 0;
stage2_col <= 0;
stage2_bank <= 0;
stage2_row <= 0;
cmd_odt_q <= 0;
stage2_data_unaligned <= 0;
stage2_data_unaligned_temp <= 0;
stage2_dm_unaligned <= 0;
stage2_dm_unaligned_temp <= 0;
if(ECC_ENABLE == 3) begin
ecc_col_addr_prev <= 0;
ecc_bank_addr_prev <= 0;
ecc_row_addr_prev <= 0;
ecc_bank_addr <= 0;
ecc_row_addr <= 0;
ecc_col_addr <= 0;
stage2_encoded_parity <= 0;
end
for(index=0; index<LANES; index=index+1) begin
unaligned_data[index] <= 0;
unaligned_dm[index] <= 0;
end
//set delay counters to 0
for(index=0; index<(1<<(BA_BITS+DUAL_RANK_DIMM)); index=index+1) begin
delay_before_precharge_counter_q[index] <= 0;
delay_before_activate_counter_q[index] <= 0;
delay_before_write_counter_q[index] <= 0;
delay_before_read_counter_q[index] <= 0;
end
//reset bank status and active row
for( index=0; index < (1<<(BA_BITS+DUAL_RANK_DIMM)); index=index+1) begin
bank_status_q[index] <= 0;
bank_active_row_q[index] <= 0;
end
//reset data
for(index = 0; index < STAGE2_DATA_DEPTH; index = index+1) begin
stage2_data[index] <= 0;
stage2_dm[index] <= 0;
end
end
// can only start accepting requests when reset is done
else if(reset_done) begin
o_wb_stall <= o_wb_stall_d || state_calibrate != DONE_CALIBRATE;
o_wb_stall_q <= o_wb_stall_d;
o_wb_stall_calib <= o_wb_stall_d; //wb stall for calibration stage
cmd_odt_q <= cmd_odt;
//update delay counter
for(index=0; index< (1<<(BA_BITS+DUAL_RANK_DIMM)); index=index+1) begin
delay_before_precharge_counter_q[index] <= delay_before_precharge_counter_d[index];
delay_before_activate_counter_q[index] <= delay_before_activate_counter_d[index];
delay_before_write_counter_q[index] <= delay_before_write_counter_d[index];
delay_before_read_counter_q[index] <= delay_before_read_counter_d[index];
end
//update bank status and active row
for(index=0; index < (1<<(BA_BITS+DUAL_RANK_DIMM)); index=index+1) begin
bank_status_q[index] <= bank_status_d[index];
bank_active_row_q[index] <= bank_active_row_d[index];
end
if(instruction_address == 20 || instruction_address == 24) begin ///current instruction at precharge
cmd_odt_q <= 1'b0;
//all banks will be in idle after refresh
for( index=0; index < (1<<(BA_BITS+DUAL_RANK_DIMM)); index=index+1) begin
bank_status_q[index] <= 0;
end
end
//refresh sequence is on-going
if(!instruction[REF_IDLE]) begin
//no transaction will be pending during refresh
o_wb_stall <= 1'b1;
o_wb_stall_calib <= 1'b1;
end
//if pipeline is not stalled (or a request is left on the prestall
//delay address 19 or if in calib), move pipeline to stage 2
if(stage2_update) begin //ITS POSSIBLE ONLY NEXT CLK WILL STALL SUPPOSE TO GO LOW
stage2_pending <= stage1_pending;
if(ECC_ENABLE != 3) begin
stage1_pending <= 1'b0; //no request initially unless overridden by the actual stb request
stage2_pending <= stage1_pending;
stage2_aux <= stage1_aux;
stage2_we <= stage1_we;
stage2_col <= stage1_col;
stage2_bank <= stage1_bank;
stage2_row <= stage1_row;
if(ODELAY_SUPPORTED) begin
stage2_data_unaligned <= stage1_data_mux;
stage2_dm_unaligned <= ~stage1_dm; //inverse each bit (1 must mean "masked" or not written)
end
else begin
stage2_data_unaligned_temp <= stage1_data_mux;
stage2_dm_unaligned_temp <= ~stage1_dm; //inverse each bit (1 must mean "masked" or not written)
end
end
// ECC_ENABLE == 3
else begin
stage1_pending <= ecc_stage1_stall? stage1_pending : 1'b0; //stage1 remains the same for ECC op (no request initially unless overridden by the actual stb request)
// if switching from write to read and ECC is not yet written then do a write first to store those ECC bits
if(!stage1_we && stage2_we && stage1_pending && !write_ecc_stored_to_mem_d && initial_calibration_done) begin
stage2_we <= 1'b1;
// if ecc_stage1_stall, stage2 will start ECC write/read operation
// if ECC write, then we are writing ECC for previous address
// if ECC read, then we are reading ECC for current address
stage2_col <= ecc_col_addr_prev;
stage2_bank[BA_BITS-1:0] <= ecc_bank_addr_prev;
stage2_row <= ecc_row_addr_prev;
ecc_col_addr_prev <= ecc_col_addr;
ecc_bank_addr_prev <= ecc_bank_addr;
ecc_row_addr_prev <= ecc_row_addr;
// For ECC requests, 2MSB of aux determines type of ECC request (read = 2'10, write = 2'b11)
stage2_aux <= { 1'b1, 1'b1, 3'b000, {(AUX_WIDTH-5){1'b1}} };
end
else begin
stage2_we <= stage1_we;
// if ecc_stage1_stall, stage2 will start ECC write/read operation
// if ECC write, then we are writing ECC for previous address