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

Subversion Repositories sdr_ctrl

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /sdr_ctrl
    from Rev 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

/trunk/rtl/core/sdrc_bank_fsm.v
0,0 → 1,323
/*********************************************************************
SDRAM Controller Bank Controller
This file is part of the sdram controller project
http://www.opencores.org/cores/sdr_ctrl/
Description:
This module takes requests from sdrc_req_gen, checks for page hit/miss and
issues precharge/activate commands and then passes the request to sdrc_xfr_ctl.
To Do:
nothing
Author(s):
- Dinesh Annayya, dinesha@opencores.org
Version : 1.0 - 8th Jan 2012
 
Copyright (C) 2000 Authors and OPENCORES.ORG
This source file may be used and distributed without
restriction provided that this copyright statement is not
removed from the file and that any derivative work contains
the original copyright notice and the associated disclaimer.
This source file is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any
later version.
This source is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General
Public License along with this source; if not, download it
from http://www.opencores.org/lgpl.shtml
*******************************************************************/
 
 
`include "sdrc.def"
 
module sdrc_bank_fsm (clk,
reset_n,
 
/* Req from req_gen */
r2b_req, // request
r2b_req_id, // ID
r2b_start, // First chunk of burst
r2b_last, // Last chunk of burst
r2b_wrap,
r2b_raddr, // row address
r2b_caddr, // col address
r2b_len, // length
r2b_write, // write request
b2r_ack,
sdr_dma_last,
 
/* Transfer request to xfr_ctl */
b2x_req, // Request to xfr_ctl
b2x_start, // first chunk of transfer
b2x_last, // last chunk of transfer
b2x_wrap,
b2x_id, // Transfer ID
b2x_addr, // row/col address
b2x_len, // transfer length
b2x_cmd, // transfer command
x2b_ack, // command accepted
/* Status to/from xfr_ctl */
tras_ok, // TRAS OK for this bank
xfr_ok,
x2b_refresh, // We did a refresh
x2b_pre_ok, // OK to do a precharge (per bank)
x2b_act_ok, // OK to do an activate
x2b_rdok, // OK to do a read
x2b_wrok, // OK to do a write
 
/* current xfr row address of the bank */
bank_row,
 
/* SDRAM Timing */
tras_delay, // Active to precharge delay
trp_delay, // Precharge to active delay
trcd_delay); // Active to R/W delay
parameter APP_AW = 30; // Application Address Width
parameter APP_DW = 32; // Application Data Width
parameter APP_BW = 4; // Application Byte Width
parameter APP_RW = 9; // Application Request Width
 
parameter SDR_DW = 16; // SDR Data Width
parameter SDR_BW = 2; // SDR Byte Width
input clk, reset_n;
 
/* Req from bank_ctl */
input r2b_req, r2b_start, r2b_last,
r2b_write, r2b_wrap;
input [`SDR_REQ_ID_W-1:0] r2b_req_id;
input [11:0] r2b_raddr;
input [11:0] r2b_caddr;
input [APP_RW-1:0] r2b_len;
output b2r_ack;
input sdr_dma_last;
 
/* Req to xfr_ctl */
output b2x_req, b2x_start, b2x_last,
tras_ok, b2x_wrap;
output [`SDR_REQ_ID_W-1:0] b2x_id;
output [11:0] b2x_addr;
output [APP_RW-1:0] b2x_len;
output [1:0] b2x_cmd;
input x2b_ack;
 
/* Status from xfr_ctl */
input x2b_refresh, x2b_act_ok, x2b_rdok,
x2b_wrok, x2b_pre_ok, xfr_ok;
input [3:0] tras_delay, trp_delay, trcd_delay;
 
output [11:0] bank_row;
 
/****************************************************************************/
// Internal Nets
 
`define BANK_IDLE 3'b000
`define BANK_PRE 3'b001
`define BANK_ACT 3'b010
`define BANK_XFR 3'b011
`define BANK_DMA_LAST_PRE 3'b100
 
reg [2:0] bank_st, next_bank_st;
wire b2x_start, b2x_last;
reg l_start, l_last;
reg b2x_req, b2r_ack;
wire [`SDR_REQ_ID_W-1:0] b2x_id;
reg [`SDR_REQ_ID_W-1:0] l_id;
reg [11:0] b2x_addr;
reg [APP_RW-1:0] l_len;
wire [APP_RW-1:0] b2x_len;
reg [1:0] b2x_cmd;
reg bank_valid;
reg [11:0] bank_row;
reg [3:0] tras_cntr, timer0;
reg l_wrap, l_write;
wire b2x_wrap;
reg [11:0] l_raddr;
reg [11:0] l_caddr;
reg l_sdr_dma_last;
reg bank_prech_page_closed;
wire tras_ok_internal, tras_ok, activate_bank;
wire page_hit, timer0_tc, ld_trp, ld_trcd;
 
always @ (posedge clk)
if (~reset_n) begin
bank_valid <= 1'b0;
tras_cntr <= 4'b0;
timer0 <= 4'b0;
bank_st <= `BANK_IDLE;
end // if (~reset_n)
 
else begin
 
bank_valid <= (x2b_refresh || bank_prech_page_closed) ? 1'b0 : // force the bank status to be invalid
// bank_valid <= (x2b_refresh) ? 1'b0 :
(activate_bank) ? 1'b1 : bank_valid;
 
tras_cntr <= (activate_bank) ? tras_delay :
(~tras_ok_internal) ? tras_cntr - 4'b1 : 4'b0;
timer0 <= (ld_trp) ? trp_delay :
(ld_trcd) ? trcd_delay :
(~timer0_tc) ? timer0 - 4'b1 : timer0;
bank_st <= next_bank_st;
 
end // else: !if(~reset_n)
 
always @ (posedge clk) begin
 
bank_row <= (activate_bank) ? b2x_addr : bank_row;
 
if (~reset_n) begin
l_start <= 1'b0;
l_last <= 1'b0;
l_id <= 1'b0;
l_len <= 1'b0;
l_wrap <= 1'b0;
l_write <= 1'b0;
l_raddr <= 1'b0;
l_caddr <= 1'b0;
l_sdr_dma_last <= 1'b0;
end
else begin
if (b2r_ack) begin
l_start <= r2b_start;
l_last <= r2b_last;
l_id <= r2b_req_id;
l_len <= r2b_len;
l_wrap <= r2b_wrap;
l_write <= r2b_write;
l_raddr <= r2b_raddr;
l_caddr <= r2b_caddr;
l_sdr_dma_last <= sdr_dma_last;
end // if (b2r_ack)
end
 
end // always @ (posedge clk)
assign tras_ok_internal = ~|tras_cntr;
assign tras_ok = tras_ok_internal;
 
assign activate_bank = (b2x_cmd == `OP_ACT) & x2b_ack;
 
