Skip to content

Commit 1af65f0

Browse files
Warning Untested! Use at your own risk!
The external memory for the Nexys Video needs to be implemented. Here is an attempt to do that...
1 parent a42e6ae commit 1af65f0

File tree

1 file changed

+179
-0
lines changed

1 file changed

+179
-0
lines changed

DDR3-21-06-10.v

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
`timescale 1 ns / 1 ps
2+
3+
///////////////////////////////////////////////
4+
// //
5+
// WARNING THIS CODE IS UNTESTED //
6+
// USE AT YOUR OWN RISK //
7+
// //
8+
///////////////////////////////////////////////
9+
10+
///////////////////////////////////////////////
11+
12+
// Demo SDRAM controller for MT48LC1M16A1 legacy SDRAM
13+
// (C) fpga4fun.com & KNJN LLC 2014
14+
15+
// Changes made for MT41K256M16 and the Nexys Video from Digilent Inc.
16+
// by Gregory S. Callen 2021
17+
18+
// The MT48LC1M16A1 is a 16Mb SDRAM arranged in 1M x 16bits (using 2 banks)
19+
// The MT41K256M16 is a 4Gb SDRAM arranged in 256M x 16bits (using 8 banks)
20+
21+
// This controller feature set has been reduced to make it easy to understand
22+
// It is based on a more complete controller targeted for Xylo-EM and Xylo-LM boards
23+
24+
// Assumptions:
25+
// 1. the SDRAM has been initialized with CAS latency=2, and any valid burst mode
26+
// 2. the read agent is active enough to refresh the RAM (if not, add a refresh timer)
27+
28+
// For more info, check
29+
// http://www.fpga4fun.com/SDRAM.html
30+
31+
///////////////////////////////////////////////
32+
33+
module DDR3(
34+
input clk,
35+
36+
// read agent
37+
input RdReq,
38+
output RdGnt,
39+
input [27:0] RdAddr,
40+
output reg [15:0] RdData,
41+
output RdDataValid,
42+
43+
// write agent
44+
input WrReq,
45+
output WrGnt,
46+
input [27:0] WrAddr,
47+
input [15:0] WrData,
48+
49+
// SDRAM
50+
output ddr3_cke, ddr3_we_n, ddr3_cas_n, ddr3_ras_n, ddr3_dq_oe,
51+
output reg [14:0] ddr3_addr,
52+
output reg [2:0] ddr3_ba,
53+
output reg [1:0] ddr3_dm = 2'b11,
54+
inout [15:0] ddr3_dq
55+
);
56+
57+
assign ddr3_cke = 1'b1;
58+
59+
localparam [2:0] SDRAM_CMD_LOADMODE = 3'b000;
60+
localparam [2:0] SDRAM_CMD_REFRESH = 3'b001;
61+
localparam [2:0] SDRAM_CMD_PRECHARGE = 3'b010;
62+
localparam [2:0] SDRAM_CMD_ACTIVE = 3'b011;
63+
localparam [2:0] SDRAM_CMD_WRITE = 3'b100;
64+
localparam [2:0] SDRAM_CMD_READ = 3'b101;
65+
localparam [2:0] SDRAM_CMD_NOP = 3'b111;
66+
67+
reg [2:0] SDRAM_CMD = SDRAM_CMD_NOP;
68+
assign {ddr3_ras_n, ddr3_cas_n, ddr3_we_n} = SDRAM_CMD;
69+
70+
// here we decide which of reads or writes have priority
71+
wire read_now = RdReq; // give priority to read requests
72+
wire write_now = ~RdReq & WrReq; // and if a read is not requested, give writes a chance...
73+
74+
reg [2:0] state=3'h4;
75+
reg ReadSelected=0; always @(posedge clk) if(state==3'h0) ReadSelected <= read_now;
76+
wire WriteSelected = ~ReadSelected;
77+
78+
wire ReadCycle = (state==3'h0) ? read_now : ReadSelected;
79+
wire [27:0] Addr = ReadCycle ? RdAddr : WrAddr;
80+
reg [27:0] AddrR=0; always @(posedge clk) AddrR <= Addr;
81+
82+
wire SameRowAndBank = (Addr[27:10]==AddrR[27:10]);
83+
assign RdGnt = (state==3'h0 & read_now) | (state==3'h1 & ReadSelected & RdReq & SameRowAndBank);
84+
assign WrGnt = (state==3'h0 & write_now) | (state==3'h1 & WriteSelected & WrReq & SameRowAndBank);
85+
86+
reg cke_flag <= 1'b0;
87+
reg rstn_flag <= 1'b0;
88+
reg [31:0] ticks <= 0;
89+
90+
wire ddr3_reset_n = rstn_flag ? 1'b1 : 1'b0;
91+
wire ddr3_cke = cke_flag ? 1'd1 : 1'b0;
92+
wire sys_reset = resetn and mem_ready and clk_locked;
93+
94+
always @(posedge clk) begin
95+
ticks <= ticks + 1;
96+
if ( sys_reset == 0 ) begin
97+
cke_flag <= 1'b0;
98+
rstn_flag <= 1'b0;
99+
ticks <= 0;
100+
state <= 3'h4;
101+
end
102+
case(state)
103+
3'h0: begin
104+
if(RdReq | WrReq) begin // is there a read or write request?
105+
SDRAM_CMD <= SDRAM_CMD_ACTIVE; // if so activate
106+
ddr3_ba <= Addr[27:25]; // this bank
107+
ddr3_addr <= Addr[24:10]; // this row
108+
ddr3_dm <= 2'b11;
109+
state <= 3'h1;
110+
end else begin
111+
SDRAM_CMD <= SDRAM_CMD_NOP; // otherwise stay idle
112+
ddr3_ba <= 0;
113+
ddr3_addr <= 0;
114+
ddr3_dm <= 2'b11;
115+
state <= 3'h0;
116+
end
117+
end
118+
3'h1: begin
119+
SDRAM_CMD <= ReadSelected ? SDRAM_CMD_READ : SDRAM_CMD_WRITE;
120+
ddr3_ba <= AddrR[27:25];
121+
ddr3_addr <= {5'b00000, AddrR[9:0]}; // column
122+
ddr3_addr[10] <= 1'b0; // no auto-precharge
123+
ddr3_dm <= 2'b00;
124+
state <= (ReadSelected ? RdReq : WrReq) & SameRowAndBank ? 3'h1 : 3'h2;
125+
end
126+
3'h2: begin
127+
$time;
128+
$display("precharge\n");
129+
SDRAM_CMD <= SDRAM_CMD_PRECHARGE; // close the row when we're done with it
130+
ddr3_ba <= 0;
131+
ddr3_addr <= 11'b100_0000_0000; // all banks precharge
132+
ddr3_dm <= 2'b11;
133+
ticks <= 0;
134+
state <= 3'h0;
135+
end
136+
3'h3: begin
137+
if ( ticks > 6000000 ) begin // precharge after 60 ms @ 100MHz
138+
state <= 3'h2;
139+
end else begin
140+
SDRAM_CMD <= SDRAM_CMD_NOP;
141+
ddr3_ba <= 0;
142+
ddr3_addr <= 0;
143+
ddr3_dm <= 2'b11;
144+
state <= 3'h0;
145+
end
146+
end
147+
3'h4: begin
148+
if ( ticks > 22000 ) begin // 220 µs @ 100MHz
149+
rstn_flag <= 1'b1;
150+
$time;
151+
$display("rstn ready\n");
152+
end
153+
if ( ticks > 75000 ) begin // 750 µs @ 100MHz
154+
cke_flag <= 1'b1;
155+
$time;
156+
$display("cke ready\n");
157+
end
158+
if ( ticks > 75300 ) begin // 753 µs @ 100MHz
159+
state <= 3'h0;
160+
$time;
161+
$display("all clear\n");
162+
end
163+
end
164+
endcase
165+
end
166+
167+
localparam trl = 4; // total read latency is the SDRAM CAS-latency (two) plus the SDRAM controller induced latency (two)
168+
reg [trl-1:0] RdDataValidPipe;
169+
always @(posedge clk) RdDataValidPipe <= {RdDataValidPipe[trl-2:0], state==2'h1 & ReadSelected};
170+
assign RdDataValid = RdDataValidPipe[trl-1];
171+
always @(posedge clk) RdData <= ddr3_dq;
172+
173+
reg ddr3_dq_oe = 1'b0; always @(posedge clk) ddr3_dq_oe <= (state==2'h1) & WriteSelected;
174+
reg [15:0] WrData1=0; always @(posedge clk) WrData1 <= WrData;
175+
reg [15:0] WrData2=0; always @(posedge clk) WrData2 <= WrData1;
176+
177+
assign ddr3_dq = ddr3_dq_oe ? WrData2 : 16'hZZZZ;
178+
endmodule
179+
///////////////////////////////////////////////

0 commit comments

Comments
 (0)