OpenCores
URL https://opencores.org/ocsvn/sdr_ctrl/sdr_ctrl/trunk

Subversion Repositories sdr_ctrl

[/] [sdr_ctrl/] [trunk/] [rtl/] [core/] [sdrc_req_gen.v] - Blame information for rev 73

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.