1 //----------------------------------------------------------------------------
2 // Pipelined, asyncronous DDR Controller
4 // (c) Joerg Bornschein (<jb@capsec.org>)
5 //----------------------------------------------------------------------------
8 parameter clk_freq = 50000000,
9 parameter clk_multiply = 12,
10 parameter clk_divide = 5,
11 parameter phase_shift = 0,
12 parameter wait200_init = 26
25 output [ `A_RNG] ddr_a,
26 output [ `BA_RNG] ddr_ba,
27 inout [ `DQ_RNG] ddr_dq,
28 inout [`DQS_RNG] ddr_dqs,
29 output [ `DM_RNG] ddr_dm,
30 // FML (FastMemoryLink)
34 input [`FML_ADR_RNG] fml_adr,
35 input [`FML_DAT_RNG] fml_din,
36 input [`FML_MSK_RNG] fml_msk,
37 output reg [`FML_DAT_RNG] fml_dout,
38 // Temporary DCM control input
39 input [2:0] rot // XXX
42 wire [ `DQ_RNG] ddr_dq_i, ddr_dq_o;
43 wire [`DQS_RNG] ddr_dqs_i, ddr_dqs_o;
46 //----------------------------------------------------------------------------
48 //----------------------------------------------------------------------------
50 wire write_clk, write_clk90;
53 wire reset_int = reset | ~clk_locked;
56 .phase_shift( phase_shift ),
57 .clk_multiply( clk_multiply ),
58 .clk_divide( clk_divide )
62 .locked( clk_locked ),
64 .read_clk( read_clk ),
65 .write_clk( write_clk ),
66 .write_clk90( write_clk90 ),
67 // phase shift control
71 //----------------------------------------------------------------------------
72 // async_fifos (cmd, wdata, rdata)
73 //----------------------------------------------------------------------------
75 reg [`CBA_RNG] cba_fifo_din;
79 reg [`WFIFO_RNG] wfifo_din;
83 wire [`RFIFO_RNG] rfifo_dout;
87 //----------------------------------------------------------------------------
88 // High-speed cmd, write and read datapath
89 //----------------------------------------------------------------------------
92 .clk90( write_clk90 ),
96 .cba_din( cba_fifo_din ),
97 .cba_wr( cba_fifo_we ),
98 .cba_full( cba_fifo_full ),
101 .wdata_din( wfifo_din ),
102 .wdata_wr( wfifo_we ),
103 .wdata_full( wfifo_full ),
108 .ddr_clk_n( ddr_clk_n ),
109 .ddr_ras_n( ddr_ras_n ),
110 .ddr_cas_n( ddr_cas_n ),
111 .ddr_we_n( ddr_we_n ),
116 .ddr_dqs( ddr_dqs_o ),
117 .ddr_dqs_oe( ddr_dqs_oe )
127 .rfifo_empty( rfifo_empty),
128 .rfifo_dout( rfifo_dout ),
129 .rfifo_next( rfifo_next ),
132 .ddr_dqs( ddr_dqs_i )
135 //----------------------------------------------------------------------------
136 // 7.8 us pulse generator
137 //----------------------------------------------------------------------------
143 .clk_freq( clk_freq )
150 //----------------------------------------------------------------------------
151 // Auto Refresh request generator
152 //----------------------------------------------------------------------------
153 always @(posedge clk)
157 ar_req <= pulse78 | (ar_req & ~ar_done);
159 // operations we might want to submit
160 wire [`CBA_RNG] ar_pre_cba;
161 wire [`CBA_RNG] ar_ar_cba;
163 assign ar_pre_cba = { `DDR_CMD_PRE, 2'b00, 13'b1111111111111 };
164 assign ar_ar_cba = { `DDR_CMD_AR, 2'b00, 13'b0000000000000 };
166 //----------------------------------------------------------------------------
168 //----------------------------------------------------------------------------
171 wire [`CBA_RNG] init_cba;
176 .wait200_init( wait200_init )
182 .init_done( init_done ),
184 .mngt_req( init_req ),
185 .mngt_ack( init_ack ),
186 .mngt_cba( init_cba )
189 //----------------------------------------------------------------------------
190 // Active Bank Information
191 //----------------------------------------------------------------------------
192 reg [`ROW_RNG] ba_row [3:0];
195 //----------------------------------------------------------------------------
197 //----------------------------------------------------------------------------
198 wire wfifo_proc_reset;
199 wire wfifo_proc_start;
202 parameter w_idle = 0;
206 parameter w_finish = 4;
210 always @(posedge clk)
214 wfifo_proc_done <= 0;
220 if (wfifo_proc_start & ~wfifo_full) begin
221 wfifo_din[`WFIFO_D0_RNG] <= fml_din[15: 0];
222 wfifo_din[`WFIFO_D1_RNG] <= fml_din[31:16];
223 wfifo_din[`WFIFO_M0_RNG] <= fml_msk[ 1: 0];
224 wfifo_din[`WFIFO_M1_RNG] <= fml_msk[ 3: 2];
230 if (~wfifo_full) begin
231 wfifo_din[`WFIFO_D0_RNG] <= fml_din[47:32];
232 wfifo_din[`WFIFO_D1_RNG] <= fml_din[63:48];
233 wfifo_din[`WFIFO_M0_RNG] <= fml_msk[ 5: 4];
234 wfifo_din[`WFIFO_M1_RNG] <= fml_msk[ 7: 6];
240 if (~wfifo_full) begin
241 wfifo_din[`WFIFO_D0_RNG] <= fml_din[79:64];
242 wfifo_din[`WFIFO_D1_RNG] <= fml_din[95:80];
243 wfifo_din[`WFIFO_M0_RNG] <= fml_msk[ 9: 8];
244 wfifo_din[`WFIFO_M1_RNG] <= fml_msk[11:10];
250 if (~wfifo_full) begin
251 wfifo_din[`WFIFO_D0_RNG] <= fml_din[111: 96];
252 wfifo_din[`WFIFO_D1_RNG] <= fml_din[127:112];
253 wfifo_din[`WFIFO_M0_RNG] <= fml_msk[12:12];
254 wfifo_din[`WFIFO_M1_RNG] <= fml_msk[15:14];
257 wfifo_proc_done <= 1;
261 if (wfifo_proc_reset) begin
263 wfifo_proc_done <= 0;
270 //----------------------------------------------------------------------------
272 //----------------------------------------------------------------------------
273 wire rfifo_proc_reset;
274 wire rfifo_proc_start;
275 reg rfifo_proc_done ;
277 parameter r_idle = 0;
281 parameter r_finish = 4;
285 assign rfifo_next = ~rfifo_empty;
287 always @(posedge clk)
291 rfifo_proc_done <= 0;
295 if (rfifo_proc_start & ~rfifo_empty) begin
296 fml_dout[31:0] <= rfifo_dout;
301 if (~rfifo_empty) begin
302 fml_dout[63:32] <= rfifo_dout;
307 if (~rfifo_empty) begin
308 fml_dout[95:64] <= rfifo_dout;
313 if (~rfifo_empty) begin
314 fml_dout[127:96] <= rfifo_dout;
316 rfifo_proc_done <= 1;
320 if (rfifo_proc_reset) begin
321 rfifo_proc_done <= 0;
329 //----------------------------------------------------------------------------
331 //----------------------------------------------------------------------------
332 wire [`FML_ADR_BA_RNG] fml_ba = fml_adr[`FML_ADR_BA_RNG];
333 wire [`FML_ADR_ROW_RNG] fml_row = fml_adr[`FML_ADR_ROW_RNG];
334 wire [`FML_ADR_COL_RNG] fml_col = fml_adr[`FML_ADR_COL_RNG];
336 wire [`FML_ADR_ROW_RNG] fml_cur_row; // current active row in sel. bank
337 assign fml_cur_row = ba_row[fml_ba];
339 wire fml_row_active; // is row in selected ba really active?
340 assign fml_row_active = ba_active[fml_ba];
344 wire fml_row_active = (fml_ba == 0) ? ba0_active : // is row in selected
345 (fml_ba == 1) ? ba1_active : // bank really active?
346 (fml_ba == 2) ? ba2_active :
350 // request operation iff correct bank is active
351 wire fml_req = fml_rd | fml_wr;
352 wire fml_row_match = (fml_row == fml_cur_row) & fml_row_active;
353 wire fml_pre_req = fml_req & ~fml_row_match & fml_row_active;
354 wire fml_act_req = fml_req & ~fml_row_active;
355 wire fml_read_req = fml_rd & fml_row_match & ~fml_done;
356 wire fml_write_req = fml_wr & fml_row_match & ~fml_done;
358 // actual operations we might want to submit
359 wire [`CBA_RNG] fml_pre_cba;
360 wire [`CBA_RNG] fml_act_cba;
361 wire [`CBA_RNG] fml_read_cba;
362 wire [`CBA_RNG] fml_write_cba;
364 assign fml_pre_cba = { `DDR_CMD_PRE, fml_ba, 13'b0 };
365 assign fml_act_cba = { `DDR_CMD_ACT, fml_ba, fml_row };
366 assign fml_read_cba = { `DDR_CMD_READ, fml_ba, {3'b000}, fml_col, {3'b000} };
367 assign fml_write_cba = { `DDR_CMD_WRITE, fml_ba, {3'b000}, fml_col, {3'b000} };
369 //----------------------------------------------------------------------------
370 // Schedule and issue commands
371 //----------------------------------------------------------------------------
373 parameter s_init = 0;
374 parameter s_idle = 1;
376 parameter s_reading = 3;
380 always @(posedge clk)
405 if (init_req & ~cba_fifo_full) begin
407 cba_fifo_din <= init_cba;
412 if (fml_read_req & ~cba_fifo_full) begin
414 cba_fifo_din <= fml_read_cba;
416 end else if (fml_write_req & ~cba_fifo_full & wfifo_proc_done) begin
418 cba_fifo_din <= fml_write_cba;
420 end else if (ar_req & ~cba_fifo_full) begin
422 cba_fifo_din <= ar_pre_cba;
426 end else if (fml_pre_req & ~cba_fifo_full) begin
428 cba_fifo_din <= fml_pre_cba;
429 ba_active[fml_ba] <= 0;
430 end else if (fml_act_req & ~cba_fifo_full) begin
432 cba_fifo_din <= fml_act_cba;
433 ba_active[fml_ba] <= 1;
434 ba_row[fml_ba] <= fml_row;
438 if (~cba_fifo_full) begin
440 cba_fifo_din <= ar_ar_cba;
445 if (rfifo_proc_done) begin
454 // start and stop rfifo engine
455 assign rfifo_proc_start = fml_read_req;
456 assign rfifo_proc_reset = fml_done;
458 // start and stop wfifo engine
459 assign wfifo_proc_start = fml_wr;
460 assign wfifo_proc_reset = fml_done;
462 //----------------------------------------------------------------------------
464 //----------------------------------------------------------------------------
465 assign ddr_cke = ~wait200; // bring up CKE as soon 200us wait is finished
467 assign ddr_dqs = ddr_dqs_oe!=1'b0 ? ddr_dqs_o : 'bz;
468 assign ddr_dq = ddr_dqs_oe!=1'b0 ? ddr_dq_o : 'bz;
470 assign ddr_dqs_i = ddr_dqs;
471 assign ddr_dq_i = ddr_dq;