-
Notifications
You must be signed in to change notification settings - Fork 1
/
ram_controller_X7.sv
385 lines (352 loc) · 10.9 KB
/
ram_controller_X7.sv
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
`timescale 1ns / 1ps
`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Nicholas Nusgart
//
// Create Date: 07/21/2019 02:53:29 PM
// Design Name: LM-3 CADR implementation
// Module Name: ram_controller_X7
// Project Name: LM-3
// Target Devices: Artix 7 XC7A35t
// Tool Versions: Vivado 2018.3, MIG v4.2
// Description:
// Controls memory interfaces for Xilinx 7-series FPGAs. In particular, this
// acts as the CPU-DDR3 SDRAM interface and as the VRAM interface. This will
// work with any 7-series FPGA using a MIG DDR3 controller IP in UI mode.
//
// Dependencies:
// dram_memif, ise_VRAM
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module ram_controller_X7(
/// DDR3 interface
// data interface
inout wire [15:0] ddr3_dq,
inout wire [1:0] ddr3_dqs_p,
inout wire [1:0] ddr3_dqs_n,
inout wire [13:0] ddr3_addr,
output wire [1:0] ddr3_dm,
output wire ddr3_odt,
// command interface
output wire [2:0] ddr3_ba,
output wire ddr3_cs_n,
output wire ddr3_cas_n,
output wire ddr3_ras_n,
output wire ddr3_we_n,
output wire ddr3_reset_n,
// clock
output wire ddr3_ck_p,
output wire ddr3_ck_n,
output wire ddr3_cke,
/// CPU Interface
input wire sdram_clk,
input wire ref_clk,
input wire vga_clk,
input wire cpu_clk,
input wire fetch,
input wire machrun,
input wire prefetch,
input wire reset,
// SDRAM
input wire [21:0] sdram_addr,
input wire [31:0] sdram_data_in,
output reg [31:0] sdram_data_out,
output wire sdram_done,
output wire sdram_ready,
input wire sdram_req,
input wire sdram_write,
input wire sdram_reset,
output wire sdram_calib_done,
output wire sdram_clk_out,
// VGA
input wire [14:0] vram_cpu_addr,
input wire [14:0] vram_vga_addr,
output wire [31:0] vram_cpu_data_out,
output wire [31:0] vram_vga_data_out,
input wire [31:0] vram_cpu_data_in,
input wire vram_cpu_req,
input wire vram_cpu_write,
input wire vram_vga_req,
output wire vram_cpu_done,
output wire vram_cpu_ready,
output wire vram_vga_ready,
// microcode
// microcode interface
input wire [13:0] mcr_addr,
input wire [48:0] mcr_data_in,
output wire [48:0] mcr_data_out,
input wire mcr_write,
output wire mcr_done,
output wire mcr_ready
);
/*
input wire sdram_req;
input wire sdram_write;
input wire dram_clk;
input wire ref_clk;*/
/// VRAM
assign vram_cpu_ready = 1'b1;
assign vram_vga_ready = 1'b1;
assign vram_cpu_done = 1'b1;
wire ena_a = vram_cpu_req | vram_cpu_write;
wire ena_b = vram_vga_req | 1'b0;
ise_vram inst (
.clka(cpu_clk),
.ena(ena_a),
.wea(vram_cpu_write),
.addra(vram_cpu_addr),
.dina(vram_cpu_data_in),
.douta(vram_cpu_data_out),
.clkb(vga_clk),
.enb(ena_b),
.web(1'b0),
.addrb(vram_vga_addr),
.dinb(32'b0),
.doutb(vram_vga_data_out)
);
/// microcode not implemented
assign mcr_data_out = 0;
assign mcr_ready = 0;
assign mcr_done = 0;
/// sdram: the main portion
// ddr interface
wire ui_clk;
wire ui_clk_sync_rst;
// reset logic
reg rs0;
reg [15:0] reset_ctr;
always @(posedge sdram_clk) begin
if (sdram_reset) begin
rs0 <= 1'b1;
end else if (rs0) begin
rs0 <= 1'b0;
`ifndef SIMULATION
reset_ctr <= 16'd65535;
`else
reset_ctr <= 16'd100;
`endif
end else if (reset_ctr != 16'b0) begin
reset_ctr <= reset_ctr - 1;
end
end
wire sys_rst = (reset_ctr == 0);
// wires
wire init_calib_complete;
assign sdram_calib_done = init_calib_complete;
reg [27:0] app_addr;
reg [2:0] app_cmd;
reg app_en;
wire app_rdy;
wire app_wdf_rdy;
reg [127:0] app_wdf_data;
reg app_wdf_wren;
wire app_wdf_end = 1;
wire [127:0] app_rd_data;
wire app_rd_data_end;
wire app_rd_data_valid;
wire app_sr_req = 0;
wire app_sr_active;
wire app_zq_req = 0;
wire app_zq_ack;
wire app_ref_req = 0;
wire app_ref_ack;
// SDRAM controller states
localparam INIT = 3'd0;
localparam IDLE = 3'd1;
localparam WRITE = 3'd2;
localparam WRITE_SEND = 3'd3;
localparam WRITE_DONE = 3'd4;
localparam READ = 3'd5;
localparam READ_DONE = 3'd6;
localparam WAIT = 3'd7;
// Interface Commmands
localparam CMD_WRITE = 3'b000;
localparam CMD_READ = 3'b001;
reg [2:0] state;
// cpu interface
reg [31:0] cpu_data_in;
reg [31:0] cpu_data_out;
reg [21:0] cpu_addr;
reg [27:0] local_addr;
reg [31:0] local_data_in;
reg [31:0] local_data_out;
reg local_req;
reg local_write;
reg local_done;
reg dram_write_done;
reg dram_read_done;
//assign sdram_ready = (state == IDLE);
assign sdram_clk_out = ui_clk;
reg cpu_req;
reg cpu_write;
reg cpu_done;
assign sdram_done = cpu_done;
assign sdram_ready = dram_read_done;
`ifdef SEP_CLOCKS
// metastability avoidance
// Needs work
always @ (posedge ui_clk) begin
cpu_req <= sdram_req;
local_req <= cpu_req;
//
cpu_write <= sdram_write;
local_write <= cpu_write;
// addr
cpu_addr <= sdram_addr;
local_addr <= {5'b0, cpu_addr, 1'b0};
// data in
cpu_data_in <= sdram_data_in;
local_data_in <= cpu_data_in;
// data out
cpu_data_out <= local_data_out;
sdram_data_out <= cpu_data_out;
// dram done
local_done <= dram_done;
cpu_done <= local_done;
end
`else
always @(*) begin
local_req = sdram_req;
local_write = sdram_write;
local_addr = {2'b0, sdram_addr, 3'b0};
local_data_in = sdram_data_in;
sdram_data_out = local_data_out;
cpu_done = dram_write_done;
end
`endif
always @ (posedge ui_clk) begin
if (ui_clk_sync_rst) begin
state <= INIT;
app_en <= 0;
app_wdf_wren <= 0;
dram_write_done <= 0;
dram_read_done <= 0;
end else begin
case (state)
INIT: begin
if (init_calib_complete) begin
state <= IDLE;
end
end
IDLE: begin
// todo controller logic
dram_write_done <= 0;
dram_read_done <= 0;
if (local_req) begin
state <= READ;
end else if (local_write) begin
state <= WRITE;
end
end
WRITE: begin
/*app_wdf_wren <= 1;
app_addr <= local_addr;
app_cmd <= CMD_WRITE;
app_wdf_data[31:0] <= local_data_in[31:0];
if (app_wdf_rdy) begin
state <= WRITE_SEND;
end*/
if (app_rdy & app_wdf_rdy) begin
app_en <= 1;
app_wdf_wren <= 1;
app_addr <= local_addr;
app_cmd <= CMD_WRITE;
app_wdf_data[31:0] <= local_data_in[31:0];
state <= WRITE_DONE;
end
end
WRITE_DONE: begin
if (app_rdy & app_en) begin
app_en <= 0;
end
if (app_wdf_rdy & app_wdf_wren) begin
app_wdf_wren <= 0;
end
if (~app_en & ~app_wdf_wren) begin
state <= WAIT;
dram_write_done <= 1;
end
end
READ: begin
if (app_rdy) begin
app_en <= 1;
app_addr <= local_addr;
app_cmd <= CMD_READ;
state <= READ_DONE;
end
end
READ_DONE: begin
// prevent double-reading RAM side
if (app_rdy & app_en) begin
app_en <= 0;
end
// read out data
if (app_rd_data_valid) begin
local_data_out <= app_rd_data[31:0];
state <= WAIT;
dram_read_done <= 1;
end
end
WAIT: begin
// prevent double-opearation CPU side
if (~local_req && ~local_write) begin
state <= IDLE;
end
end
// invalid state --> go to idle state
default: state <= IDLE;
endcase
end
end
dram_memif u_dram_memif (
// Memory interface ports
.ddr3_addr (ddr3_addr), // output [13:0] ddr3_addr
.ddr3_ba (ddr3_ba), // output [2:0] ddr3_ba
.ddr3_cas_n (ddr3_cas_n), // output ddr3_cas_n
.ddr3_ck_n (ddr3_ck_n), // output [0:0] ddr3_ck_n
.ddr3_ck_p (ddr3_ck_p), // output [0:0] ddr3_ck_p
.ddr3_cke (ddr3_cke), // output [0:0] ddr3_cke
.ddr3_ras_n (ddr3_ras_n), // output ddr3_ras_n
.ddr3_reset_n (ddr3_reset_n), // output ddr3_reset_n
.ddr3_we_n (ddr3_we_n), // output ddr3_we_n
.ddr3_dq (ddr3_dq), // inout [15:0] ddr3_dq
.ddr3_dqs_n (ddr3_dqs_n), // inout [1:0] ddr3_dqs_n
.ddr3_dqs_p (ddr3_dqs_p), // inout [1:0] ddr3_dqs_p
.init_calib_complete (init_calib_complete), // output init_calib_complete
.ddr3_cs_n (ddr3_cs_n), // output [0:0] ddr3_cs_n
.ddr3_dm (ddr3_dm), // output [1:0] ddr3_dm
.ddr3_odt (ddr3_odt), // output [0:0] ddr3_odt
// Application interface ports
.app_addr (app_addr), // input [27:0] app_addr
.app_cmd (app_cmd), // input [2:0] app_cmd
.app_en (app_en), // input app_en
.app_wdf_data (app_wdf_data), // input [127:0] app_wdf_data
.app_wdf_end (app_wdf_end), // input app_wdf_end
.app_wdf_wren (app_wdf_wren), // input app_wdf_wren
.app_rd_data (app_rd_data), // output [127:0] app_rd_data
.app_rd_data_end (app_rd_data_end), // output app_rd_data_end
.app_rd_data_valid (app_rd_data_valid), // output app_rd_data_valid
.app_rdy (app_rdy), // output app_rdy
.app_wdf_rdy (app_wdf_rdy), // output app_wdf_rdy
.app_sr_req (app_sr_req), // input app_sr_req
.app_ref_req (app_ref_req), // input app_ref_req
.app_zq_req (app_zq_req), // input app_zq_req
.app_sr_active (app_sr_active), // output app_sr_active
.app_ref_ack (app_ref_ack), // output app_ref_ack
.app_zq_ack (app_zq_ack), // output app_zq_ack
.ui_clk (ui_clk), // output ui_clk
.ui_clk_sync_rst (ui_clk_sync_rst), // output ui_clk_sync_rst
//.app_wdf_mask (15'b0000000000001111), // input [15:0] app_wdf_mask
.app_wdf_mask (16'b1111111111110000), // input [15:0] app_wdf_mask
// System Clock Ports
.sys_clk_i (sdram_clk),
// Reference Clock Ports
.clk_ref_i (ref_clk),
.sys_rst (sys_rst) // input sys_rst
);
endmodule
`default_nettype wire