Root/lm32/logic/sakc/rtl/wb_ddr/ddr_ctrl.v

1//----------------------------------------------------------------------------
2// Pipelined, asyncronous DDR Controller
3//
4// (c) Joerg Bornschein (<jb@capsec.org>)
5//----------------------------------------------------------------------------
6module ddr_ctrl
7#(
8    parameter phase_shift = 0,
9    parameter clk_freq = 100000000,
10    parameter clk_multiply = 12,
11    parameter clk_divide = 5,
12    parameter wait200_init = 26
13) (
14    input clk,
15    input reset,
16    // DDR ports
17    output [2:0] ddr_clk,
18    output [2:0] 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 [1:0] ddr_cke,
24    output [1:0] 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    output reg fml_done,
32    input [`FML_ADR_RNG] fml_adr,
33    input fml_rd,
34    input fml_wr,
35    input [`FML_DAT_RNG] fml_wdat,
36    input [`FML_BE_RNG] fml_wbe,
37    input fml_wnext,
38    output fml_rempty,
39    input fml_rnext,
40    output [`FML_DAT_RNG] fml_rdat,
41    // DCM phase shift control
42    output ps_ready,
43    input ps_up,
44    input ps_down,
45    // Logic Probe
46    output probe_clk,
47    input [7:0] probe_sel,
48    output reg [7:0] probe
49);
50
51wire [ `DQ_RNG] ddr_dq_i, ddr_dq_o;
52wire [`DQS_RNG] ddr_dqs_i, ddr_dqs_o;
53wire ddr_dqs_oe;
54
55//----------------------------------------------------------------------------
56// clock generator
57//----------------------------------------------------------------------------
58wire clk_locked;
59wire write_clk, write_clk90;
60wire read_clk;
61
62wire reset_int = reset | ~clk_locked;
63
64ddr_clkgen #(
65    .phase_shift( phase_shift ),
66    .clk_multiply( clk_multiply ),
67    .clk_divide( clk_divide )
68) clkgen (
69    .clk( clk ),
70    .reset( reset ),
71    .locked( clk_locked ),
72    // ddr-clk
73    .read_clk( read_clk ),
74    .write_clk( write_clk ),
75    .write_clk90( write_clk90 ),
76    // phase shift control
77    .ps_ready( ps_ready ),
78    .ps_up( ps_up ),
79    .ps_down( ps_down )
80);
81
82//----------------------------------------------------------------------------
83// async_fifos (cmd, wdata, rdata)
84//----------------------------------------------------------------------------
85wire cba_fifo_full;
86reg [`CBA_RNG] cba_fifo_din;
87reg cba_fifo_we;
88
89wire wfifo_full;
90wire [`WFIFO_RNG] wfifo_din;
91wire wfifo_we;
92
93wire [`RFIFO_RNG] rfifo_dout;
94wire rfifo_empty;
95wire rfifo_next;
96
97assign wfifo_din = { ~fml_wbe, fml_wdat };
98assign wfifo_we = fml_wnext;
99
100assign fml_rdat = rfifo_dout;
101assign fml_rempty = rfifo_empty;
102assign rfifo_next = fml_rnext;
103
104//----------------------------------------------------------------------------
105// High-speed cmd, write and read datapath
106//----------------------------------------------------------------------------
107ddr_wpath wpath0 (
108    .clk( write_clk ),
109    .clk90( write_clk90 ),
110    .reset( reset_int ),
111    // CBA async fifo
112    .cba_clk( clk ),
113    .cba_din( cba_fifo_din ),
114    .cba_wr( cba_fifo_we ),
115    .cba_full( cba_fifo_full ),
116    // WDATA async fifo
117    .wdata_clk( clk ),
118    .wdata_din( wfifo_din ),
119    .wdata_wr( wfifo_we ),
120    .wdata_full( wfifo_full ),
121    //
122    .sample( sample ),
123    // DDR
124    .ddr_clk( ddr_clk ),
125    .ddr_clk_n( ddr_clk_n ),
126    .ddr_ras_n( ddr_ras_n ),
127    .ddr_cas_n( ddr_cas_n ),
128    .ddr_we_n( ddr_we_n ),
129    .ddr_a( ddr_a ),
130    .ddr_ba( ddr_ba ),
131    .ddr_dm( ddr_dm ),
132    .ddr_dq( ddr_dq_o ),
133    .ddr_dqs( ddr_dqs_o ),
134    .ddr_dqs_oe( ddr_dqs_oe )
135);
136
137ddr_rpath rpath0 (
138    .clk( read_clk ),
139    .reset( reset_int ),
140    //
141    .sample( sample ),
142    //
143    .rfifo_clk( clk ),
144    .rfifo_empty( rfifo_empty),
145    .rfifo_dout( rfifo_dout ),
146    .rfifo_next( rfifo_next ),
147    // DDR
148    .ddr_dq( ddr_dq_i ),
149    .ddr_dqs( ddr_dqs_i )
150);
151
152//----------------------------------------------------------------------------
153// 7.8 us pulse generator
154//----------------------------------------------------------------------------
155wire pulse78;
156reg ar_req;
157reg ar_done;
158
159ddr_pulse78 #(
160    .clk_freq( clk_freq )
161) pulse78_gen (
162    .clk( clk ),
163    .reset( reset_int ),
164    .pulse78( pulse78 )
165);
166
167//----------------------------------------------------------------------------
168// Auto Refresh request generator
169//----------------------------------------------------------------------------
170always @(posedge clk)
171    if (reset_int)
172        ar_req <= 0;
173    else
174        ar_req <= pulse78 | (ar_req & ~ar_done);
175
176// operations we might want to submit
177wire [`CBA_RNG] ar_pre_cba;
178wire [`CBA_RNG] ar_ar_cba;
179
180assign ar_pre_cba = { `DDR_CMD_PRE, 2'b00, 13'b1111111111111 };
181assign ar_ar_cba = { `DDR_CMD_AR, 2'b00, 13'b0000000000000 };
182
183//----------------------------------------------------------------------------
184// Init & management
185//----------------------------------------------------------------------------
186wire init_req;
187reg init_ack;
188wire [`CBA_RNG] init_cba;
189wire init_done;
190wire wait200;
191
192ddr_init #(
193    .wait200_init( wait200_init )
194) init (
195    .clk( clk ),
196    .reset( reset_int ),
197    .pulse78( pulse78 ),
198    .wait200( wait200 ),
199    .init_done( init_done ),
200    //
201    .mngt_req( init_req ),
202    .mngt_ack( init_ack ),
203    .mngt_cba( init_cba )
204);
205
206//----------------------------------------------------------------------------
207// Active Bank Information
208//----------------------------------------------------------------------------
209reg [`ROW_RNG] ba_row [3:0];
210reg [3:0] ba_active;
211
212//----------------------------------------------------------------------------
213// FML decoding
214//----------------------------------------------------------------------------
215wire [`FML_ADR_BA_RNG] fml_ba = fml_adr[`FML_ADR_BA_RNG];
216wire [`FML_ADR_ROW_RNG] fml_row = fml_adr[`FML_ADR_ROW_RNG];
217wire [`FML_ADR_COL_RNG] fml_col = fml_adr[`FML_ADR_COL_RNG];
218
219wire [`FML_ADR_ROW_RNG] fml_cur_row; // current active row in sel. bank
220assign fml_cur_row = ba_row[fml_ba];
221
222wire fml_row_active; // is row in selected ba really active?
223assign fml_row_active = ba_active[fml_ba];
224
225
226/*
227wire fml_row_active = (fml_ba == 0) ? ba0_active : // is row in selected
228                        (fml_ba == 1) ? ba1_active : // bank really active?
229                        (fml_ba == 2) ? ba2_active :
230                                        ba3_active ;
231*/
232
233// request operation iff correct bank is active
234wire fml_req = fml_rd | fml_wr;
235wire fml_row_match = (fml_row == fml_cur_row) & fml_row_active;
236wire fml_pre_req = fml_req & ~fml_row_match & fml_row_active;
237wire fml_act_req = fml_req & ~fml_row_active;
238wire fml_read_req = fml_rd & fml_row_match & ~fml_done;
239wire fml_write_req = fml_wr & fml_row_match & ~fml_done;
240
241// actual operations we might want to submit
242wire [`CBA_RNG] fml_pre_cba;
243wire [`CBA_RNG] fml_act_cba;
244wire [`CBA_RNG] fml_read_cba;
245wire [`CBA_RNG] fml_write_cba;
246
247assign fml_pre_cba = { `DDR_CMD_PRE, fml_ba, 13'b0 };
248assign fml_act_cba = { `DDR_CMD_ACT, fml_ba, fml_row };
249assign fml_read_cba = { `DDR_CMD_READ, fml_ba, {3'b000}, fml_col, {3'b000} };
250assign fml_write_cba = { `DDR_CMD_WRITE, fml_ba, {3'b000}, fml_col, {3'b000} };
251
252//----------------------------------------------------------------------------
253// Schedule and issue commands
254//----------------------------------------------------------------------------
255
256parameter s_init = 0;
257parameter s_idle = 1;
258parameter s_ar = 2;
259parameter s_reading = 3;
260
261reg [1:0] state;
262
263always @(posedge clk)
264begin
265    if (reset_int) begin
266        state <= s_init;
267        ba_active <= 0;
268        ba_row[0] <= 0;
269        ba_row[1] <= 0;
270        ba_row[2] <= 0;
271        ba_row[3] <= 0;
272
273        fml_done <= 0;
274        init_ack <= 0;
275        cba_fifo_we <= 0;
276        ar_done <= 0;
277    end else begin
278        fml_done <= 0;
279        init_ack <= 0;
280        cba_fifo_we <= 0;
281        ar_done <= 0;
282
283        case (state)
284            s_init: begin
285                if (init_done)
286                    state <= s_idle;
287
288                if (init_req & ~cba_fifo_full) begin
289                    cba_fifo_we <= 1;
290                    cba_fifo_din <= init_cba;
291                    init_ack <= 1;
292                end
293            end
294            s_idle: begin
295                if (fml_read_req & ~cba_fifo_full) begin
296                    cba_fifo_we <= 1;
297                    cba_fifo_din <= fml_read_cba;
298                    fml_done <= 1;
299                end else if (fml_write_req & ~cba_fifo_full) begin
300                    cba_fifo_we <= 1;
301                    cba_fifo_din <= fml_write_cba;
302                    fml_done <= 1;
303                end else if (ar_req & ~cba_fifo_full) begin
304                    cba_fifo_we <= 1;
305                    cba_fifo_din <= ar_pre_cba;
306                    ar_done <= 1;
307                    ba_active <= 'b0;
308                    state <= s_ar;
309                end else if (fml_pre_req & ~cba_fifo_full) begin
310                    cba_fifo_we <= 1;
311                    cba_fifo_din <= fml_pre_cba;
312                    ba_active[fml_ba] <= 0;
313                end else if (fml_act_req & ~cba_fifo_full) begin
314                    cba_fifo_we <= 1;
315                    cba_fifo_din <= fml_act_cba;
316                    ba_active[fml_ba] <= 1;
317                    ba_row[fml_ba] <= fml_row;
318                end
319            end
320            s_ar: begin
321                if (~cba_fifo_full) begin
322                    cba_fifo_we <= 1;
323                    cba_fifo_din <= ar_ar_cba;
324                    state <= s_idle;
325                end
326            end
327        endcase
328    end
329end
330
331//----------------------------------------------------------------------------
332// Demux dqs and dq
333//----------------------------------------------------------------------------
334assign ddr_cke = {~wait200, ~wait200}; // bring up CKE as soon 200us wait is finished
335
336assign ddr_dqs = ddr_dqs_oe!=1'b0 ? ddr_dqs_o : 'bz;
337assign ddr_dq = ddr_dqs_oe!=1'b0 ? ddr_dq_o : 'bz;
338
339assign ddr_dqs_i = ddr_dqs;
340assign ddr_dq_i = ddr_dq;
341
342assign ddr_cs_n = 2'b00;
343
344//----------------------------------------------------------------------------
345// Probes
346//----------------------------------------------------------------------------
347assign probe_clk = clk;
348
349always @(*)
350begin
351    case (probe_sel)
352        8'h00: probe <= { cba_fifo_we, wfifo_we, rfifo_next, 1'b0, cba_fifo_full, wfifo_full, rfifo_empty, 1'b0 };
353        8'h01: probe <= { write_clk, write_clk90, read_clk, 5'b00000 };
354        8'h10: probe <= { rfifo_empty, rfifo_next, rfifo_dout[ 5: 0] };
355        8'h11: probe <= { rfifo_empty, rfifo_next, rfifo_dout[13: 8] };
356        8'h12: probe <= { rfifo_empty, rfifo_next, rfifo_dout[21:16] };
357        8'h13: probe <= { rfifo_empty, rfifo_next, rfifo_dout[29:24] };
358        8'h20: probe <= wfifo_din[ 7:0];
359        8'h21: probe <= wfifo_din[15:8];
360        8'h20: probe <= wfifo_din[23:16];
361        8'h21: probe <= wfifo_din[31:24];
362        8'h30: probe <= cba_fifo_din[17:10];
363        8'h31: probe <= cba_fifo_din[ 9:2];
364    default: probe <= 0'b0;
365    endcase
366end
367
368
369endmodule
370
371

Archive Download this file

Branches:
master



interactive