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

1//----------------------------------------------------------------------------
2// Wishbone DDR Controller -- fast write data-path
3//
4// (c) Joerg Bornschein (<jb@capsec.org>)
5//----------------------------------------------------------------------------
6`include "ddr_include.v"
7
8module ddr_wpath (
9    input clk,
10    input clk90,
11    input reset,
12    // CBA async fifo
13    input cba_clk,
14    input [`CBA_RNG] cba_din,
15    input cba_wr,
16    output cba_full,
17    // WDATA async fifo
18    input wdata_clk,
19    input [`WFIFO_RNG] wdata_din,
20    input wdata_wr,
21    output wdata_full,
22    // sample to rdata
23    output sample,
24    // DDR
25    output [2:0] ddr_clk,
26    output [2:0] ddr_clk_n,
27    output ddr_ras_n,
28    output ddr_cas_n,
29    output ddr_we_n,
30    output [ `A_RNG] ddr_a,
31    output [ `BA_RNG] ddr_ba,
32    output [ `DM_RNG] ddr_dm,
33    output [ `DQ_RNG] ddr_dq,
34    output [`DQS_RNG] ddr_dqs,
35     output ddr_dqs_oe
36);
37
38wire gnd = 1'b0;
39wire vcc = 1'b1;
40
41//----------------------------------------------------------------------------
42// CBA async. fifo
43//----------------------------------------------------------------------------
44wire [`CBA_RNG] cba_data;
45wire cba_empty;
46wire cba_ack;
47
48wire cba_avail = ~cba_empty;
49
50async_fifo #(
51    .DATA_WIDTH( `CBA_WIDTH ),
52    .ADDRESS_WIDTH( 4 )
53) cba_fifo (
54    .Data_out( cba_data ),
55    .Empty_out( cba_empty ),
56    .ReadEn_in( cba_ack ),
57    .RClk( clk ),
58    //
59    .Data_in( cba_din ),
60    .WriteEn_in( cba_wr ),
61    .Full_out( cba_full ),
62    .WClk( cba_clk ),
63    .Clear_in( reset )
64);
65
66//----------------------------------------------------------------------------
67// WDATA async. fifo
68//----------------------------------------------------------------------------
69wire [`WFIFO_RNG] wdata_data;
70wire wdata_empty;
71wire wdata_ack;
72
73wire wdata_avail = ~wdata_empty;
74
75async_fifo #(
76    .DATA_WIDTH( `WFIFO_WIDTH ),
77    .ADDRESS_WIDTH( 4 )
78) wdata_fifo (
79    .Data_out( wdata_data ),
80    .Empty_out( wdata_empty ),
81    .ReadEn_in( wdata_ack ),
82    .RClk( ~clk90 ),
83    //
84    .Data_in( wdata_din ),
85    .WriteEn_in( wdata_wr ),
86    .Full_out( wdata_full ),
87    .WClk( wdata_clk ),
88    .Clear_in( reset )
89);
90
91
92//----------------------------------------------------------------------------
93// Handle CBA
94//----------------------------------------------------------------------------
95reg [3:0] delay_count;
96
97reg [`CBA_RNG] ddr_cba;
98wire [`CBA_RNG] CBA_NOP = { `DDR_CMD_NOP, 15'b0 };
99
100assign cba_ack = cba_avail & (delay_count == 0);
101
102wire [`CMD_RNG] cba_cmd = cba_data[(`CBA_WIDTH-1):(`CBA_WIDTH-3)];
103
104always @(posedge clk)
105begin
106    if (reset) begin
107        delay_count <= 0;
108        ddr_cba <= CBA_NOP;
109    end else begin
110        if (delay_count != 0) begin
111            delay_count <= delay_count - 1;
112            ddr_cba <= CBA_NOP;
113        end
114
115        if (!cba_ack) begin
116            ddr_cba <= CBA_NOP;
117        end else begin
118            ddr_cba <= cba_data;
119
120            case (cba_cmd)
121                `DDR_CMD_MRS : delay_count <= 2;
122                `DDR_CMD_AR : delay_count <= 14;
123                `DDR_CMD_ACT : delay_count <= 4;
124                `DDR_CMD_PRE : delay_count <= 2;
125                `DDR_CMD_READ : delay_count <= 6; // XXX
126                `DDR_CMD_WRITE : delay_count <= 8; // XXX
127            endcase
128        end
129    end
130end
131            
132
133//----------------------------------------------------------------------------
134// READ-SHIFT-REGISTER
135//----------------------------------------------------------------------------
136reg [7:0] read_shr;
137wire read_cmd = (cba_cmd == `DDR_CMD_READ) & cba_ack;
138assign sample = read_shr[6];
139
140always @(posedge clk)
141begin
142    if (reset)
143        read_shr <= 'b0;
144    else begin
145        if (read_cmd)
146             read_shr <= { 8'b00011000 };
147         else
148             read_shr <= { read_shr[6:0], 1'b0 };
149     end
150end
151
152//----------------------------------------------------------------------------
153// WRITE-SHIFT-REGISTER
154//----------------------------------------------------------------------------
155
156reg [0:4] write_shr;
157wire write_cmd = (cba_cmd == `DDR_CMD_WRITE) & cba_ack;
158
159always @(posedge clk)
160begin
161    if (reset)
162        write_shr <= 'b0;
163    else begin
164        if (write_cmd)
165             write_shr <= { 5'b11111 };
166         else
167             write_shr <= { write_shr[1:4], 1'b0 };
168     end
169end
170
171//----------------------------------------------------------------------------
172// DDR_DQS, DDR_DQS_OE
173//----------------------------------------------------------------------------
174genvar i;
175
176reg ddr_dqs_oe_reg;
177assign ddr_dqs_oe = ddr_dqs_oe_reg;
178
179always @(negedge clk)
180begin
181  ddr_dqs_oe_reg <= write_shr[0];
182end
183
184generate
185for (i=0; i<3; i=i+1) begin : CLK
186    FDDRRSE ddr_clk_reg (
187        .Q( ddr_clk[i] ),
188        .C0( clk90 ),
189        .C1( ~clk90 ),
190        .CE( vcc ),
191        .D0( vcc ),
192        .D1( gnd ),
193        .R( gnd ),
194        .S( gnd )
195    );
196
197    FDDRRSE ddr_clk_n_reg (
198        .Q( ddr_clk_n[i] ),
199        .C0( clk90 ),
200        .C1( ~clk90 ),
201        .CE( vcc ),
202        .D0( gnd ),
203        .D1( vcc ),
204        .R( gnd ),
205        .S( gnd )
206    );
207end
208endgenerate
209
210generate
211for (i=0; i<`DQS_WIDTH; i=i+1) begin : DQS
212    FDDRRSE ddr_dqs_reg (
213        .Q( ddr_dqs[i] ),
214        .C0( clk ),
215        .C1( ~clk ),
216        .CE( vcc ),
217        .D0( write_shr[1] ),
218        .D1( gnd ),
219        .R( gnd ),
220        .S( gnd )
221    );
222end
223endgenerate
224
225
226//----------------------------------------------------------------------------
227// DQ data output
228//----------------------------------------------------------------------------
229wire [`DQ_RNG] buf_d0;
230wire [`DM_RNG] buf_m0;
231reg [`DQ_RNG] buf_d1; // pipleine high word data
232reg [`DM_RNG] buf_m1; // pipleine high word mask
233
234assign buf_d0 = wdata_data[`WFIFO_D0_RNG];
235assign buf_m0 = wdata_data[`WFIFO_M0_RNG];
236
237always @(negedge clk90)
238begin
239    buf_d1 <= wdata_data[`WFIFO_D1_RNG];
240    buf_m1 <= wdata_data[`WFIFO_M1_RNG];
241end
242
243assign wdata_ack = write_shr[1];
244
245// generate DDR_DQ register
246generate
247for (i=0; i<`DQ_WIDTH; i=i+1) begin : DQ_REG
248    FDDRRSE ddr_dq_reg (
249        .Q( ddr_dq[i] ),
250        .C0( ~clk90 ),
251        .C1( clk90 ),
252        .CE( vcc ),
253        .D0( buf_d0[i] ),
254        .D1( buf_d1[i] ),
255        .R( gnd ),
256        .S( gnd )
257    );
258end
259endgenerate
260
261// generate DDR_DM register
262generate
263for (i=0; i<`DM_WIDTH; i=i+1) begin : DM_REG
264    FDDRRSE ddr_dm_reg (
265        .Q( ddr_dm[i] ),
266        .C0( ~clk90 ),
267        .C1( clk90 ),
268        .CE( vcc ),
269        .D0( buf_m0[i] ),
270        .D1( buf_m1[i] ),
271        .R( gnd ),
272        .S( gnd )
273    );
274end
275endgenerate
276
277//----------------------------------------------------------------------------
278// Connect ddr_cba to actual DDR pins
279//----------------------------------------------------------------------------
280assign ddr_a = ddr_cba[(`A_WIDTH-1):0];
281assign ddr_ba = ddr_cba[(`A_WIDTH+`BA_WIDTH-1):(`A_WIDTH)];
282assign ddr_ras_n = ddr_cba[(`CBA_WIDTH-1)];
283assign ddr_cas_n = ddr_cba[(`CBA_WIDTH-2)];
284assign ddr_we_n = ddr_cba[(`CBA_WIDTH-3)];
285
286endmodule
287

Archive Download this file

Branches:
master



interactive