add peripherals
[shakti-peripherals.git] / src / peripherals / sdram / controller / sdrc_bank_fsm.v
1 /*********************************************************************
2
3 SDRAM Controller Bank Controller
4
5 This file is part of the sdram controller project
6 http://www.opencores.org/cores/sdr_ctrl/
7
8 Description:
9 This module takes requests from sdrc_req_gen, checks for page hit/miss and
10 issues precharge/activate commands and then passes the request to sdrc_xfr_ctl.
11
12 To Do:
13 nothing
14
15 Author(s):
16 - Dinesh Annayya, dinesha@opencores.org
17 Version : 1.0 - 8th Jan 2012
18
19
20
21 Copyright (C) 2000 Authors and OPENCORES.ORG
22
23 This source file may be used and distributed without
24 restriction provided that this copyright statement is not
25 removed from the file and that any derivative work contains
26 the original copyright notice and the associated disclaimer.
27
28 This source file is free software; you can redistribute it
29 and/or modify it under the terms of the GNU Lesser General
30 Public License as published by the Free Software Foundation;
31 either version 2.1 of the License, or (at your option) any
32 later version.
33
34 This source is distributed in the hope that it will be
35 useful, but WITHOUT ANY WARRANTY; without even the implied
36 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
37 PURPOSE. See the GNU Lesser General Public License for more
38 details.
39
40 You should have received a copy of the GNU Lesser General
41 Public License along with this source; if not, download it
42 from http://www.opencores.org/lgpl.shtml
43
44 *******************************************************************/
45
46
47 //`include "sdrc_define.v"
48
49 module sdrc_bank_fsm (clk,
50 reset_n,
51
52 /* Req from req_gen */
53 r2b_req, // request
54 r2b_req_id, // ID
55 r2b_start, // First chunk of burst
56 r2b_last, // Last chunk of burst
57 r2b_wrap,
58 r2b_raddr, // row address
59 r2b_caddr, // col address
60 r2b_len, // length
61 r2b_write, // write request
62 b2r_ack,
63 sdr_dma_last,
64
65 /* Transfer request to xfr_ctl */
66 b2x_req, // Request to xfr_ctl
67 b2x_start, // first chunk of transfer
68 b2x_last, // last chunk of transfer
69 b2x_wrap,
70 b2x_id, // Transfer ID
71 b2x_addr, // row/col address
72 b2x_len, // transfer length
73 b2x_cmd, // transfer command
74 x2b_ack, // command accepted
75
76 /* Status to/from xfr_ctl */
77 tras_ok, // TRAS OK for this bank
78 xfr_ok,
79 x2b_refresh, // We did a refresh
80 x2b_pre_ok, // OK to do a precharge (per bank)
81 x2b_act_ok, // OK to do an activate
82 x2b_rdok, // OK to do a read
83 x2b_wrok, // OK to do a write
84
85 /* current xfr row address of the bank */
86 bank_row,
87
88 /* SDRAM Timing */
89 tras_delay, // Active to precharge delay
90 trp_delay, // Precharge to active delay
91 trcd_delay); // Active to R/W delay
92
93
94 `define SDR_REQ_ID_W 4
95
96 `define SDR_RFSH_TIMER_W 12
97 `define SDR_RFSH_ROW_CNT_W 3
98
99 // B2X Command
100
101 `define OP_PRE 2'b00
102 `define OP_ACT 2'b01
103 `define OP_RD 2'b10
104 `define OP_WR 2'b11
105
106 // SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N)
107
108 `define SDR_DESEL 4'b1111
109 `define SDR_NOOP 4'b0111
110 `define SDR_ACTIVATE 4'b0011
111 `define SDR_READ 4'b0101
112 `define SDR_WRITE 4'b0100
113 `define SDR_BT 4'b0110
114 `define SDR_PRECHARGE 4'b0010
115 `define SDR_REFRESH 4'b0001
116 `define SDR_MODE 4'b0000
117
118 `define ASIC 1'b1
119 `define FPGA 1'b0
120 `define TARGET_DESIGN `ASIC
121 // 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits
122 `define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width
123
124 parameter SDR_DW = 64; // SDR Data Width
125 parameter SDR_BW = 8; // SDR Byte Width
126
127 input clk, reset_n;
128
129 /* Req from bank_ctl */
130 input r2b_req, r2b_start, r2b_last,
131 r2b_write, r2b_wrap;
132 input [`SDR_REQ_ID_W-1:0] r2b_req_id;
133 input [12:0] r2b_raddr;
134 input [12:0] r2b_caddr;
135 input [`REQ_BW-1:0] r2b_len;
136 output b2r_ack;
137 input sdr_dma_last;
138
139 /* Req to xfr_ctl */
140 output b2x_req, b2x_start, b2x_last,
141 tras_ok, b2x_wrap;
142 output [`SDR_REQ_ID_W-1:0] b2x_id;
143 output [12:0] b2x_addr;
144 output [`REQ_BW-1:0] b2x_len;
145 output [1:0] b2x_cmd;
146 input x2b_ack;
147
148 /* Status from xfr_ctl */
149 input x2b_refresh, x2b_act_ok, x2b_rdok,
150 x2b_wrok, x2b_pre_ok, xfr_ok;
151
152 input [3:0] tras_delay, trp_delay, trcd_delay;
153
154 output [12:0] bank_row;
155
156 /****************************************************************************/
157 // Internal Nets
158
159 `define BANK_IDLE 3'b000
160 `define BANK_PRE 3'b001
161 `define BANK_ACT 3'b010
162 `define BANK_XFR 3'b011
163 `define BANK_DMA_LAST_PRE 3'b100
164
165 reg [2:0] bank_st, next_bank_st;
166 wire b2x_start, b2x_last;
167 reg l_start, l_last;
168 reg b2x_req, b2r_ack;
169 wire [`SDR_REQ_ID_W-1:0] b2x_id;
170 reg [`SDR_REQ_ID_W-1:0] l_id;
171 reg [12:0] b2x_addr;
172 reg [`REQ_BW-1:0] l_len;
173 wire [`REQ_BW-1:0] b2x_len;
174 reg [1:0] b2x_cmd_t;
175 reg bank_valid;
176 reg [12:0] bank_row;
177 reg [3:0] tras_cntr, timer0;
178 reg l_wrap, l_write;
179 wire b2x_wrap;
180 reg [12:0] l_raddr;
181 reg [12:0] l_caddr;
182 reg l_sdr_dma_last;
183 reg bank_prech_page_closed;
184
185 wire tras_ok_internal, tras_ok, activate_bank;
186
187 wire page_hit, timer0_tc_t, ld_trp, ld_trcd;
188
189 /*** Timing Break Logic Added for FPGA - Start ****/
190 reg x2b_wrok_r, xfr_ok_r , x2b_rdok_r;
191 reg [1:0] b2x_cmd_r,timer0_tc_r,tras_ok_r,x2b_pre_ok_r,x2b_act_ok_r;
192 always @ (posedge clk)
193 if (~reset_n) begin
194 x2b_wrok_r <= 1'b0;
195 xfr_ok_r <= 1'b0;
196 x2b_rdok_r <= 1'b0;
197 b2x_cmd_r <= 2'b0;
198 timer0_tc_r <= 1'b0;
199 tras_ok_r <= 1'b0;
200 x2b_pre_ok_r <= 1'b0;
201 x2b_act_ok_r <= 1'b0;
202 end
203 else begin
204 x2b_wrok_r <= x2b_wrok;
205 xfr_ok_r <= xfr_ok;
206 x2b_rdok_r <= x2b_rdok;
207 b2x_cmd_r <= b2x_cmd_t;
208 timer0_tc_r <= (ld_trp | ld_trcd) ? 1'b0 : timer0_tc_t;
209 tras_ok_r <= tras_ok_internal;
210 x2b_pre_ok_r <= x2b_pre_ok;
211 x2b_act_ok_r <= x2b_act_ok;
212 end
213
214 wire x2b_wrok_t = (`TARGET_DESIGN == `FPGA) ? x2b_wrok_r : x2b_wrok;
215 wire xfr_ok_t = (`TARGET_DESIGN == `FPGA) ? xfr_ok_r : xfr_ok;
216 wire x2b_rdok_t = (`TARGET_DESIGN == `FPGA) ? x2b_rdok_r : x2b_rdok;
217 wire [1:0] b2x_cmd = (`TARGET_DESIGN == `FPGA) ? b2x_cmd_r : b2x_cmd_t;
218 wire timer0_tc = (`TARGET_DESIGN == `FPGA) ? timer0_tc_r : timer0_tc_t;
219 assign tras_ok = (`TARGET_DESIGN == `FPGA) ? tras_ok_r : tras_ok_internal;
220 wire x2b_pre_ok_t = (`TARGET_DESIGN == `FPGA) ? x2b_pre_ok_r : x2b_pre_ok;
221 wire x2b_act_ok_t = (`TARGET_DESIGN == `FPGA) ? x2b_act_ok_r : x2b_act_ok;
222
223 /*** Timing Break Logic Added for FPGA - End****/
224
225
226 always @ (posedge clk)
227 if (~reset_n) begin
228 bank_valid <= 1'b0;
229 tras_cntr <= 4'b0;
230 timer0 <= 4'b0;
231 bank_st <= `BANK_IDLE;
232 end // if (~reset_n)
233
234 else begin
235
236 bank_valid <= (x2b_refresh || bank_prech_page_closed) ? 1'b0 : // force the bank status to be invalid
237 (activate_bank) ? 1'b1 : bank_valid;
238
239 tras_cntr <= (activate_bank) ? tras_delay :
240 (~tras_ok_internal) ? tras_cntr - 4'b1 : 4'b0;
241
242 timer0 <= (ld_trp) ? trp_delay :
243 (ld_trcd) ? trcd_delay :
244 (timer0 != 'h0) ? timer0 - 4'b1 : timer0;
245
246 bank_st <= next_bank_st;
247
248 end // else: !if(~reset_n)
249
250 always @ (posedge clk) begin
251
252 bank_row <= (bank_st == `BANK_ACT) ? b2x_addr : bank_row;
253
254 if (~reset_n) begin
255 l_start <= 1'b0;
256 l_last <= 1'b0;
257 l_id <= 1'b0;
258 l_len <= 1'b0;
259 l_wrap <= 1'b0;
260 l_write <= 1'b0;
261 l_raddr <= 1'b0;
262 l_caddr <= 1'b0;
263 l_sdr_dma_last <= 1'b0;
264 end
265 else begin
266 if (b2r_ack) begin
267 l_start <= r2b_start;
268 l_last <= r2b_last;
269 l_id <= r2b_req_id;
270 l_len <= r2b_len;
271 l_wrap <= r2b_wrap;
272 l_write <= r2b_write;
273 l_raddr <= r2b_raddr;
274 l_caddr <= r2b_caddr;
275 l_sdr_dma_last <= sdr_dma_last;
276 end // if (b2r_ack)
277 end
278
279 end // always @ (posedge clk)
280
281 assign tras_ok_internal = ~|tras_cntr;
282
283 assign activate_bank = (b2x_cmd == `OP_ACT) & x2b_ack;
284
285 assign page_hit = (r2b_raddr == bank_row) ? bank_valid : 1'b0; // its a hit only if bank is valid
286
287 assign timer0_tc_t = ~|timer0;
288
289 assign ld_trp = (b2x_cmd == `OP_PRE) ? x2b_ack : 1'b0;
290
291 assign ld_trcd = (b2x_cmd == `OP_ACT) ? x2b_ack : 1'b0;
292
293
294
295 always @ (*) begin
296
297 bank_prech_page_closed = 1'b0;
298 b2x_req = 1'b0;
299 b2x_cmd_t = 2'bx;
300 b2r_ack = 1'b0;
301 b2x_addr = 13'bx;
302 next_bank_st = bank_st;
303
304 case (bank_st)
305
306 `BANK_IDLE : begin
307 if(`TARGET_DESIGN == `FPGA) begin // To break the timing, b2x request are generated delayed
308 if (~r2b_req) begin
309 next_bank_st = `BANK_IDLE;
310 end // if (~r2b_req)
311 else if (page_hit) begin
312 b2r_ack = 1'b1;
313 b2x_cmd_t = (r2b_write) ? `OP_WR : `OP_RD;
314 next_bank_st = `BANK_XFR;
315 end // if (page_hit)
316 else begin // page_miss
317 b2r_ack = 1'b1;
318 b2x_cmd_t = `OP_PRE;
319 next_bank_st = `BANK_PRE; // bank was precharged on l_sdr_dma_last
320 end // else: !if(page_hit)
321 end else begin // ASIC
322 if (~r2b_req) begin
323 bank_prech_page_closed = 1'b0;
324 b2x_req = 1'b0;
325 b2x_cmd_t = 2'bx;
326 b2r_ack = 1'b0;
327 b2x_addr = 13'bx;
328 next_bank_st = `BANK_IDLE;
329 end // if (~r2b_req)
330 else if (page_hit) begin
331 b2x_req = (r2b_write) ? x2b_wrok_t & xfr_ok_t :
332 x2b_rdok_t & xfr_ok_t;
333 b2x_cmd_t = (r2b_write) ? `OP_WR : `OP_RD;
334 b2r_ack = 1'b1;
335 b2x_addr = r2b_caddr;
336 next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_XFR; // in case of hit, stay here till xfr sm acks
337 end // if (page_hit)
338 else begin // page_miss
339 b2x_req = tras_ok & x2b_pre_ok_t;
340 b2x_cmd_t = `OP_PRE;
341 b2r_ack = 1'b1;
342 b2x_addr = r2b_raddr & 13'hBFF; // Dont want to pre all banks!
343 next_bank_st = (l_sdr_dma_last) ? `BANK_PRE : (x2b_ack) ? `BANK_ACT : `BANK_PRE; // bank was precharged on l_sdr_dma_last
344 end // else: !if(page_hit)
345 end
346 end // case: `BANK_IDLE
347
348 `BANK_PRE : begin
349 b2x_req = tras_ok & x2b_pre_ok_t;
350 b2x_cmd_t = `OP_PRE;
351 b2r_ack = 1'b0;
352 b2x_addr = l_raddr & 13'hBFF; // Dont want to pre all banks!
353 bank_prech_page_closed = 1'b0;
354 next_bank_st = (x2b_ack) ? `BANK_ACT : `BANK_PRE;
355 end // case: `BANK_PRE
356
357 `BANK_ACT : begin
358 b2x_req = timer0_tc & x2b_act_ok_t;
359 b2x_cmd_t = `OP_ACT;
360 b2r_ack = 1'b0;
361 b2x_addr = l_raddr;
362 bank_prech_page_closed = 1'b0;
363 next_bank_st = (x2b_ack) ? `BANK_XFR : `BANK_ACT;
364 end // case: `BANK_ACT
365
366 `BANK_XFR : begin
367 b2x_req = (l_write) ? timer0_tc & x2b_wrok_t & xfr_ok_t :
368 timer0_tc & x2b_rdok_t & xfr_ok_t;
369 b2x_cmd_t = (l_write) ? `OP_WR : `OP_RD;
370 b2r_ack = 1'b0;
371 b2x_addr = l_caddr;
372 bank_prech_page_closed = 1'b0;
373 next_bank_st = (x2b_refresh) ? `BANK_ACT :
374 (x2b_ack & l_sdr_dma_last) ? `BANK_DMA_LAST_PRE :
375 (x2b_ack) ? `BANK_IDLE : `BANK_XFR;
376 end // case: `BANK_XFR
377
378 `BANK_DMA_LAST_PRE : begin
379 b2x_req = tras_ok & x2b_pre_ok_t;
380 b2x_cmd_t = `OP_PRE;
381 b2r_ack = 1'b0;
382 b2x_addr = l_raddr & 13'hBFF; // Dont want to pre all banks!
383 bank_prech_page_closed = 1'b1;
384 next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_DMA_LAST_PRE;
385 end // case: `BANK_DMA_LAST_PRE
386
387 endcase // case(bank_st)
388
389 end // always @ (bank_st or ...)
390
391 assign b2x_start = (bank_st == `BANK_IDLE) ? r2b_start : l_start;
392
393 assign b2x_last = (bank_st == `BANK_IDLE) ? r2b_last : l_last;
394
395 assign b2x_id = (bank_st == `BANK_IDLE) ? r2b_req_id : l_id;
396
397 assign b2x_len = (bank_st == `BANK_IDLE) ? r2b_len : l_len;
398
399 assign b2x_wrap = (bank_st == `BANK_IDLE) ? r2b_wrap : l_wrap;
400
401 endmodule // sdr_bank_fsm