assign page_hit = (r2b_raddr == bank_row) ? bank_valid : 1'b0; // its a hit only if bank is valid
 
assign timer0_tc = ~|timer0;
 
assign ld_trp = (b2x_cmd == `OP_PRE) ? x2b_ack : 1'b0;
 
assign ld_trcd = (b2x_cmd == `OP_ACT) ? x2b_ack : 1'b0;
always @ (*) begin
 
bank_prech_page_closed = 1'b0;
b2x_req = 1'b0;
b2x_cmd = 2'bx;
b2r_ack = 1'b0;
b2x_addr = 12'bx;
next_bank_st = bank_st;
 
case (bank_st)
 
`BANK_IDLE : begin
 
if (~r2b_req) begin
bank_prech_page_closed = 1'b0;
b2x_req = 1'b0;
b2x_cmd = 2'bx;
b2r_ack = 1'b0;
b2x_addr = 12'bx;
next_bank_st = `BANK_IDLE;
end // if (~r2b_req)
else if (page_hit) begin
b2x_req = (r2b_write) ? x2b_wrok & xfr_ok :
x2b_rdok & xfr_ok;
b2x_cmd = (r2b_write) ? `OP_WR : `OP_RD;
b2r_ack = 1'b1;
b2x_addr = r2b_caddr;
next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_XFR; // in case of hit, stay here till xfr sm acks
end // if (page_hit)
else begin // page_miss
b2x_req = tras_ok_internal & x2b_pre_ok;
b2x_cmd = `OP_PRE;
b2r_ack = 1'b1;
b2x_addr = r2b_raddr & 12'hBFF; // Dont want to pre all banks!
next_bank_st = (l_sdr_dma_last) ? `BANK_PRE : (x2b_ack) ? `BANK_ACT : `BANK_PRE; // bank was precharged on l_sdr_dma_last
end // else: !if(page_hit)
 
end // case: `BANK_IDLE
 
`BANK_PRE : begin
b2x_req = tras_ok_internal & x2b_pre_ok;
b2x_cmd = `OP_PRE;
b2r_ack = 1'b0;
b2x_addr = l_raddr & 12'hBFF; // Dont want to pre all banks!
bank_prech_page_closed = 1'b0;
next_bank_st = (x2b_ack) ? `BANK_ACT : `BANK_PRE;
end // case: `BANK_PRE
 
`BANK_ACT : begin
b2x_req = timer0_tc & x2b_act_ok;
b2x_cmd = `OP_ACT;
b2r_ack = 1'b0;
b2x_addr = l_raddr;
bank_prech_page_closed = 1'b0;
next_bank_st = (x2b_ack) ? `BANK_XFR : `BANK_ACT;
end // case: `BANK_ACT
`BANK_XFR : begin
b2x_req = (l_write) ? timer0_tc & x2b_wrok & xfr_ok :
timer0_tc & x2b_rdok & xfr_ok;
b2x_cmd = (l_write) ? `OP_WR : `OP_RD;
b2r_ack = 1'b0;
b2x_addr = l_caddr;
bank_prech_page_closed = 1'b0;
next_bank_st = (x2b_refresh) ? `BANK_ACT :
(x2b_ack & l_sdr_dma_last) ? `BANK_DMA_LAST_PRE :
(x2b_ack) ? `BANK_IDLE : `BANK_XFR;
end // case: `BANK_XFR
 
`BANK_DMA_LAST_PRE : begin
b2x_req = tras_ok_internal & x2b_pre_ok;
b2x_cmd = `OP_PRE;
b2r_ack = 1'b0;
b2x_addr = l_raddr & 12'hBFF; // Dont want to pre all banks!
bank_prech_page_closed = 1'b1;
next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_DMA_LAST_PRE;
end // case: `BANK_DMA_LAST_PRE
endcase // case(bank_st)
 
end // always @ (bank_st or ...)
 
assign b2x_start = (bank_st == `BANK_IDLE) ? r2b_start : l_start;
 
assign b2x_last = (bank_st == `BANK_IDLE) ? r2b_last : l_last;
 
assign b2x_id = (bank_st == `BANK_IDLE) ? r2b_req_id : l_id;
 
assign b2x_len = (bank_st == `BANK_IDLE) ? r2b_len : l_len;
 
