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