massive overhaul of fpga code
[fleet.git] / src / edu / berkeley / fleet / fpga / mem / ddr_ctrl.v
1 //----------------------------------------------------------------------------
2 // Pipelined, asyncronous DDR Controller
3 //
4 // (c) Joerg Bornschein (<jb@capsec.org>)
5 //----------------------------------------------------------------------------
6 module ddr_ctrl 
7 #(
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
13 ) (
14         input                   clk, 
15         input                   reset,
16         //  DDR ports
17         output                  ddr_clk,
18         output                  ddr_clk_n,
19         input                   ddr_clk_fb,
20         output                  ddr_ras_n,
21         output                  ddr_cas_n,
22         output                  ddr_we_n,
23         output                  ddr_cke,
24         output                  ddr_cs_n,
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)
31         input                   fml_wr,
32         input                   fml_rd,
33         output reg              fml_done,
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
40 );
41
42 wire [ `DQ_RNG]       ddr_dq_i,  ddr_dq_o;
43 wire [`DQS_RNG]       ddr_dqs_i, ddr_dqs_o;
44 wire                  ddr_dqs_oe;
45
46 //----------------------------------------------------------------------------
47 // clock generator
48 //----------------------------------------------------------------------------
49 wire clk_locked;
50 wire write_clk, write_clk90;
51 wire read_clk;
52
53 wire reset_int = reset | ~clk_locked;
54
55 ddr_clkgen #(
56         .phase_shift(  phase_shift  ),
57         .clk_multiply( clk_multiply ),
58         .clk_divide(   clk_divide   )
59 ) clkgen (
60         .clk(             clk            ),
61         .reset(           reset          ),
62         .locked(          clk_locked     ),
63         // ddr-clk 
64         .read_clk(        read_clk       ),
65         .write_clk(       write_clk      ),
66         .write_clk90(     write_clk90    ),
67         // phase shift control
68         .rot(             rot            )      // XXX
69 );
70
71 //----------------------------------------------------------------------------
72 // async_fifos (cmd, wdata, rdata)
73 //----------------------------------------------------------------------------
74 wire                  cba_fifo_full;
75 reg  [`CBA_RNG]       cba_fifo_din;
76 reg                   cba_fifo_we;
77
78 wire                  wfifo_full;
79 reg   [`WFIFO_RNG]    wfifo_din;
80 reg                   wfifo_we;
81
82
83 wire [`RFIFO_RNG]     rfifo_dout;
84 wire                  rfifo_empty;
85 wire                  rfifo_next;
86
87 //----------------------------------------------------------------------------
88 // High-speed cmd, write and read datapath
89 //----------------------------------------------------------------------------
90 ddr_wpath wpath0 (
91         .clk(         write_clk    ),
92         .clk90(       write_clk90  ),
93         .reset(       reset_int    ),
94         // CBA async fifo
95         .cba_clk(     clk           ),
96         .cba_din(     cba_fifo_din  ),
97         .cba_wr(      cba_fifo_we   ),
98         .cba_full(    cba_fifo_full ),
99         // WDATA async fifo
100         .wdata_clk(   clk           ),
101         .wdata_din(   wfifo_din     ),
102         .wdata_wr(    wfifo_we      ),
103         .wdata_full(  wfifo_full    ),
104         //
105         .sample(     sample      ), 
106         // DDR
107         .ddr_clk(     ddr_clk    ),
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   ),
112         .ddr_a(       ddr_a      ),
113         .ddr_ba(      ddr_ba     ),
114         .ddr_dm(      ddr_dm     ),
115         .ddr_dq(      ddr_dq_o   ),
116         .ddr_dqs(     ddr_dqs_o  ),
117         .ddr_dqs_oe(  ddr_dqs_oe )
118 );
119
120 ddr_rpath rpath0 (
121         .clk(         read_clk   ),
122         .reset(       reset_int  ),
123         // 
124         .sample(      sample     ),
125         //
126         .rfifo_clk(   clk        ),
127         .rfifo_empty( rfifo_empty),
128         .rfifo_dout(  rfifo_dout ),
129         .rfifo_next(  rfifo_next ),
130         // DDR
131         .ddr_dq(      ddr_dq_i   ),
132         .ddr_dqs(     ddr_dqs_i  )
133 );
134
135 //----------------------------------------------------------------------------
136 // 7.8 us pulse generator
137 //----------------------------------------------------------------------------
138 wire pulse78;
139 reg  ar_req;
140 reg  ar_done;
141
142 ddr_pulse78 #(
143         .clk_freq( clk_freq )
144 ) pulse78_gen (
145         .clk(      clk        ),
146         .reset(    reset_int  ),
147         .pulse78(  pulse78    )
148 );
149
150 //----------------------------------------------------------------------------
151 // Auto Refresh request generator
152 //----------------------------------------------------------------------------
153 always @(posedge clk)
154         if (reset_int)
155                 ar_req <= 0;
156         else
157                 ar_req <= pulse78 | (ar_req & ~ar_done);
158
159 // operations we might want to submit
160 wire [`CBA_RNG] ar_pre_cba;
161 wire [`CBA_RNG] ar_ar_cba;
162
163 assign ar_pre_cba   = { `DDR_CMD_PRE, 2'b00, 13'b1111111111111 };
164 assign ar_ar_cba    = { `DDR_CMD_AR,  2'b00, 13'b0000000000000 };
165
166 //----------------------------------------------------------------------------
167 // Init & management
168 //----------------------------------------------------------------------------
169 wire                 init_req;
170 reg                  init_ack;
171 wire [`CBA_RNG]      init_cba;
172 wire                 init_done;
173 wire                 wait200;
174
175 ddr_init #(
176         .wait200_init( wait200_init )
177 ) init (
178         .clk(         clk         ),
179         .reset(       reset_int   ),
180         .pulse78(     pulse78     ),
181         .wait200(     wait200     ),
182         .init_done(   init_done   ),
183         //
184         .mngt_req(    init_req    ),
185         .mngt_ack(    init_ack    ),
186         .mngt_cba(    init_cba    )
187 );
188
189 //----------------------------------------------------------------------------
190 // Active Bank Information 
191 //----------------------------------------------------------------------------
192 reg [`ROW_RNG] ba_row [3:0];
193 reg [3:0]      ba_active;
194
195 //----------------------------------------------------------------------------
196 // Handle write FIFO
197 //----------------------------------------------------------------------------
198 wire wfifo_proc_reset;
199 wire wfifo_proc_start;
200 reg  wfifo_proc_done;
201
202 parameter w_idle   = 0;
203 parameter w_1      = 1;
204 parameter w_2      = 2;
205 parameter w_3      = 3;
206 parameter w_finish = 4;
207
208 reg [2:0] wstate;
209
210 always @(posedge clk)
211 begin
212         if (reset_int) begin
213                 wstate          <= w_idle;
214                 wfifo_proc_done <= 0;
215         end else begin
216                 wfifo_we <= 0;
217
218                 case (wstate)
219                         w_idle: begin
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];
225                                         wfifo_we                 <= 1;
226                                         wstate                   <= w_1;
227                                 end
228                         end
229                         w_1: begin
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];
235                                         wfifo_we                 <= 1;
236                                         wstate                   <= w_2;
237                                 end
238                         end
239                         w_2: begin
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];
245                                         wfifo_we                 <= 1;
246                                         wstate                   <= w_3;
247                                 end
248                         end
249                         w_3: begin
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];
255                                         wfifo_we                 <= 1;
256                                         wstate                   <= w_finish;
257                                         wfifo_proc_done          <= 1;
258                                 end
259                         end
260                         w_finish: begin
261                                 if (wfifo_proc_reset) begin
262                                         wstate          <= w_idle;
263                                         wfifo_proc_done <= 0;
264                                 end
265                         end
266                 endcase
267         end
268 end
269
270 //----------------------------------------------------------------------------
271 // Handle read FIFO
272 //----------------------------------------------------------------------------
273 wire rfifo_proc_reset;
274 wire rfifo_proc_start;
275 reg  rfifo_proc_done ;
276
277 parameter r_idle   = 0;
278 parameter r_1      = 1;
279 parameter r_2      = 2;
280 parameter r_3      = 3;
281 parameter r_finish = 4;
282
283 reg [2:0] rstate;
284
285 assign rfifo_next = ~rfifo_empty;
286
287 always @(posedge clk)
288 begin
289         if (reset_int) begin
290                 rstate          <= r_idle;
291                 rfifo_proc_done <= 0;
292         end else begin
293                 case (rstate)
294                         r_idle: begin
295                                 if (rfifo_proc_start & ~rfifo_empty) begin
296                                         fml_dout[31:0]   <= rfifo_dout;
297                                         rstate           <= r_1;
298                                 end
299                         end
300                         r_1: begin
301                                 if (~rfifo_empty) begin
302                                         fml_dout[63:32]  <= rfifo_dout;
303                                         rstate           <= r_2;
304                                 end
305                         end
306                         r_2: begin
307                                 if (~rfifo_empty) begin
308                                         fml_dout[95:64]  <= rfifo_dout;
309                                         rstate           <= r_3;
310                                 end
311                         end
312                         r_3: begin
313                                 if (~rfifo_empty) begin
314                                         fml_dout[127:96] <= rfifo_dout;
315                                         rstate           <= r_finish;
316                                         rfifo_proc_done  <= 1;
317                                 end
318                         end
319                         r_finish: begin
320                                 if (rfifo_proc_reset) begin
321                                         rfifo_proc_done  <= 0;
322                                         rstate           <= r_idle;
323                                 end
324                         end
325                 endcase
326         end
327 end
328
329 //----------------------------------------------------------------------------
330 // FML decoding
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];
335
336 wire [`FML_ADR_ROW_RNG]   fml_cur_row;   // current active row in sel. bank
337 assign fml_cur_row    = ba_row[fml_ba];
338
339 wire   fml_row_active;  // is row in selected ba really active?
340 assign fml_row_active = ba_active[fml_ba]; 
341
342
343 /*
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 :
347                                         ba3_active ;
348 */
349
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;
357
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;
363
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} };
368
369 //----------------------------------------------------------------------------
370 // Schedule and issue commands
371 //----------------------------------------------------------------------------
372
373 parameter s_init      = 0;
374 parameter s_idle      = 1;
375 parameter s_ar        = 2;
376 parameter s_reading   = 3;
377
378 reg [1:0] state;
379
380 always @(posedge clk)
381 begin
382         if (reset_int) begin
383                 state        <= s_init;
384                 ba_active    <= 0;
385                 ba_row[0]    <= 0;
386                 ba_row[1]    <= 0;
387                 ba_row[2]    <= 0;
388                 ba_row[3]    <= 0;
389
390                 fml_done     <= 0;
391                 init_ack     <= 0;
392                 cba_fifo_we  <= 0;
393                 ar_done      <= 0;
394         end else begin
395                 fml_done     <= 0;
396                 init_ack     <= 0;
397                 cba_fifo_we  <= 0;
398                 ar_done      <= 0;
399
400                 case (state)
401                         s_init: begin
402                                 if (init_done)
403                                         state <= s_idle;
404
405                                 if (init_req & ~cba_fifo_full) begin
406                                         cba_fifo_we       <= 1;
407                                         cba_fifo_din      <= init_cba;
408                                         init_ack          <= 1;
409                                 end
410                         end
411                         s_idle: begin
412                                 if (fml_read_req & ~cba_fifo_full) begin
413                                         cba_fifo_we       <= 1;
414                                         cba_fifo_din      <= fml_read_cba;
415                                         state             <= s_reading;
416                                 end else if (fml_write_req & ~cba_fifo_full & wfifo_proc_done) begin
417                                         cba_fifo_we       <= 1;
418                                         cba_fifo_din      <= fml_write_cba;
419                                         fml_done          <= 1;
420                                 end else if (ar_req & ~cba_fifo_full) begin
421                                         cba_fifo_we       <= 1;
422                                         cba_fifo_din      <= ar_pre_cba;
423                                         ar_done           <= 1;
424                                         ba_active         <= 'b0;
425                                         state             <= s_ar;
426                                 end else if (fml_pre_req & ~cba_fifo_full) begin
427                                         cba_fifo_we       <= 1;
428                                         cba_fifo_din      <= fml_pre_cba;
429                                         ba_active[fml_ba] <= 0;
430                                 end else if (fml_act_req & ~cba_fifo_full) begin
431                                         cba_fifo_we       <= 1;
432                                         cba_fifo_din      <= fml_act_cba;
433                                         ba_active[fml_ba] <= 1;
434                                         ba_row[fml_ba]    <= fml_row;
435                                 end
436                         end
437                         s_ar: begin
438                                 if (~cba_fifo_full) begin
439                                         cba_fifo_we       <= 1;
440                                         cba_fifo_din      <= ar_ar_cba;
441                                         state             <= s_idle;
442                                 end
443                         end
444                         s_reading: begin
445                                 if (rfifo_proc_done) begin
446                                         fml_done          <= 1;
447                                         state             <= s_idle;
448                                 end
449                         end
450                 endcase
451         end
452 end
453
454 // start and stop rfifo engine
455 assign rfifo_proc_start = fml_read_req;
456 assign rfifo_proc_reset = fml_done;
457
458 // start and stop wfifo engine
459 assign wfifo_proc_start = fml_wr;
460 assign wfifo_proc_reset = fml_done;
461
462 //----------------------------------------------------------------------------
463 // Demux dqs and dq
464 //----------------------------------------------------------------------------
465 assign ddr_cke   = ~wait200;     // bring up CKE as soon 200us wait is finished
466
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;
469
470 assign ddr_dqs_i = ddr_dqs;
471 assign ddr_dq_i  = ddr_dq;
472
473 assign ddr_cs_n = 0;
474
475 endmodule
476
477 // vim: set ts=4