add peripherals
[shakti-peripherals.git] / src / peripherals / sdram / controller / sdrc_req_gen.v
1 /*********************************************************************
2
3 SDRAM Controller Request Generation
4
5 This file is part of the sdram controller project
6 http://www.opencores.org/cores/sdr_ctrl/
7
8 Description: SDRAM Controller Reguest Generation
9
10 Address Generation Based on cfg_colbits
11 cfg_colbits= 2'b00
12 Address[7:0] - Column Address
13 Address[9:8] - Bank Address
14 Address[22:10] - Row Address
15 cfg_colbits= 2'b01
16 Address[8:0] - Column Address
17 Address[10:9] - Bank Address
18 Address[23:11] - Row Address
19 cfg_colbits= 2'b10
20 Address[9:0] - Column Address
21 Address[11:10] - Bank Address
22 Address[24:12] - Row Address
23 cfg_colbits= 2'b11
24 Address[10:0] - Column Address
25 Address[12:11] - Bank Address
26 Address[25:13] - Row Address
27
28 The SDRAMs are operated in 4 beat burst mode.
29
30 If Wrap = 0;
31 If the current burst cross the page boundary, then this block split the request
32 into two coressponding change in address and request length
33
34 if the current burst cross the page boundar.
35 This module takes requests from the memory controller,
36 chops them to page boundaries if wrap=0,
37 and passes the request to bank_ctl
38
39 Note: With Wrap = 0, each request from Application layer will be splited into two request,
40 if the current burst cross the page boundary.
41
42 To Do:
43 nothing
44
45 Author(s):
46 - Dinesh Annayya, dinesha@opencores.org
47 Version : 0.0 - 8th Jan 2012
48 0.1 - 5th Feb 2012, column/row/bank address are register to improve the timing issue in FPGA synthesis
49
50
51
52 Copyright (C) 2000 Authors and OPENCORES.ORG
53
54 This source file may be used and distributed without
55 restriction provided that this copyright statement is not
56 removed from the file and that any derivative work contains
57 the original copyright notice and the associated disclaimer.
58
59 This source file is free software; you can redistribute it
60 and/or modify it under the terms of the GNU Lesser General
61 Public License as published by the Free Software Foundation;
62 either version 2.1 of the License, or (at your option) any
63 later version.
64
65 This source is distributed in the hope that it will be
66 useful, but WITHOUT ANY WARRANTY; without even the implied
67 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
68 PURPOSE. See the GNU Lesser General Public License for more
69 details.
70
71 You should have received a copy of the GNU Lesser General
72 Public License along with this source; if not, download it
73 from http://www.opencores.org/lgpl.shtml
74
75 *******************************************************************/
76
77
78
79 module sdrc_req_gen (clk,
80 reset_n,
81 cfg_colbits,
82 sdr_width,
83
84 /* Request from app */
85 req, // Transfer Request
86 req_id, // ID for this transfer
87 req_addr, // SDRAM Address
88 req_len, // Burst Length (in 32 bit words)
89 req_wrap, // Wrap mode request (xfr_len = 4)
90 req_wr_n, // 0 => Write request, 1 => read req
91 req_ack, // Request has been accepted
92
93 /* Req to xfr_ctl */
94 r2x_idle,
95
96 /* Req to bank_ctl */
97 r2b_req, // request
98 r2b_req_id, // ID
99 r2b_start, // First chunk of burst
100 r2b_last, // Last chunk of burst
101 r2b_wrap, // Wrap Mode
102 r2b_ba, // bank address
103 r2b_raddr, // row address
104 r2b_caddr, // col address
105 r2b_len, // length
106 r2b_write, // write request
107 b2r_ack,
108 b2r_arb_ok
109 );
110
111
112 `define SDR_REQ_ID_W 4
113
114 `define SDR_RFSH_TIMER_W 12
115 `define SDR_RFSH_ROW_CNT_W 3
116
117 // B2X Command
118
119 `define OP_PRE 2'b00
120 `define OP_ACT 2'b01
121 `define OP_RD 2'b10
122 `define OP_WR 2'b11
123
124 // SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N)
125
126 `define SDR_DESEL 4'b1111
127 `define SDR_NOOP 4'b0111
128 `define SDR_ACTIVATE 4'b0011
129 `define SDR_READ 4'b0101
130 `define SDR_WRITE 4'b0100
131 `define SDR_BT 4'b0110
132 `define SDR_PRECHARGE 4'b0010
133 `define SDR_REFRESH 4'b0001
134 `define SDR_MODE 4'b0000
135
136 `define ASIC 1'b1
137 `define FPGA 1'b0
138 `define TARGET_DESIGN `ASIC
139 // 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits
140 `define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width
141
142 parameter APP_AW = 26; // Application Address Width
143 parameter APP_DW = 64; // Application Data Width
144 parameter APP_BW = 8; // Application Byte Width
145 parameter APP_RW = 9; // Application Request Width
146
147 parameter SDR_DW = 64; // SDR Data Width
148 parameter SDR_BW = 8; // SDR Byte Width
149
150
151 input clk ;
152 input reset_n ;
153 input [1:0] cfg_colbits ; // 2'b00 - 8 Bit column address, 2'b01 - 9 Bit, 10 - 10 bit, 11 - 11Bits
154
155 /* Request from app */
156 input req ; // Request
157 input [`SDR_REQ_ID_W-1:0] req_id ; // Request ID
158 input [APP_AW-1:0] req_addr ; // Request Address
159 input [APP_RW-1:0] req_len ; // Request length
160 input req_wr_n ; // 0 -Write, 1 - Read
161 input req_wrap ; // 1 - Wrap the Address on page boundary
162 output req_ack ; // Request Ack
163
164 /* Req to bank_ctl */
165 output r2x_idle ;
166 output r2b_req ; // Request
167 output r2b_start ; // First Junk of the Burst Access
168 output r2b_last ; // Last Junk of the Burst Access
169 output r2b_write ; // 1 - Write, 0 - Read
170 output r2b_wrap ; // 1 - Wrap the Address at the page boundary.
171 output [`SDR_REQ_ID_W-1:0] r2b_req_id;
172 output [1:0] r2b_ba ; // Bank Address
173 output [12:0] r2b_raddr ; // Row Address
174 output [12:0] r2b_caddr ; // Column Address
175 output [`REQ_BW-1:0] r2b_len ; // Burst Length
176 input b2r_ack ; // Request Ack
177 input b2r_arb_ok ; // Bank controller fifo is not full and ready to accept the command
178 //
179 input [1:0] sdr_width; // 2'b00 - 32 Bit, 2'b01 - 16 Bit, 2'b1x - 8Bit
180
181
182 /****************************************************************************/
183 // Internal Nets
184
185 `define REQ_IDLE 2'b00
186 `define REQ_ACTIVE 2'b01
187 `define REQ_PAGE_WRAP 2'b10
188
189 reg [1:0] req_st, next_req_st;
190 reg r2x_idle, req_ack, r2b_req, r2b_start,
191 r2b_write, req_idle, req_ld, lcl_wrap;
192 reg [`SDR_REQ_ID_W-1:0] r2b_req_id;
193 reg [`REQ_BW-1:0] lcl_req_len;
194
195 wire r2b_last, page_ovflw;
196 reg page_ovflw_r;
197 wire [`REQ_BW-1:0] r2b_len, next_req_len;
198 wire [12:0] max_r2b_len;
199 reg [12:0] max_r2b_len_r;
200
201 reg [1:0] r2b_ba;
202 reg [12:0] r2b_raddr;
203 reg [12:0] r2b_caddr;
204
205 reg [APP_AW-1:0] curr_sdr_addr ;
206 wire [APP_AW-1:0] next_sdr_addr ;
207
208
209 //--------------------------------------------------------------------
210 // Generate the internal Adress and Burst length Based on sdram width
211 //--------------------------------------------------------------------
212 reg [APP_AW:0] req_addr_int;
213 reg [APP_RW-1:0] req_len_int;
214
215 always @(*) begin
216 if(sdr_width == 2'b00) begin // 32 Bit SDR Mode
217 req_addr_int = {1'b0,req_addr};
218 req_len_int = req_len;
219 end else if(sdr_width == 2'b01) begin // 16 Bit SDR Mode
220 // Changed the address and length to match the 16 bit SDR Mode
221 req_addr_int = {req_addr,1'b0};
222 req_len_int = {req_len,1'b0};
223 end else begin // 8 Bit SDR Mode
224 // Changed the address and length to match the 16 bit SDR Mode
225 req_addr_int = {req_addr,2'b0};
226 req_len_int = {req_len,2'b0};
227 end
228 end
229
230 //
231 // Identify the page over flow.
232 // Find the Maximum Burst length allowed from the selected column
233 // address, If the requested burst length is more than the allowed Maximum
234 // burst length, then we need to handle the bank cross over case and we
235 // need to split the reuest.
236 //
237 assign max_r2b_len = (cfg_colbits == 2'b00) ? (12'h100 - {4'b0, req_addr_int[7:0]}) :
238 (cfg_colbits == 2'b01) ? (12'h200 - {3'b0, req_addr_int[8:0]}) :
239 (cfg_colbits == 2'b10) ? (12'h400 - {2'b0, req_addr_int[9:0]}) : (12'h800 - {1'b0, req_addr_int[10:0]});
240
241
242 // If the wrap = 0 and current application burst length is crossing the page boundary,
243 // then request will be split into two with corresponding change in request address and request length.
244 //
245 // If the wrap = 0 and current burst length is not crossing the page boundary,
246 // then request from application layer will be transparently passed on the bank control block.
247
248 //
249 // if the wrap = 1, then this block will not modify the request address and length.
250 // The wrapping functionality will be handle by the bank control module and
251 // column address will rewind back as follows XX -> FF ? 00 ? 1
252 //
253 // Note: With Wrap = 0, each request from Application layer will be spilited into two request,
254 // if the current burst cross the page boundary.
255 assign page_ovflw = ({1'b0, req_len_int} > max_r2b_len) ? (req_ack && ~req_wrap) : 1'b0; // vish change
256
257 assign r2b_len = r2b_start ? ((page_ovflw_r) ? max_r2b_len_r : lcl_req_len) :
258 lcl_req_len;
259
260 assign next_req_len = lcl_req_len - r2b_len;
261
262 assign next_sdr_addr = curr_sdr_addr + r2b_len;
263
264
265 assign r2b_wrap = lcl_wrap;
266
267 assign r2b_last = (r2b_start & !page_ovflw_r) | (req_st == `REQ_PAGE_WRAP);
268 //
269 //
270 //
271 always @ (posedge clk) begin
272
273 page_ovflw_r <= (req_ack) ? page_ovflw: 'h0;
274
275 max_r2b_len_r <= (req_ack) ? max_r2b_len: 'h0;
276 r2b_start <= (req_ack) ? 1'b1 :
277 (b2r_ack) ? 1'b0 : r2b_start;
278
279 r2b_write <= (req_ack) ? ~req_wr_n : r2b_write;
280
281 r2b_req_id <= (req_ack) ? req_id : r2b_req_id;
282
283 lcl_wrap <= (req_ack) ? req_wrap : lcl_wrap;
284
285 lcl_req_len <= (req_ack) ? req_len_int :
286 (req_ld) ? next_req_len : lcl_req_len;
287
288 curr_sdr_addr <= (req_ack) ? req_addr_int :
289 (req_ld) ? next_sdr_addr : curr_sdr_addr;
290
291 end // always @ (posedge clk)
292
293 always @ (*) begin
294 r2x_idle = 1'b0;
295 req_idle = 1'b0;
296 req_ack = 1'b0;
297 req_ld = 1'b0;
298 r2b_req = 1'b0;
299 next_req_st = `REQ_IDLE;
300
301 case (req_st) // synopsys full_case parallel_case
302
303 `REQ_IDLE : begin
304 r2x_idle = ~req;
305 req_idle = 1'b1;
306 req_ack = req & b2r_arb_ok;
307 req_ld = 1'b0;
308 r2b_req = 1'b0;
309 next_req_st = (req & b2r_arb_ok) ? `REQ_ACTIVE : `REQ_IDLE;
310 end // case: `REQ_IDLE
311
312 `REQ_ACTIVE : begin
313 r2x_idle = 1'b0;
314 req_idle = 1'b0;
315 req_ack = 1'b0;
316 req_ld = b2r_ack;
317 r2b_req = 1'b1; // req_gen to bank_req
318 next_req_st = (b2r_ack ) ? ((page_ovflw_r) ? `REQ_PAGE_WRAP :`REQ_IDLE) : `REQ_ACTIVE;
319 end // case: `REQ_ACTIVE
320 `REQ_PAGE_WRAP : begin
321 r2x_idle = 1'b0;
322 req_idle = 1'b0;
323 req_ack = 1'b0;
324 req_ld = b2r_ack;
325 r2b_req = 1'b1; // req_gen to bank_req
326 next_req_st = (b2r_ack) ? `REQ_IDLE : `REQ_PAGE_WRAP;
327 end // case: `REQ_ACTIVE
328
329 endcase // case(req_st)
330
331 end // always @ (req_st or ....)
332
333 always @ (posedge clk)
334 if (~reset_n) begin
335 req_st <= `REQ_IDLE;
336 end // if (~reset_n)
337 else begin
338 req_st <= next_req_st;
339 end // else: !if(~reset_n)
340 //
341 // addrs bits for the bank, row and column
342 //
343 // Register row/column/bank to improve fpga timing issue
344 wire [APP_AW-1:0] map_address ;
345
346 assign map_address = (req_ack) ? req_addr_int :
347 (req_ld) ? next_sdr_addr : curr_sdr_addr;
348
349 always @ (posedge clk) begin
350 // Bank Bits are always - 2 Bits
351 r2b_ba <= (cfg_colbits == 2'b00) ? {map_address[9:8]} :
352 (cfg_colbits == 2'b01) ? {map_address[10:9]} :
353 (cfg_colbits == 2'b10) ? {map_address[11:10]} : map_address[12:11];
354
355 /********************
356 * Colbits Mapping:
357 * 2'b00 - 8 Bit
358 * 2'b01 - 16 Bit
359 * 2'b10 - 10 Bit
360 * 2'b11 - 11 Bits
361 ************************/
362 r2b_caddr <= (cfg_colbits == 2'b00) ? {5'b0, map_address[7:0]} :
363 (cfg_colbits == 2'b01) ? {4'b0, map_address[8:0]} :
364 (cfg_colbits == 2'b10) ? {3'b0, map_address[9:0]} : {2'b0, map_address[10:0]};
365
366 r2b_raddr <= (cfg_colbits == 2'b00) ? map_address[22:10] :
367 (cfg_colbits == 2'b01) ? map_address[23:11] :
368 (cfg_colbits == 2'b10) ? map_address[24:12] : map_address[25:13];
369 end
370
371 endmodule // sdr_req_gen