assign b2x_wrap = (bank_st == `BANK_IDLE) ? r2b_wrap : l_wrap;
endmodule // sdr_bank_fsm
trunk/rtl/core/sdrc_bank_fsm.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/rtl/core/sdrc_bs_convert.v =================================================================== --- trunk/rtl/core/sdrc_bs_convert.v (revision 3) +++ trunk/rtl/core/sdrc_bs_convert.v (revision 4) @@ -54,8 +54,8 @@ app_req_addr_int, app_req_len, app_req_len_int, - app_req, - app_req_int, + app_sdr_req, + app_sdr_req_int, app_req_dma_last, app_req_dma_last_int, app_req_wr_n, @@ -91,8 +91,8 @@ input [APP_RW-1:0] app_req_len ; output [APP_RW-1:0] app_req_len_int; input app_req_wr_n; -input app_req; -output app_req_int; +input app_sdr_req; +output app_sdr_req_int; input app_req_dma_last; output app_req_dma_last_int; input app_req_ack_int; @@ -114,7 +114,7 @@ reg [APP_RW-1:0] app_req_len_int; reg app_req_dma_last_int; -reg app_req_int; +reg app_sdr_req_int; reg app_req_ack; reg [APP_DW-1:0] app_rd_data; @@ -152,7 +152,7 @@ app_wr_data_int = app_wr_data; app_wr_en_n_int = app_wr_en_n; app_req_dma_last_int = app_req_dma_last; - app_req_int = app_req; + app_sdr_req_int = app_sdr_req; app_wr_next = app_wr_next_int; app_rd_data = app_rd_data_int; app_rd_valid = app_rd_valid_int; @@ -164,7 +164,7 @@ app_req_addr_int = {app_req_addr,1'b0}; app_req_len_int = {app_req_len,1'b0}; app_req_dma_last_int = app_req_dma_last; - app_req_int = app_req && ok_to_req; + app_sdr_req_int = app_sdr_req && ok_to_req; app_req_ack = app_req_ack_int; app_wr_next = lcl_wr_next; app_rd_valid = lcl_rd_valid; @@ -209,7 +209,7 @@ end SDR16_WR_LO: begin - if(app_wr_next) + if(app_wr_next_int) begin upper_word = 1'b1; next_wr_state = SDR16_WR_HI;
/trunk/rtl/core/sdrc_core.v
67,8 → 67,8
`include "sdrc.def"
module sdrc_core
(
sdram_clk,
pad_sdram_clk,
clk,
pad_clk,
reset_n,
sdr_width,
 
129,8 → 129,8
//-----------------------------------------------
// Global Variable
// ----------------------------------------------
input sdram_clk ; // SDRAM Clock
input pad_sdram_clk ; // SDRAM Clock from Pad, used for registering Read Data
input clk ; // SDRAM Clock
input pad_clk ; // SDRAM Clock from Pad, used for registering Read Data
input reset_n ; // Reset Signal
input sdr_width ; // 0 - 32 Bit SDR, 1 - 16 Bit SDR
 
266,7 → 266,7
// if wrap=0, decodes the bank and passe the request to bank_ctl
 
sdrc_req_gen u_req_gen (
.clk (sdram_clk ),
.clk (clk ),
.reset_n (reset_n ),
.sdr_dev_config (cfg_sdr_dev_config ),
 
306,7 → 306,7
// sdr_xfr_ctl.
 
sdrc_bank_ctl u_bank_ctl (
.clk (sdram_clk ),
.clk (clk ),
.reset_n (reset_n ),
.a2b_req_depth (cfg_req_depth ),
365,7 → 365,7
// bank is not available.
 
sdrc_xfr_ctl u_xfr_ctl (
.clk (sdram_clk ),
.clk (clk ),
.reset_n (reset_n ),
/* Transfer request from bank_ctl */
410,7 → 410,7
.x2a_rdlast (xfr_rdlast ),
.x2a_wrlast (xfr_wrlast ),
.app_wrdt (add_wr_data_int ),
.app_wren_n (add_wr_en_n_int ),
.app_wren_n (app_wr_en_n_int ),
.x2a_wrnext (app_wr_next_int ),
.x2a_rddt (app_rd_data_int ),
.x2a_rdok (app_rd_valid_int ),
433,7 → 433,7
);
sdrc_bs_convert u_bs_convert (
.clk (sdram_clk ),
.clk (clk ),
.reset_n (reset_n ),
.sdr_width (sdr_width ),
 
446,7 → 446,7
.app_req_dma_last (app_req_dma_last ),
.app_req_dma_last_int(app_req_dma_last_int),
.app_req_wr_n (app_req_wr_n ),
.app_req_ack16 (app_req_ack_int ),
.app_req_ack_int (app_req_ack_int ),
.app_req_ack (app_req_ack ),
 
.app_wr_data (app_wr_data ),
/trunk/rtl/core/sdrc_bank_ctl.v
48,6 → 48,7
 
module sdrc_bank_ctl (clk,
reset_n,
a2b_req_depth, // Number of requests we can buffer
 
/* Req from req_gen */
r2b_req, // request
55,19 → 56,22
r2b_start, // First chunk of burst
r2b_last, // Last chunk of burst
r2b_wrap,
r2b_ba, // bank address
r2b_raddr, // row address
r2b_caddr, // col address
r2b_len, // length
r2b_write, // write request
b2r_arb_ok, // OK to arbitrate for next xfr
b2r_ack,
sdr_dma_last,
 
/* Transfer request to xfr_ctl */
b2x_idle, // All banks are idle
b2x_req, // Request to xfr_ctl
b2x_start, // first chunk of transfer
b2x_last, // last chunk of transfer
b2x_wrap,
b2x_id, // Transfer ID
b2x_ba, // bank address
b2x_addr, // row/col address
b2x_len, // transfer length
b2x_cmd, // transfer command
74,8 → 78,7
x2b_ack, // command accepted
/* Status to/from xfr_ctl */
tras_ok, // TRAS OK for this bank
xfr_ok,
b2x_tras_ok, // TRAS OK for all banks
x2b_refresh, // We did a refresh
x2b_pre_ok, // OK to do a precharge (per bank)
x2b_act_ok, // OK to do an activate
82,8 → 85,11
x2b_rdok, // OK to do a read
x2b_wrok, // OK to do a write
 
/* current xfr row address of the bank */
bank_row,
/* xfr msb address */
sdr_dev_config,
xfr_bank_sel,
xfr_addr_msb,
sdr_req_norm_dma_last,
 
/* SDRAM Timing */
tras_delay, // Active to precharge delay
99,20 → 105,24
parameter SDR_BW = 2; // SDR Byte Width
input clk, reset_n;
 
input [1:0] a2b_req_depth;
/* Req from bank_ctl */
input r2b_req, r2b_start, r2b_last,
r2b_write, r2b_wrap;
input [`SDR_REQ_ID_W-1:0] r2b_req_id;
input [1:0] r2b_ba;
input [11:0] r2b_raddr;
input [11:0] r2b_caddr;
input [APP_RW-1:0] r2b_len;
output b2r_ack;
input sdr_dma_last;
input [APP_RW-1:0] r2b_len;
output b2r_arb_ok, b2r_ack;
input sdr_req_norm_dma_last;
 
/* Req to xfr_ctl */
output b2x_req, b2x_start, b2x_last,
tras_ok, b2x_wrap;
output b2x_idle, b2x_req, b2x_start, b2x_last,
b2x_tras_ok, b2x_wrap;
output [`SDR_REQ_ID_W-1:0] b2x_id;
output [1:0] b2x_ba;
output [11:0] b2x_addr;
output [APP_RW-1:0] b2x_len;
output [1:0] b2x_cmd;
119,205 → 129,442
input x2b_ack;
 
/* Status from xfr_ctl */
input [3:0] x2b_pre_ok;
input x2b_refresh, x2b_act_ok, x2b_rdok,
x2b_wrok, x2b_pre_ok, xfr_ok;
x2b_wrok;
input [3:0] tras_delay, trp_delay, trcd_delay;
 
output [11:0] bank_row;
input [1:0] sdr_dev_config;
input [1:0] xfr_bank_sel;
output [13:0] xfr_addr_msb;
 
/****************************************************************************/
// Internal Nets
 
`define BANK_IDLE 3'b000
`define BANK_PRE 3'b001
`define BANK_ACT 3'b010
`define BANK_XFR 3'b011
`define BANK_DMA_LAST_PRE 3'b100
wire [3:0] r2i_req, i2r_ack, i2x_req,
i2x_start, i2x_last, i2x_wrap, tras_ok;
wire [11:0] i2x_addr0, i2x_addr1, i2x_addr2, i2x_addr3;
wire [APP_RW-1:0] i2x_len0, i2x_len1, i2x_len2, i2x_len3;
wire [1:0] i2x_cmd0, i2x_cmd1, i2x_cmd2, i2x_cmd3;
wire [`SDR_REQ_ID_W-1:0] i2x_id0, i2x_id1, i2x_id2, i2x_id3;
 
reg [2:0] bank_st, next_bank_st;
wire b2x_start, b2x_last;
reg l_start, l_last;
reg b2x_req, b2r_ack;
reg b2x_req;
wire b2x_idle, b2x_start, b2x_last, b2x_wrap;
wire [`SDR_REQ_ID_W-1:0] b2x_id;
reg [`SDR_REQ_ID_W-1:0] l_id;
reg [11:0] b2x_addr;
reg [APP_RW-1:0] l_len;
wire [11:0] b2x_addr;
wire [APP_RW-1:0] b2x_len;
reg [1:0] b2x_cmd;
reg bank_valid;
reg [11:0] bank_row;
reg [3:0] tras_cntr, timer0;
reg l_wrap, l_write;
wire b2x_wrap;
reg [11:0] l_raddr;
reg [11:0] l_caddr;
reg l_sdr_dma_last;
reg bank_prech_page_closed;
wire [1:0] b2x_cmd;
wire [3:0] x2i_ack;
reg [1:0] b2x_ba;
wire tras_ok_internal, tras_ok, activate_bank;
reg [`SDR_REQ_ID_W-1:0] curr_id;
 
wire [1:0] xfr_ba;
wire xfr_ba_last;
wire [3:0] xfr_ok;
 
// This 8 bit register stores the bank addresses for upto 4 requests.
reg [7:0] rank_ba;
reg [3:0] rank_ba_last;
// This 3 bit counter counts the number of requests we have
// buffered so far, legal values are 0, 1, 2, 3, or 4.
reg [2:0] rank_cnt;
wire [3:0] rank_req, rank_wr_sel;
wire rank_fifo_wr, rank_fifo_rd;
wire rank_fifo_full, rank_fifo_mt;
wire page_hit, timer0_tc, ld_trp, ld_trcd;
wire [11:0] bank0_row, bank1_row, bank2_row, bank3_row;
 
assign b2x_tras_ok = &tras_ok;
 
// Distribute the request from req_gen
 
assign r2i_req[0] = (r2b_ba == 2'b00) ? r2b_req & ~rank_fifo_full : 1'b0;
assign r2i_req[1] = (r2b_ba == 2'b01) ? r2b_req & ~rank_fifo_full : 1'b0;
assign r2i_req[2] = (r2b_ba == 2'b10) ? r2b_req & ~rank_fifo_full : 1'b0;
assign r2i_req[3] = (r2b_ba == 2'b11) ? r2b_req & ~rank_fifo_full : 1'b0;
 
assign b2r_ack = (r2b_ba == 2'b00) ? i2r_ack[0] :
(r2b_ba == 2'b01) ? i2r_ack[1] :
(r2b_ba == 2'b10) ? i2r_ack[2] :
(r2b_ba == 2'b11) ? i2r_ack[3] : 1'b0;
 
assign b2r_arb_ok = ~rank_fifo_full;
// Put the requests from the 4 bank_fsms into a 4 deep shift
// register file. The earliest request is prioritized over the
// later requests. Also the number of requests we are allowed to
// buffer is limited by a 2 bit external input
// Mux the req/cmd to xfr_ctl. Allow RD/WR commands from the request in
// rank0, allow only PR/ACT commands from the requests in other ranks
// If the rank_fifo is empty, send the request from the bank addressed by
// r2b_ba
 
assign xfr_ba = (rank_fifo_mt) ? r2b_ba : rank_ba[1:0];
assign xfr_ba_last = (rank_fifo_mt) ? sdr_req_norm_dma_last : rank_ba_last[0];
assign rank_req[0] = i2x_req[xfr_ba]; // each rank generates requests
assign rank_req[1] = (rank_cnt < 3'h2) ? 1'b0 :
(rank_ba[3:2] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] :
(rank_ba[3:2] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] :
(rank_ba[3:2] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] :
i2x_req[3] & ~i2x_cmd3[1];
assign rank_req[2] = (rank_cnt < 3'h3) ? 1'b0 :
(rank_ba[5:4] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] :
(rank_ba[5:4] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] :
(rank_ba[5:4] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] :
i2x_req[3] & ~i2x_cmd3[1];
assign rank_req[3] = (rank_cnt < 3'h4) ? 1'b0 :
(rank_ba[7:6] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] :
(rank_ba[7:6] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] :
(rank_ba[7:6] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] :
i2x_req[3] & ~i2x_cmd3[1];
always @ (rank_req or rank_ba or xfr_ba or xfr_ba_last) begin
 
if (rank_req[0]) begin
b2x_req = 1'b1;
b2x_ba = xfr_ba;
end // if (rank_req[0])
else if (rank_req[1]) begin
b2x_req = 1'b1;
b2x_ba = rank_ba[3:2];
end // if (rank_req[1])
else if (rank_req[2]) begin
b2x_req = 1'b1;
b2x_ba = rank_ba[5:4];
end // if (rank_req[2])
else if (rank_req[3]) begin
b2x_req = 1'b1;
b2x_ba = rank_ba[7:6];
end // if (rank_req[3])
else begin
b2x_req = 1'b0;
b2x_ba = 2'b00;
end // else: !if(rank_req[3])
end // always @ (rank_req or rank_fifo_mt or r2b_ba or rank_ba)
 
assign b2x_idle = rank_fifo_mt;
assign b2x_start = i2x_start[b2x_ba];
assign b2x_last = i2x_last[b2x_ba];
assign b2x_wrap = i2x_wrap[b2x_ba];
 
assign b2x_addr = (b2x_ba == 2'b11) ? i2x_addr3 :
(b2x_ba == 2'b10) ? i2x_addr2 :
(b2x_ba == 2'b01) ? i2x_addr1 : i2x_addr0;
assign b2x_len = (b2x_ba == 2'b11) ? i2x_len3 :
(b2x_ba == 2'b10) ? i2x_len2 :
(b2x_ba == 2'b01) ? i2x_len1 : i2x_len0;
assign b2x_cmd = (b2x_ba == 2'b11) ? i2x_cmd3 :
(b2x_ba == 2'b10) ? i2x_cmd2 :
(b2x_ba == 2'b01) ? i2x_cmd1 : i2x_cmd0;
assign b2x_id = (b2x_ba == 2'b11) ? i2x_id3 :
(b2x_ba == 2'b10) ? i2x_id2 :
(b2x_ba == 2'b01) ? i2x_id1 : i2x_id0;
assign x2i_ack[0] = (b2x_ba == 2'b00) ? x2b_ack : 1'b0;
assign x2i_ack[1] = (b2x_ba == 2'b01) ? x2b_ack : 1'b0;
assign x2i_ack[2] = (b2x_ba == 2'b10) ? x2b_ack : 1'b0;
assign x2i_ack[3] = (b2x_ba == 2'b11) ? x2b_ack : 1'b0;
 
// Rank Fifo
// On a write write to selected rank and increment rank_cnt
// On a read shift rank_ba right 2 bits and decrement rank_cnt
 
assign rank_fifo_wr = b2r_ack;
 
assign rank_fifo_rd = b2x_req & b2x_cmd[1] & x2b_ack;
assign rank_wr_sel[0] = (rank_cnt == 3'h0) ? rank_fifo_wr :
(rank_cnt == 3'h1) ? rank_fifo_wr & rank_fifo_rd :
1'b0;
 
assign rank_wr_sel[1] = (rank_cnt == 3'h1) ? rank_fifo_wr & ~rank_fifo_rd :
(rank_cnt == 3'h2) ? rank_fifo_wr & rank_fifo_rd :
1'b0;
 
assign rank_wr_sel[2] = (rank_cnt == 3'h2) ? rank_fifo_wr & ~rank_fifo_rd :
(rank_cnt == 3'h3) ? rank_fifo_wr & rank_fifo_rd :
1'b0;
 
assign rank_wr_sel[3] = (rank_cnt == 3'h3) ? rank_fifo_wr & ~rank_fifo_rd :
(rank_cnt == 3'h4) ? rank_fifo_wr & rank_fifo_rd :
1'b0;
 
assign rank_fifo_mt = (rank_cnt == 3'b0) ? 1'b1 : 1'b0;
 
assign rank_fifo_full = (rank_cnt[2]) ? 1'b1 :
(rank_cnt[1:0] == a2b_req_depth) ? 1'b1 : 1'b0;
 
// FIFO Check
 
// synopsys translate_off
 
always @ (posedge clk) begin
 
if (~rank_fifo_wr & rank_fifo_rd && rank_cnt == 3'h0) begin
$display ("%t: %m: ERROR!!! Read from empty Fifo", $time);
$stop;
end // if (rank_fifo_rd && rank_cnt == 3'h0)
 
if (rank_fifo_wr && ~rank_fifo_rd && rank_cnt == 3'h4) begin
$display ("%t: %m: ERROR!!! Write to full Fifo", $time);
$stop;
end // if (rank_fifo_wr && ~rank_fifo_rd && rank_cnt == 3'h4)
end // always @ (posedge clk)
// synopsys translate_on
always @ (posedge clk)
if (~reset_n) begin
bank_valid <= 1'b0;
tras_cntr <= 4'b0;
timer0 <= 4'b0;
bank_st <= `BANK_IDLE;
rank_cnt <= 3'b0;
rank_ba <= 8'b0;
rank_ba_last <= 4'b0;
 
end // if (~reset_n)
 
else begin
 
bank_valid <= (x2b_refresh || bank_prech_page_closed) ? 1'b0 : // force the bank status to be invalid
// bank_valid <= (x2b_refresh) ? 1'b0 :
(activate_bank) ? 1'b1 : bank_valid;
rank_cnt <= (rank_fifo_wr & ~rank_fifo_rd) ? rank_cnt + 3'b1 :
(~rank_fifo_wr & rank_fifo_rd) ? rank_cnt - 3'b1 :
rank_cnt;
 
tras_cntr <= (activate_bank) ? tras_delay :
(~tras_ok_internal) ? tras_cntr - 4'b1 : 4'b0;
rank_ba[1:0] <= (rank_wr_sel[0]) ? r2b_ba :
(rank_fifo_rd) ? rank_ba[3:2] : rank_ba[1:0];
timer0 <= (ld_trp) ? trp_delay :
(ld_trcd) ? trcd_delay :
(~timer0_tc) ? timer0 - 4'b1 : timer0;
rank_ba[3:2] <= (rank_wr_sel[1]) ? r2b_ba :
(rank_fifo_rd) ? rank_ba[5:4] : rank_ba[3:2];
bank_st <= next_bank_st;
rank_ba[5:4] <= (rank_wr_sel[2]) ? r2b_ba :
(rank_fifo_rd) ? rank_ba[7:6] : rank_ba[5:4];
rank_ba[7:6] <= (rank_wr_sel[3]) ? r2b_ba :
(rank_fifo_rd) ? 2'b00 : rank_ba[7:6];
 
end // else: !if(~reset_n)
rank_ba_last[0] <= (rank_wr_sel[0]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? rank_ba_last[1] : rank_ba_last[0];
 
always @ (posedge clk) begin
rank_ba_last[1] <= (rank_wr_sel[1]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? rank_ba_last[2] : rank_ba_last[1];
 
bank_row <= (activate_bank) ? b2x_addr : bank_row;
rank_ba_last[2] <= (rank_wr_sel[2]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? rank_ba_last[3] : rank_ba_last[2];
 
if (~reset_n) begin
l_start <= 1'b0;
l_last <= 1'b0;
l_id <= 1'b0;
l_len <= 1'b0;
l_wrap <= 1'b0;
l_write <= 1'b0;
l_raddr <= 1'b0;
l_caddr <= 1'b0;
l_sdr_dma_last <= 1'b0;
end
else begin
if (b2r_ack) begin
l_start <= r2b_start;
l_last <= r2b_last;
l_id <= r2b_req_id;
l_len <= r2b_len;
l_wrap <= r2b_wrap;
l_write <= r2b_write;
l_raddr <= r2b_raddr;
l_caddr <= r2b_caddr;
l_sdr_dma_last <= sdr_dma_last;
end // if (b2r_ack)
end
rank_ba_last[3] <= (rank_wr_sel[3]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? 1'b0 : rank_ba_last[3];
 
end // always @ (posedge clk)
end // else: !if(~reset_n)
assign tras_ok_internal = ~|tras_cntr;
assign tras_ok = tras_ok_internal;
assign xfr_ok[0] = (xfr_ba == 2'b00) ? 1'b1 : 1'b0;
assign xfr_ok[1] = (xfr_ba == 2'b01) ? 1'b1 : 1'b0;
assign xfr_ok[2] = (xfr_ba == 2'b10) ? 1'b1 : 1'b0;
assign xfr_ok[3] = (xfr_ba == 2'b11) ? 1'b1 : 1'b0;
/****************************************************************************/
// Instantiate Bank Ctl FSM 0
 
assign activate_bank = (b2x_cmd == `OP_ACT) & x2b_ack;
sdrc_bank_fsm bank0_fsm (.clk (clk),
.reset_n (reset_n),
 
assign page_hit = (r2b_raddr == bank_row) ? bank_valid : 1'b0; // its a hit only if bank is valid
/* Req from req_gen */
.r2b_req (r2i_req[0]),
.r2b_req_id (r2b_req_id),
.r2b_start (r2b_start),
.r2b_last (r2b_last),
.r2b_wrap (r2b_wrap),
.r2b_raddr (r2b_raddr),
.r2b_caddr (r2b_caddr),
.r2b_len (r2b_len),
.r2b_write (r2b_write),
.b2r_ack (i2r_ack[0]),
.sdr_dma_last(rank_ba_last[0]),
 
assign timer0_tc = ~|timer0;
/* Transfer request to xfr_ctl */
.b2x_req (i2x_req[0]),
.b2x_start (i2x_start[0]),
.b2x_last (i2x_last[0]),
.b2x_wrap (i2x_wrap[0]),
.b2x_id (i2x_id0),
.b2x_addr (i2x_addr0),
.b2x_len (i2x_len0),
.b2x_cmd (i2x_cmd0),
.x2b_ack (x2i_ack[0]),
/* Status to/from xfr_ctl */
.tras_ok (tras_ok[0]),
.xfr_ok (xfr_ok[0]),
.x2b_refresh (x2b_refresh),
.x2b_pre_ok (x2b_pre_ok[0]),
.x2b_act_ok (x2b_act_ok),
.x2b_rdok (x2b_rdok),
.x2b_wrok (x2b_wrok),
 
assign ld_trp = (b2x_cmd == `OP_PRE) ? x2b_ack : 1'b0;
.bank_row(bank0_row),
 
assign ld_trcd = (b2x_cmd == `OP_ACT) ? x2b_ack : 1'b0;
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
always @ (*) begin
/****************************************************************************/
// Instantiate Bank Ctl FSM 1
 
bank_prech_page_closed = 1'b0;
b2x_req = 1'b0;
b2x_cmd = 2'bx;
b2r_ack = 1'b0;
b2x_addr = 12'bx;
next_bank_st = bank_st;
sdrc_bank_fsm bank1_fsm (.clk (clk),
.reset_n (reset_n),
 
case (bank_st)
/* Req from req_gen */
.r2b_req (r2i_req[1]),
.r2b_req_id (r2b_req_id),
.r2b_start (r2b_start),
.r2b_last (r2b_last),
.r2b_wrap (r2b_wrap),
.r2b_raddr (r2b_raddr),
.r2b_caddr (r2b_caddr),
.r2b_len (r2b_len),
.r2b_write (r2b_write),
.b2r_ack (i2r_ack[1]),
.sdr_dma_last(rank_ba_last[1]),
 
`BANK_IDLE : begin
/* Transfer request to xfr_ctl */
.b2x_req (i2x_req[1]),
.b2x_start (i2x_start[1]),
.b2x_last (i2x_last[1]),
.b2x_wrap (i2x_wrap[1]),
.b2x_id (i2x_id1),
.b2x_addr (i2x_addr1),
.b2x_len (i2x_len1),
.b2x_cmd (i2x_cmd1),
.x2b_ack (x2i_ack[1]),
/* Status to/from xfr_ctl */
.tras_ok (tras_ok[1]),
.xfr_ok (xfr_ok[1]),
.x2b_refresh (x2b_refresh),
.x2b_pre_ok (x2b_pre_ok[1]),
.x2b_act_ok (x2b_act_ok),
.x2b_rdok (x2b_rdok),
.x2b_wrok (x2b_wrok),
 
if (~r2b_req) begin
bank_prech_page_closed = 1'b0;
b2x_req = 1'b0;
b2x_cmd = 2'bx;
b2r_ack = 1'b0;
b2x_addr = 12'bx;
next_bank_st = `BANK_IDLE;
end // if (~r2b_req)
else if (page_hit) begin
b2x_req = (r2b_write) ? x2b_wrok & xfr_ok :
x2b_rdok & xfr_ok;
b2x_cmd = (r2b_write) ? `OP_WR : `OP_RD;
b2r_ack = 1'b1;
b2x_addr = r2b_caddr;
next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_XFR; // in case of hit, stay here till xfr sm acks
end // if (page_hit)
else begin // page_miss
b2x_req = tras_ok_internal & x2b_pre_ok;
b2x_cmd = `OP_PRE;
b2r_ack = 1'b1;
b2x_addr = r2b_raddr & 12'hBFF; // Dont want to pre all banks!
next_bank_st = (l_sdr_dma_last) ? `BANK_PRE : (x2b_ack) ? `BANK_ACT : `BANK_PRE; // bank was precharged on l_sdr_dma_last
end // else: !if(page_hit)
.bank_row(bank1_row),
 
end // case: `BANK_IDLE
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
/****************************************************************************/
// Instantiate Bank Ctl FSM 2
 
`BANK_PRE : begin
b2x_req = tras_ok_internal & x2b_pre_ok;
b2x_cmd = `OP_PRE;
b2r_ack = 1'b0;
b2x_addr = l_raddr & 12'hBFF; // Dont want to pre all banks!
bank_prech_page_closed = 1'b0;
next_bank_st = (x2b_ack) ? `BANK_ACT : `BANK_PRE;
end // case: `BANK_PRE
sdrc_bank_fsm bank2_fsm (.clk (clk),
.reset_n (reset_n),
 
`BANK_ACT : begin
b2x_req = timer0_tc & x2b_act_ok;
b2x_cmd = `OP_ACT;
b2r_ack = 1'b0;
b2x_addr = l_raddr;
bank_prech_page_closed = 1'b0;
next_bank_st = (x2b_ack) ? `BANK_XFR : `BANK_ACT;
end // case: `BANK_ACT
`BANK_XFR : begin
b2x_req = (l_write) ? timer0_tc & x2b_wrok & xfr_ok :
timer0_tc & x2b_rdok & xfr_ok;
b2x_cmd = (l_write) ? `OP_WR : `OP_RD;
b2r_ack = 1'b0;
b2x_addr = l_caddr;
bank_prech_page_closed = 1'b0;
next_bank_st = (x2b_refresh) ? `BANK_ACT :
(x2b_ack & l_sdr_dma_last) ? `BANK_DMA_LAST_PRE :
(x2b_ack) ? `BANK_IDLE : `BANK_XFR;
end // case: `BANK_XFR
/* Req from req_gen */
.r2b_req (r2i_req[2]),
.r2b_req_id (r2b_req_id),
.r2b_start (r2b_start),
.r2b_last (r2b_last),
.r2b_wrap (r2b_wrap),
.r2b_raddr (r2b_raddr),
.r2b_caddr (r2b_caddr),
.r2b_len (r2b_len),
.r2b_write (r2b_write),
.b2r_ack (i2r_ack[2]),
.sdr_dma_last(rank_ba_last[2]),
 
`BANK_DMA_LAST_PRE : begin
b2x_req = tras_ok_internal & x2b_pre_ok;
b2x_cmd = `OP_PRE;
b2r_ack = 1'b0;
b2x_addr = l_raddr & 12'hBFF; // Dont want to pre all banks!
bank_prech_page_closed = 1'b1;
next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_DMA_LAST_PRE;
end // case: `BANK_DMA_LAST_PRE
endcase // case(bank_st)
/* Transfer request to xfr_ctl */
.b2x_req (i2x_req[2]),
.b2x_start (i2x_start[2]),
.b2x_last (i2x_last[2]),
.b2x_wrap (i2x_wrap[2]),
.b2x_id (i2x_id2),
.b2x_addr (i2x_addr2),
.b2x_len (i2x_len2),
.b2x_cmd (i2x_cmd2),
.x2b_ack (x2i_ack[2]),
/* Status to/from xfr_ctl */
.tras_ok (tras_ok[2]),
.xfr_ok (xfr_ok[2]),
.x2b_refresh (x2b_refresh),
.x2b_pre_ok (x2b_pre_ok[2]),
.x2b_act_ok (x2b_act_ok),
.x2b_rdok (x2b_rdok),
.x2b_wrok (x2b_wrok),
 
end // always @ (bank_st or ...)
.bank_row(bank2_row),
 
assign b2x_start = (bank_st == `BANK_IDLE) ? r2b_start : l_start;
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
/****************************************************************************/
// Instantiate Bank Ctl FSM 3
 
assign b2x_last = (bank_st == `BANK_IDLE) ? r2b_last : l_last;
sdrc_bank_fsm bank3_fsm (.clk (clk),
.reset_n (reset_n),
 
assign b2x_id = (bank_st == `BANK_IDLE) ? r2b_req_id : l_id;
/* Req from req_gen */
.r2b_req (r2i_req[3]),
.r2b_req_id (r2b_req_id),
.r2b_start (r2b_start),
.r2b_last (r2b_last),
.r2b_wrap (r2b_wrap),
.r2b_raddr (r2b_raddr),
.r2b_caddr (r2b_caddr),
.r2b_len (r2b_len),
.r2b_write (r2b_write),
.b2r_ack (i2r_ack[3]),
.sdr_dma_last(rank_ba_last[3]),
 
assign b2x_len = (bank_st == `BANK_IDLE) ? r2b_len : l_len;
/* Transfer request to xfr_ctl */
.b2x_req (i2x_req[3]),
.b2x_start (i2x_start[3]),
.b2x_last (i2x_last[3]),
.b2x_wrap (i2x_wrap[3]),
.b2x_id (i2x_id3),
.b2x_addr (i2x_addr3),
.b2x_len (i2x_len3),
.b2x_cmd (i2x_cmd3),
.x2b_ack (x2i_ack[3]),
/* Status to/from xfr_ctl */
.tras_ok (tras_ok[3]),
.xfr_ok (xfr_ok[3]),
.x2b_refresh (x2b_refresh),
.x2b_pre_ok (x2b_pre_ok[3]),
.x2b_act_ok (x2b_act_ok),
.x2b_rdok (x2b_rdok),
.x2b_wrok (x2b_wrok),
 
assign b2x_wrap = (bank_st == `BANK_IDLE) ? r2b_wrap : l_wrap;
.bank_row(bank3_row),
 
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
endmodule // sdr_bank_fsm
 
/* address for current xfr, debug only */
wire [11:0] cur_row = (xfr_bank_sel==3) ? bank3_row:
(xfr_bank_sel==2) ? bank2_row:
(xfr_bank_sel==1) ? bank1_row: bank0_row;
 
assign xfr_addr_msb = (sdr_dev_config == 2'b11) ? {cur_row, xfr_bank_sel[1:0]}:
{cur_row, xfr_bank_sel[0]};
 
endmodule // sdr_bank_ctl

powered by: WebSVN 2.1.0

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