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

Subversion Repositories yifive

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /yifive/trunk
    from Rev 18 to Rev 19
    Reverse comparison

Rev 18 → Rev 19

/caravel_yifive/verilog/rtl/lib/async_fifo.sv
0,0 → 1,323
/*********************************************************************
ASYNC FIFO
This file is part of the sdram controller project
http://www.opencores.org/cores/sdr_ctrl/
Description: ASYNC FIFO
To Do:
nothing
Author(s): Dinesh Annayya, dinesha@opencores.org
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
*******************************************************************/
 
//-------------------------------------------
// async FIFO
//-----------------------------------------------
//`timescale 1ns/1ps
 
module async_fifo (wr_clk,
wr_reset_n,
wr_en,
wr_data,
full, // sync'ed to wr_clk
afull, // sync'ed to wr_clk
rd_clk,
rd_reset_n,
rd_en,
empty, // sync'ed to rd_clk
aempty, // sync'ed to rd_clk
rd_data);
 
parameter W = 4'd8;
parameter DP = 3'd4;
parameter WR_FAST = 1'b1;
parameter RD_FAST = 1'b1;
parameter FULL_DP = DP;
parameter EMPTY_DP = 1'b0;
 
parameter AW = (DP == 2) ? 1 :
(DP == 4) ? 2 :
(DP == 8) ? 3 :
(DP == 16) ? 4 :
(DP == 32) ? 5 :
(DP == 64) ? 6 :
(DP == 128) ? 7 :
(DP == 256) ? 8 : 0;
 
output [W-1 : 0] rd_data;
input [W-1 : 0] wr_data;
input wr_clk, wr_reset_n, wr_en, rd_clk, rd_reset_n,
rd_en;
output full, empty;
output afull, aempty; // about full and about to empty
 
 
// synopsys translate_off
 
initial begin
if (AW == 0) begin
$display ("%m : ERROR!!! Fifo depth %d not in range 2 to 256", DP);
end // if (AW == 0)
end // initial begin
 
// synopsys translate_on
 
reg [W-1 : 0] mem[DP-1 : 0];
 
/*********************** write side ************************/
reg [AW:0] sync_rd_ptr_0, sync_rd_ptr_1;
wire [AW:0] sync_rd_ptr;
reg [AW:0] wr_ptr, grey_wr_ptr;
reg [AW:0] grey_rd_ptr;
reg full_q;
wire full_c;
wire afull_c;
wire [AW:0] wr_ptr_inc = wr_ptr + 1'b1;
wire [AW:0] wr_cnt = get_cnt(wr_ptr, sync_rd_ptr);
 
assign full_c = (wr_cnt == FULL_DP) ? 1'b1 : 1'b0;
assign afull_c = (wr_cnt == FULL_DP-1) ? 1'b1 : 1'b0;
 
 
always @(posedge wr_clk or negedge wr_reset_n) begin
if (!wr_reset_n) begin
wr_ptr <= 0;
grey_wr_ptr <= 0;
full_q <= 0;
end
else if (wr_en) begin
wr_ptr <= wr_ptr_inc;
grey_wr_ptr <= bin2grey(wr_ptr_inc);
if (wr_cnt == (FULL_DP-1)) begin
full_q <= 1'b1;
end
end
else begin
if (full_q && (wr_cnt<FULL_DP)) begin
full_q <= 1'b0;
end
end
end
 
assign full = (WR_FAST == 1) ? full_c : full_q;
assign afull = afull_c;
 
always @(posedge wr_clk) begin
if (wr_en) begin
mem[wr_ptr[AW-1:0]] <= wr_data;
end
end
 
wire [AW:0] grey_rd_ptr_dly ;
assign #1 grey_rd_ptr_dly = grey_rd_ptr;
 
// read pointer synchronizer
always @(posedge wr_clk or negedge wr_reset_n) begin
if (!wr_reset_n) begin
sync_rd_ptr_0 <= 0;
sync_rd_ptr_1 <= 0;
end
else begin
sync_rd_ptr_0 <= grey_rd_ptr_dly;
sync_rd_ptr_1 <= sync_rd_ptr_0;
end
end
 
assign sync_rd_ptr = grey2bin(sync_rd_ptr_1);
 
/************************ read side *****************************/
reg [AW:0] sync_wr_ptr_0, sync_wr_ptr_1;
wire [AW:0] sync_wr_ptr;
reg [AW:0] rd_ptr;
reg empty_q;
wire empty_c;
wire aempty_c;
wire [AW:0] rd_ptr_inc = rd_ptr + 1'b1;
wire [AW:0] sync_wr_ptr_dec = sync_wr_ptr - 1'b1;
wire [AW:0] rd_cnt = get_cnt(sync_wr_ptr, rd_ptr);
assign empty_c = (rd_cnt == 0) ? 1'b1 : 1'b0;
assign aempty_c = (rd_cnt == 1) ? 1'b1 : 1'b0;
 
always @(posedge rd_clk or negedge rd_reset_n) begin
if (!rd_reset_n) begin
rd_ptr <= 0;
grey_rd_ptr <= 0;
empty_q <= 1'b1;
end
else begin
if (rd_en) begin
rd_ptr <= rd_ptr_inc;
grey_rd_ptr <= bin2grey(rd_ptr_inc);
if (rd_cnt==(EMPTY_DP+1)) begin
empty_q <= 1'b1;
end
end
else begin
if (empty_q && (rd_cnt!=EMPTY_DP)) begin
empty_q <= 1'b0;
end
end
end
end
 
assign empty = (RD_FAST == 1) ? empty_c : empty_q;
assign aempty = aempty_c;
 
reg [W-1 : 0] rd_data_q;
 
wire [W-1 : 0] rd_data_c = mem[rd_ptr[AW-1:0]];
always @(posedge rd_clk) begin
rd_data_q <= rd_data_c;
end
assign rd_data = (RD_FAST == 1) ? rd_data_c : rd_data_q;
 
wire [AW:0] grey_wr_ptr_dly ;
assign #1 grey_wr_ptr_dly = grey_wr_ptr;
 
// write pointer synchronizer
always @(posedge rd_clk or negedge rd_reset_n) begin
if (!rd_reset_n) begin
sync_wr_ptr_0 <= 0;
sync_wr_ptr_1 <= 0;
end
else begin
sync_wr_ptr_0 <= grey_wr_ptr_dly;
sync_wr_ptr_1 <= sync_wr_ptr_0;
end
end
assign sync_wr_ptr = grey2bin(sync_wr_ptr_1);
 
/************************ functions ******************************/
function [AW:0] bin2grey;
input [AW:0] bin;
reg [8:0] bin_8;
reg [8:0] grey_8;
begin
bin_8 = bin;
grey_8[1:0] = do_grey(bin_8[2:0]);
grey_8[3:2] = do_grey(bin_8[4:2]);
grey_8[5:4] = do_grey(bin_8[6:4]);
grey_8[7:6] = do_grey(bin_8[8:6]);
grey_8[8] = bin_8[8];
bin2grey = grey_8;
end
endfunction
 
function [AW:0] grey2bin;
input [AW:0] grey;
reg [8:0] grey_8;
reg [8:0] bin_8;
begin
grey_8 = grey;
bin_8[8] = grey_8[8];
bin_8[7:6] = do_bin({bin_8[8], grey_8[7:6]});
bin_8[5:4] = do_bin({bin_8[6], grey_8[5:4]});
bin_8[3:2] = do_bin({bin_8[4], grey_8[3:2]});
bin_8[1:0] = do_bin({bin_8[2], grey_8[1:0]});
grey2bin = bin_8;
end
endfunction
 
 
function [1:0] do_grey;
input [2:0] bin;
begin
if (bin[2]) begin // do reverse grey
case (bin[1:0])
2'b00: do_grey = 2'b10;
2'b01: do_grey = 2'b11;
2'b10: do_grey = 2'b01;
2'b11: do_grey = 2'b00;
endcase
end
else begin
case (bin[1:0])
2'b00: do_grey = 2'b00;
2'b01: do_grey = 2'b01;
2'b10: do_grey = 2'b11;
2'b11: do_grey = 2'b10;
endcase
end
end
endfunction
 
function [1:0] do_bin;
input [2:0] grey;
begin
if (grey[2]) begin // actually bin[2]
case (grey[1:0])
2'b10: do_bin = 2'b00;
2'b11: do_bin = 2'b01;
2'b01: do_bin = 2'b10;
2'b00: do_bin = 2'b11;
endcase
end
else begin
case (grey[1:0])
2'b00: do_bin = 2'b00;
2'b01: do_bin = 2'b01;
2'b11: do_bin = 2'b10;
2'b10: do_bin = 2'b11;
endcase
end
end
endfunction
function [AW:0] get_cnt;
input [AW:0] wr_ptr, rd_ptr;
begin
if (wr_ptr >= rd_ptr) begin
get_cnt = (wr_ptr - rd_ptr);
end
else begin
get_cnt = DP*2 - (rd_ptr - wr_ptr);
end
end
endfunction
 
// synopsys translate_off
always @(posedge wr_clk) begin
if (wr_en && full) begin
$display($time, "%m Error! afifo overflow!");
$stop;
end
end
 
always @(posedge rd_clk) begin
if (rd_en && empty) begin
$display($time, "%m error! afifo underflow!");
$stop;
end
end
// synopsys translate_on
 
endmodule
caravel_yifive/verilog/rtl/lib/async_fifo.sv Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/lib/sync_fifo.sv =================================================================== --- caravel_yifive/verilog/rtl/lib/sync_fifo.sv (revision 18) +++ caravel_yifive/verilog/rtl/lib/sync_fifo.sv (revision 19) @@ -1,142 +1,148 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// YiFive cores common library Module //// -//// //// -//// This file is part of the YIFive cores project //// -//// http://www.opencores.org/cores/yifive/ //// -//// //// -//// Description //// -//// Sync Fifo with full and empty //// -//// //// -//// To Do: //// -//// nothing //// -//// //// -//// Author(s): //// -//// - Dinesh Annayya, dinesha@opencores.org //// -//// //// -//// Revision : June 7, 2021 //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// 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 //// -//// //// -////////////////////////////////////////////////////////////////////// +/********************************************************************* + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SYNC FIFO + Parameters: + W : Width (integer) + D : Depth (integer, power of 2, 4 to 256) + + To Do: + nothing + + Author(s): Dinesh Annayya, dinesha@opencores.org + + 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 + +*******************************************************************/ -module sync_fifo #( - parameter DATA_WIDTH = 32, // Data Width - parameter ADDR_WIDTH = 1, // Address Width - parameter FIFO_DEPTH = 2 // FIFO DEPTH - -)( - output [DATA_WIDTH-1:0] dout, - input rstn, - input clk, - input wr_en, // Write - input rd_en, // Read - input [DATA_WIDTH-1:0] din, - output full, - output empty -); +module sync_fifo (clk, + reset_n, + wr_en, + wr_data, + full, + empty, + rd_en, + rd_data); -reg [DATA_WIDTH-1:0] ram [FIFO_DEPTH-1:0]; -reg [ADDR_WIDTH-1:0] wptr; // write ptr -reg [ADDR_WIDTH-1:0] rptr; // write ptr -reg [ADDR_WIDTH:0] status_cnt; // status counter -reg empty; -reg full; + parameter W = 8; + parameter D = 4; - - //-----------Code Start--------------------------- - always @ (negedge rstn or posedge clk) - begin : WRITE_POINTER - if (rstn==1'b0) begin - wptr <= 0; - end else if (wr_en ) begin - wptr <= wptr + 1; - end - end + parameter AW = (D == 4) ? 2 : + (D == 8) ? 3 : + (D == 16) ? 4 : + (D == 32) ? 5 : + (D == 64) ? 6 : + (D == 128) ? 7 : + (D == 256) ? 8 : 0; + + output [W-1 : 0] rd_data; + input [W-1 : 0] wr_data; + input clk, reset_n, wr_en, rd_en; + output full, empty; -always @ (negedge rstn or posedge clk) -begin : READ_POINTER - if (rstn==1'b0) begin - rptr <= 0; - end else if (rd_en) begin - rptr <= rptr + 1; - end -end + // synopsys translate_off -always @ (negedge rstn or posedge clk) -begin : STATUS_COUNTER - if (rstn==1'b0) begin - status_cnt <= 0; - // Read but no write. - end else if (rd_en && (!wr_en) && (status_cnt != 0)) begin - status_cnt <= status_cnt - 1; - // Write but no read. - end else if (wr_en && (!rd_en) && (status_cnt != FIFO_DEPTH)) begin - status_cnt <= status_cnt + 1; - end -end + initial begin + if (AW == 0) begin + $display ("%m : ERROR!!! Fifo depth %d not in range 4 to 256", D); + end // if (AW == 0) + end // initial begin -// underflow is not handled -always @ (negedge rstn or posedge clk) -begin : EMPTY_FLAG - if (rstn==1'b0) begin - empty <= 1; - // Read but no write. - end else if (rd_en && (!wr_en) && (status_cnt == 1)) begin - empty <= 1; - // Write - end else if (wr_en) begin - empty <= 0; - end else if (status_cnt == 0) begin - empty <= 1; - end -end + // synopsys translate_on -// overflow is not handled -always @ (negedge rstn or posedge clk) -begin : FULL_FLAG - if (rstn==1'b0) begin - full <= 0; - // Write but no read. - end else if (wr_en && (!rd_en) && (status_cnt == (FIFO_DEPTH-1))) begin - full <= 1; - // Read - end else if (rd_en && (!wr_en) ) begin - full <= 0; - end else if (status_cnt == FIFO_DEPTH) begin - full <= 1; - end -end -assign dout = ram[rptr]; -always @ (posedge clk) -begin - if (wr_en) ram[wptr] <= din; -end + reg [W-1 : 0] mem[D-1 : 0]; + reg [AW-1 : 0] rd_ptr, wr_ptr; + reg full, empty; + wire [W-1 : 0] rd_data; + + always @ (posedge clk or negedge reset_n) + if (reset_n == 1'b0) begin + wr_ptr <= {AW{1'b0}} ; + end + else begin + if (wr_en & !full) begin + wr_ptr <= wr_ptr + 1'b1 ; + end + end + always @ (posedge clk or negedge reset_n) + if (reset_n == 1'b0) begin + rd_ptr <= {AW{1'b0}} ; + end + else begin + if (rd_en & !empty) begin + rd_ptr <= rd_ptr + 1'b1 ; + end + end + + + always @ (posedge clk or negedge reset_n) + if (reset_n == 1'b0) begin + empty <= 1'b1 ; + end + else begin + empty <= (((wr_ptr - rd_ptr) == {{(AW-1){1'b0}}, 1'b1}) & rd_en & ~wr_en) ? 1'b1 : + ((wr_ptr == rd_ptr) & ~rd_en & wr_en) ? 1'b0 : empty ; + end + + always @ (posedge clk or negedge reset_n) + if (reset_n == 1'b0) begin + full <= 1'b0 ; + end + else begin + full <= (((wr_ptr - rd_ptr) == {{(AW-1){1'b1}}, 1'b0}) & ~rd_en & wr_en) ? 1'b1 : + (((wr_ptr - rd_ptr) == {AW{1'b1}}) & rd_en & ~wr_en) ? 1'b0 : full ; + end + + always @ (posedge clk) + if (wr_en) + mem[wr_ptr] <= wr_data; + +assign rd_data = mem[rd_ptr]; + + +// synopsys translate_off + always @(posedge clk) begin + if (wr_en && full) begin + $display("%m : Error! sfifo overflow!"); + end + end + + always @(posedge clk) begin + if (rd_en && empty) begin + $display("%m : error! sfifo underflow!"); + end + end + +// synopsys translate_on +//--------------------------------------- + endmodule + +
/caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_bank_ctl.v
0,0 → 1,571
/*********************************************************************
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_define.v"
 
module sdrc_bank_ctl (clk,
reset_n,
a2b_req_depth, // Number of requests we can buffer
 
/* 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_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,
 
/* 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
x2b_ack, // command accepted
/* Status to/from xfr_ctl */
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
x2b_rdok, // OK to do a read
x2b_wrok, // OK to do a write
 
/* xfr msb address */
xfr_bank_sel,
sdr_req_norm_dma_last,
 
/* SDRAM Timing */
tras_delay, // Active to precharge delay
trp_delay, // Precharge to active delay
trcd_delay); // Active to R/W delay
parameter SDR_DW = 16; // SDR Data Width
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 [12:0] r2b_raddr;
input [12:0] r2b_caddr;
input [`REQ_BW-1:0] r2b_len;
output b2r_arb_ok, b2r_ack;
input sdr_req_norm_dma_last;
 
/* Req to xfr_ctl */
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 [12:0] b2x_addr;
output [`REQ_BW-1:0] b2x_len;
output [1:0] b2x_cmd;
input x2b_ack;
 
/* Status from xfr_ctl */
input [3:0] x2b_pre_ok;
input x2b_refresh, x2b_act_ok, x2b_rdok,
x2b_wrok;
input [3:0] tras_delay, trp_delay, trcd_delay;
 
input [1:0] xfr_bank_sel;
 
/****************************************************************************/
// Internal Nets
 
wire [3:0] r2i_req, i2r_ack, i2x_req,
i2x_start, i2x_last, i2x_wrap, tras_ok;
wire [12:0] i2x_addr0, i2x_addr1, i2x_addr2, i2x_addr3;
wire [`REQ_BW-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 b2x_req;
wire b2x_idle, b2x_start, b2x_last, b2x_wrap;
wire [`SDR_REQ_ID_W-1:0] b2x_id;
wire [12:0] b2x_addr;
wire [`REQ_BW-1:0] b2x_len;
wire [1:0] b2x_cmd;
wire [3:0] x2i_ack;
reg [1:0] b2x_ba;
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 [12: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;
 
/******************
Modified the Better FPGA Timing Purpose
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;
********************/
// Assumption: Only one Ack Will be asserted at a time.
assign b2r_ack =|i2r_ack;
 
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
 
// In FPGA Mode, to improve the timing, also send the rank_ba
assign xfr_ba = (`TARGET_DESIGN == `FPGA) ? rank_ba[1:0]:
((rank_fifo_mt) ? r2b_ba : rank_ba[1:0]);
assign xfr_ba_last = (`TARGET_DESIGN == `FPGA) ? rank_ba_last[0]:
((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 @ (*) begin
b2x_req = 1'b0;
b2x_ba = xfr_ba;
 
if(`TARGET_DESIGN == `ASIC) begin // Support Multiple Rank request only on ASIC
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])
end else begin // If FPGA
if (rank_req[0]) begin
b2x_req = 1'b1;
end
end
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
rank_cnt <= 3'b0;
rank_ba <= 8'b0;
rank_ba_last <= 4'b0;
 
end // if (~reset_n)
else begin
 
rank_cnt <= (rank_fifo_wr & ~rank_fifo_rd) ? rank_cnt + 3'b1 :
(~rank_fifo_wr & rank_fifo_rd) ? rank_cnt - 3'b1 :
rank_cnt;
 
rank_ba[1:0] <= (rank_wr_sel[0]) ? r2b_ba :
(rank_fifo_rd) ? rank_ba[3:2] : rank_ba[1:0];
rank_ba[3:2] <= (rank_wr_sel[1]) ? r2b_ba :
(rank_fifo_rd) ? rank_ba[5:4] : rank_ba[3:2];
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];
 
if(`TARGET_DESIGN == `ASIC) begin // This Logic is implemented for ASIC Only
// Note: Currenly top-level does not generate the
// sdr_req_norm_dma_last signal and can be tied zero at top-level
rank_ba_last[0] <= (rank_wr_sel[0]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? rank_ba_last[1] : rank_ba_last[0];
 
rank_ba_last[1] <= (rank_wr_sel[1]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? rank_ba_last[2] : rank_ba_last[1];
 
rank_ba_last[2] <= (rank_wr_sel[2]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? rank_ba_last[3] : rank_ba_last[2];
 
rank_ba_last[3] <= (rank_wr_sel[3]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? 1'b0 : rank_ba_last[3];
end
 
end // else: !if(~reset_n)
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
 
sdrc_bank_fsm bank0_fsm (.clk (clk),
.reset_n (reset_n),
 
/* 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]),
 
/* 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),
 
.bank_row(bank0_row),
 
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
/****************************************************************************/
// Instantiate Bank Ctl FSM 1
 
sdrc_bank_fsm bank1_fsm (.clk (clk),
.reset_n (reset_n),
 
/* 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]),
 
/* 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),
 
.bank_row(bank1_row),
 
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
/****************************************************************************/
// Instantiate Bank Ctl FSM 2
 
sdrc_bank_fsm bank2_fsm (.clk (clk),
.reset_n (reset_n),
 
/* 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]),
 
/* 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),
 
.bank_row(bank2_row),
 
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
/****************************************************************************/
// Instantiate Bank Ctl FSM 3
 
sdrc_bank_fsm bank3_fsm (.clk (clk),
.reset_n (reset_n),
 
/* 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]),
 
/* 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),
 
.bank_row(bank3_row),
 
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
 
/* address for current xfr, debug only */
wire [12:0] cur_row = (xfr_bank_sel==3) ? bank3_row:
(xfr_bank_sel==2) ? bank2_row:
(xfr_bank_sel==1) ? bank1_row: bank0_row;
 
 
endmodule // sdr_bank_ctl
caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_bank_ctl.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_bank_fsm.v =================================================================== --- caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_bank_fsm.v (nonexistent) +++ caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_bank_fsm.v (revision 19) @@ -0,0 +1,371 @@ +/********************************************************************* + + 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_define.v" + +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 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 [12:0] r2b_raddr; + input [12:0] r2b_caddr; + input [`REQ_BW-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 [12:0] b2x_addr; + output [`REQ_BW-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 [12: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 [12:0] b2x_addr; + reg [`REQ_BW-1:0] l_len; + wire [`REQ_BW-1:0] b2x_len; + reg [1:0] b2x_cmd_t; + reg bank_valid; + reg [12:0] bank_row; + reg [3:0] tras_cntr, timer0; + reg l_wrap, l_write; + wire b2x_wrap; + reg [12:0] l_raddr; + reg [12: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_t, ld_trp, ld_trcd; + + /*** Timing Break Logic Added for FPGA - Start ****/ + reg x2b_wrok_r, xfr_ok_r , x2b_rdok_r; + reg [1:0] b2x_cmd_r,timer0_tc_r,tras_ok_r,x2b_pre_ok_r,x2b_act_ok_r; + always @ (posedge clk) + if (~reset_n) begin + x2b_wrok_r <= 1'b0; + xfr_ok_r <= 1'b0; + x2b_rdok_r <= 1'b0; + b2x_cmd_r <= 2'b0; + timer0_tc_r <= 1'b0; + tras_ok_r <= 1'b0; + x2b_pre_ok_r <= 1'b0; + x2b_act_ok_r <= 1'b0; + end + else begin + x2b_wrok_r <= x2b_wrok; + xfr_ok_r <= xfr_ok; + x2b_rdok_r <= x2b_rdok; + b2x_cmd_r <= b2x_cmd_t; + timer0_tc_r <= (ld_trp | ld_trcd) ? 1'b0 : timer0_tc_t; + tras_ok_r <= tras_ok_internal; + x2b_pre_ok_r <= x2b_pre_ok; + x2b_act_ok_r <= x2b_act_ok; + end + + wire x2b_wrok_t = (`TARGET_DESIGN == `FPGA) ? x2b_wrok_r : x2b_wrok; + wire xfr_ok_t = (`TARGET_DESIGN == `FPGA) ? xfr_ok_r : xfr_ok; + wire x2b_rdok_t = (`TARGET_DESIGN == `FPGA) ? x2b_rdok_r : x2b_rdok; + wire [1:0] b2x_cmd = (`TARGET_DESIGN == `FPGA) ? b2x_cmd_r : b2x_cmd_t; + wire timer0_tc = (`TARGET_DESIGN == `FPGA) ? timer0_tc_r : timer0_tc_t; + assign tras_ok = (`TARGET_DESIGN == `FPGA) ? tras_ok_r : tras_ok_internal; + wire x2b_pre_ok_t = (`TARGET_DESIGN == `FPGA) ? x2b_pre_ok_r : x2b_pre_ok; + wire x2b_act_ok_t = (`TARGET_DESIGN == `FPGA) ? x2b_act_ok_r : x2b_act_ok; + + /*** Timing Break Logic Added for FPGA - End****/ + + + 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 + (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 != 'h0) ? timer0 - 4'b1 : timer0; + + bank_st <= next_bank_st; + + end // else: !if(~reset_n) + + always @ (posedge clk) begin + + bank_row <= (bank_st == `BANK_ACT) ? 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 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_t = ~|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_t = 2'bx; + b2r_ack = 1'b0; + b2x_addr = 13'bx; + next_bank_st = bank_st; + + case (bank_st) + + `BANK_IDLE : begin + if(`TARGET_DESIGN == `FPGA) begin // To break the timing, b2x request are generated delayed + if (~r2b_req) begin + next_bank_st = `BANK_IDLE; + end // if (~r2b_req) + else if (page_hit) begin + b2r_ack = 1'b1; + b2x_cmd_t = (r2b_write) ? `OP_WR : `OP_RD; + next_bank_st = `BANK_XFR; + end // if (page_hit) + else begin // page_miss + b2r_ack = 1'b1; + b2x_cmd_t = `OP_PRE; + next_bank_st = `BANK_PRE; // bank was precharged on l_sdr_dma_last + end // else: !if(page_hit) + end else begin // ASIC + if (~r2b_req) begin + bank_prech_page_closed = 1'b0; + b2x_req = 1'b0; + b2x_cmd_t = 2'bx; + b2r_ack = 1'b0; + b2x_addr = 13'bx; + next_bank_st = `BANK_IDLE; + end // if (~r2b_req) + else if (page_hit) begin + b2x_req = (r2b_write) ? x2b_wrok_t & xfr_ok_t : + x2b_rdok_t & xfr_ok_t; + b2x_cmd_t = (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 & x2b_pre_ok_t; + b2x_cmd_t = `OP_PRE; + b2r_ack = 1'b1; + b2x_addr = r2b_raddr & 13'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 + end // case: `BANK_IDLE + + `BANK_PRE : begin + b2x_req = tras_ok & x2b_pre_ok_t; + b2x_cmd_t = `OP_PRE; + b2r_ack = 1'b0; + b2x_addr = l_raddr & 13'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_t; + b2x_cmd_t = `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_t & xfr_ok_t : + timer0_tc & x2b_rdok_t & xfr_ok_t; + b2x_cmd_t = (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 & x2b_pre_ok_t; + b2x_cmd_t = `OP_PRE; + b2r_ack = 1'b0; + b2x_addr = l_raddr & 13'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
caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_bank_fsm.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_bs_convert.v =================================================================== --- caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_bs_convert.v (nonexistent) +++ caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_bs_convert.v (revision 19) @@ -0,0 +1,228 @@ +/********************************************************************* + + SDRAM Controller buswidth converter + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SDRAM Controller Buswidth converter + + This module does write/read data transalation between + application data to SDRAM bus width + + To Do: + nothing + + Author(s): + - Dinesh Annayya, dinesha@opencores.org + Version : 0.0 - 8th Jan 2012 - Initial structure + 0.2 - 2nd Feb 2012 + Improved the command pipe structure to accept up-to 4 command of different bank. + 0.3 - 6th Feb 2012 + Bug fix on read valid generation + + + + 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_define.v" +module sdrc_bs_convert ( + clk , + reset_n , + sdr_width , + + /* Control Signal from xfr ctrl */ + x2a_rdstart , + x2a_wrstart , + x2a_rdlast , + x2a_wrlast , + x2a_rddt , + x2a_rdok , + a2x_wrdt , + a2x_wren_n , + x2a_wrnext , + + /* Control Signal from/to to application i/f */ + app_wr_data , + app_wr_en_n , + app_wr_next , + app_last_wr , + app_rd_data , + app_rd_valid , + app_last_rd + ); + + +parameter APP_AW = 30; // Application Address Width +parameter APP_DW = 32; // Application Data Width +parameter APP_BW = 4; // Application Byte Width + +parameter SDR_DW = 16; // SDR Data Width +parameter SDR_BW = 2; // SDR Byte Width + +input clk ; +input reset_n ; +input [1:0] sdr_width ; // 2'b00 - 32 Bit SDR, 2'b01 - 16 Bit SDR, 2'b1x - 8 Bit + +/* Control Signal from xfr ctrl Read Transaction*/ +input x2a_rdstart ; // read start indication +input x2a_rdlast ; // read last burst access +input [SDR_DW-1:0] x2a_rddt ; +input x2a_rdok ; + +/* Control Signal from xfr ctrl Write Transaction*/ +input x2a_wrstart ; // writ start indication +input x2a_wrlast ; // write last transfer +input x2a_wrnext ; +output [SDR_DW-1:0] a2x_wrdt ; +output [SDR_BW-1:0] a2x_wren_n ; + +// Application Write Transaction +input [APP_DW-1:0] app_wr_data ; +input [APP_BW-1:0] app_wr_en_n ; +output app_wr_next ; +output app_last_wr ; // Indicate last Write Transfer for a given burst size + +// Application Read Transaction +output [APP_DW-1:0] app_rd_data ; +output app_rd_valid ; +output app_last_rd ; // Indicate last Read Transfer for a given burst size + +//---------------------------------------------- +// Local Decleration +// ---------------------------------------- + +reg [APP_DW-1:0] app_rd_data ; +reg app_rd_valid ; +reg [SDR_DW-1:0] a2x_wrdt ; +reg [SDR_BW-1:0] a2x_wren_n ; +reg app_wr_next ; + +reg [23:0] saved_rd_data ; +reg [1:0] rd_xfr_count ; +reg [1:0] wr_xfr_count ; + + +assign app_last_wr = x2a_wrlast; +assign app_last_rd = x2a_rdlast; + +always @(*) begin + if(sdr_width == 2'b00) // 32 Bit SDR Mode + begin + a2x_wrdt = app_wr_data; + a2x_wren_n = app_wr_en_n; + app_wr_next = x2a_wrnext; + app_rd_data = x2a_rddt; + app_rd_valid = x2a_rdok; + end + else if(sdr_width == 2'b01) // 16 Bit SDR Mode + begin + // Changed the address and length to match the 16 bit SDR Mode + app_wr_next = (x2a_wrnext & wr_xfr_count[0]); + app_rd_valid = (x2a_rdok & rd_xfr_count[0]); + if(wr_xfr_count[0] == 1'b1) + begin + a2x_wren_n = app_wr_en_n[3:2]; + a2x_wrdt = app_wr_data[31:16]; + end + else + begin + a2x_wren_n = app_wr_en_n[1:0]; + a2x_wrdt = app_wr_data[15:0]; + end + + app_rd_data = {x2a_rddt,saved_rd_data[15:0]}; + end else // 8 Bit SDR Mode + begin + // Changed the address and length to match the 16 bit SDR Mode + app_wr_next = (x2a_wrnext & (wr_xfr_count[1:0]== 2'b11)); + app_rd_valid = (x2a_rdok & (rd_xfr_count[1:0]== 2'b11)); + if(wr_xfr_count[1:0] == 2'b11) + begin + a2x_wren_n = app_wr_en_n[3]; + a2x_wrdt = app_wr_data[31:24]; + end + else if(wr_xfr_count[1:0] == 2'b10) + begin + a2x_wren_n = app_wr_en_n[2]; + a2x_wrdt = app_wr_data[23:16]; + end + else if(wr_xfr_count[1:0] == 2'b01) + begin + a2x_wren_n = app_wr_en_n[1]; + a2x_wrdt = app_wr_data[15:8]; + end + else begin + a2x_wren_n = app_wr_en_n[0]; + a2x_wrdt = app_wr_data[7:0]; + end + + app_rd_data = {x2a_rddt,saved_rd_data[23:0]}; + end + end + + + +always @(posedge clk) + begin + if(!reset_n) + begin + rd_xfr_count <= 8'b0; + wr_xfr_count <= 8'b0; + saved_rd_data <= 24'h0; + end + else begin + + // During Write Phase + if(x2a_wrlast) begin + wr_xfr_count <= 0; + end + else if(x2a_wrnext) begin + wr_xfr_count <= wr_xfr_count + 1'b1; + end + + // During Read Phase + if(x2a_rdlast) begin + rd_xfr_count <= 0; + end + else if(x2a_rdok) begin + rd_xfr_count <= rd_xfr_count + 1'b1; + end + + // Save Previous Data + if(x2a_rdok) begin + if(sdr_width == 2'b01) // 16 Bit SDR Mode + saved_rd_data[15:0] <= x2a_rddt; + else begin// 8 bit SDR Mode - + if(rd_xfr_count[1:0] == 2'b00) saved_rd_data[7:0] <= x2a_rddt[7:0]; + else if(rd_xfr_count[1:0] == 2'b01) saved_rd_data[15:8] <= x2a_rddt[7:0]; + else if(rd_xfr_count[1:0] == 2'b10) saved_rd_data[23:16] <= x2a_rddt[7:0]; + end + end + end +end + +endmodule // sdr_bs_convert
caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_bs_convert.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_core.v =================================================================== --- caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_core.v (nonexistent) +++ caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_core.v (revision 19) @@ -0,0 +1,477 @@ +/********************************************************************* + + SDRAM Controller Core File + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SDRAM Controller Core Module + 2 types of SDRAMs are supported, 1Mx16 2 bank, or 4Mx16 4 bank. + This block integrate following sub modules + + sdrc_bs_convert + convert the system side 32 bit into equvailent 8/16/32 SDR format + sdrc_req_gen + This module takes requests from the app, chops them to burst booundaries + if wrap=0, decodes the bank and passe the request to bank_ctl + sdrc_xfr_ctl + This module takes requests from sdr_bank_ctl, runs the transfer and + controls data flow to/from the app. At the end of the transfer it issues a + burst terminate if not at the end of a burst and another command to this + bank is not available. + + sdrc_bank_ctl + This module takes requests from sdr_req_gen, checks for page hit/miss and + issues precharge/activate commands and then passes the request to + sdr_xfr_ctl. + + + Assumption: SDRAM Pads should be placed near to this module. else + user should add a FF near the pads + + To Do: + nothing + + Author(s): + - Dinesh Annayya, dinesha@opencores.org + Version : 0.0 - 8th Jan 2012 + Initial version with 16/32 Bit SDRAM Support + : 0.1 - 24th Jan 2012 + 8 Bit SDRAM Support is added + 0.2 - 2nd Feb 2012 + Improved the command pipe structure to accept up-to + 4 command of different bank. + 0.3 - 7th Feb 2012 + Bug fix for parameter defination for request length has changed from 9 to 12 + 0.4 - 26th April 2013 + SDRAM Address Bit is Extended by 12 bit to 13 bit to support higher SDRAM + + + 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_define.v" +module sdrc_core + ( + clk, + pad_clk, + reset_n, + sdr_width, + cfg_colbits, + + /* Request from app */ + app_req, // Transfer Request + app_req_addr, // SDRAM Address + app_req_len, // Burst Length (in 16 bit words) + app_req_wrap, // Wrap mode request (xfr_len = 4) + app_req_wr_n, // 0 => Write request, 1 => read req + app_req_ack, // Request has been accepted + cfg_req_depth, //how many req. buffer should hold + + app_wr_data, + app_wr_en_n, + app_last_wr, + + app_rd_data, + app_rd_valid, + app_last_rd, + app_wr_next_req, + sdr_init_done, + app_req_dma_last, + + /* Interface to SDRAMs */ + sdr_cs_n, + sdr_cke, + sdr_ras_n, + sdr_cas_n, + sdr_we_n, + sdr_dqm, + sdr_ba, + sdr_addr, + pad_sdr_din, + sdr_dout, + sdr_den_n, + + /* Parameters */ + cfg_sdr_en, + cfg_sdr_mode_reg, + cfg_sdr_tras_d, + cfg_sdr_trp_d, + cfg_sdr_trcd_d, + cfg_sdr_cas, + cfg_sdr_trcar_d, + cfg_sdr_twr_d, + cfg_sdr_rfsh, + cfg_sdr_rfmax); + +parameter APP_AW = 26; // 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 + + +//----------------------------------------------- +// Global Variable +// ---------------------------------------------- +input clk ; // SDRAM Clock +input pad_clk ; // SDRAM Clock from Pad, used for registering Read Data +input reset_n ; // Reset Signal +input [1:0] sdr_width ; // 2'b00 - 32 Bit SDR, 2'b01 - 16 Bit SDR, 2'b1x - 8 Bit +input [1:0] cfg_colbits ; // 2'b00 - 8 Bit column address, 2'b01 - 9 Bit, 10 - 10 bit, 11 - 11Bits + + +//------------------------------------------------ +// Request from app +//------------------------------------------------ +input app_req ; // Application Request +input [APP_AW-1:0] app_req_addr ; // Address +input app_req_wr_n ; // 0 - Write, 1 - Read +input app_req_wrap ; // Address Wrap +output app_req_ack ; // Application Request Ack + +input [APP_DW-1:0] app_wr_data ; // Write Data +output app_wr_next_req ; // Next Write Data Request +input [APP_BW-1:0] app_wr_en_n ; // Byte wise Write Enable +output app_last_wr ; // Last Write trannsfer of a given Burst +output [APP_DW-1:0] app_rd_data ; // Read Data +output app_rd_valid ; // Read Valid +output app_last_rd ; // Last Read Transfer of a given Burst + +//------------------------------------------------ +// Interface to SDRAMs +//------------------------------------------------ +output sdr_cke ; // SDRAM CKE +output sdr_cs_n ; // SDRAM Chip Select +output sdr_ras_n ; // SDRAM ras +output sdr_cas_n ; // SDRAM cas +output sdr_we_n ; // SDRAM write enable +output [SDR_BW-1:0] sdr_dqm ; // SDRAM Data Mask +output [1:0] sdr_ba ; // SDRAM Bank Enable +output [12:0] sdr_addr ; // SDRAM Address +input [SDR_DW-1:0] pad_sdr_din ; // SDRA Data Input +output [SDR_DW-1:0] sdr_dout ; // SDRAM Data Output +output [SDR_BW-1:0] sdr_den_n ; // SDRAM Data Output enable + +//------------------------------------------------ +// Configuration Parameter +//------------------------------------------------ +output sdr_init_done ; // Indicate SDRAM Initialisation Done +input [3:0] cfg_sdr_tras_d ; // Active to precharge delay +input [3:0] cfg_sdr_trp_d ; // Precharge to active delay +input [3:0] cfg_sdr_trcd_d ; // Active to R/W delay +input cfg_sdr_en ; // Enable SDRAM controller +input [1:0] cfg_req_depth ; // Maximum Request accepted by SDRAM controller +input [APP_RW-1:0] app_req_len ; // Application Burst Request length in 32 bit +input [12:0] cfg_sdr_mode_reg ; +input [2:0] cfg_sdr_cas ; // SDRAM CAS Latency +input [3:0] cfg_sdr_trcar_d ; // Auto-refresh period +input [3:0] cfg_sdr_twr_d ; // Write recovery delay +input [`SDR_RFSH_TIMER_W-1 : 0] cfg_sdr_rfsh; +input [`SDR_RFSH_ROW_CNT_W -1 : 0] cfg_sdr_rfmax; +input app_req_dma_last; // this signal should close the bank + +/****************************************************************************/ +// Internal Nets + +// SDR_REQ_GEN +wire [`SDR_REQ_ID_W-1:0]r2b_req_id; +wire [1:0] r2b_ba; +wire [12:0] r2b_raddr; +wire [12:0] r2b_caddr; +wire [`REQ_BW-1:0] r2b_len; + +// SDR BANK CTL +wire [`SDR_REQ_ID_W-1:0]b2x_id; +wire [1:0] b2x_ba; +wire [12:0] b2x_addr; +wire [`REQ_BW-1:0] b2x_len; +wire [1:0] b2x_cmd; + +// SDR_XFR_CTL +wire [3:0] x2b_pre_ok; +wire [`SDR_REQ_ID_W-1:0]xfr_id; +wire [APP_DW-1:0] app_rd_data; +wire sdr_cs_n, sdr_cke, sdr_ras_n, sdr_cas_n, sdr_we_n; +wire [SDR_BW-1:0] sdr_dqm; +wire [1:0] sdr_ba; +wire [12:0] sdr_addr; +wire [SDR_DW-1:0] sdr_dout; +wire [SDR_DW-1:0] sdr_dout_int; +wire [SDR_BW-1:0] sdr_den_n; +wire [SDR_BW-1:0] sdr_den_n_int; + +wire [1:0] xfr_bank_sel; + +wire [APP_AW-1:0] app_req_addr; +wire [APP_RW-1:0] app_req_len; + +wire [APP_DW-1:0] app_wr_data; +wire [SDR_DW-1:0] a2x_wrdt ; +wire [APP_BW-1:0] app_wr_en_n; +wire [SDR_BW-1:0] a2x_wren_n; + +//wire [31:0] app_rd_data; +wire [SDR_DW-1:0] x2a_rddt; + + +// synopsys translate_off + wire [3:0] sdr_cmd; + assign sdr_cmd = {sdr_cs_n, sdr_ras_n, sdr_cas_n, sdr_we_n}; +// synopsys translate_on + +assign sdr_den_n = sdr_den_n_int ; +assign sdr_dout = sdr_dout_int ; + + +// To meet the timing at read path, read data is registered w.r.t pad_sdram_clock and register back to sdram_clk +// assumption, pad_sdram_clk is synhronous and delayed clock of sdram_clk. +// register w.r.t pad sdram clk +reg [SDR_DW-1:0] pad_sdr_din1; +reg [SDR_DW-1:0] pad_sdr_din2; +always@(posedge pad_clk) begin + pad_sdr_din1 <= pad_sdr_din; +end + +always@(posedge clk) begin + pad_sdr_din2 <= pad_sdr_din1; +end + + + /****************************************************************************/ + // Instantiate sdr_req_gen + // This module takes requests from the app, chops them to burst booundaries + // if wrap=0, decodes the bank and passe the request to bank_ctl + +sdrc_req_gen #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_req_gen ( + .clk (clk ), + .reset_n (reset_n ), + .cfg_colbits (cfg_colbits ), + .sdr_width (sdr_width ), + + /* Req to xfr_ctl */ + .r2x_idle (r2x_idle ), + + /* Request from app */ + .req (app_req ), + .req_id (4'b0 ), + .req_addr (app_req_addr ), + .req_len (app_req_len ), + .req_wrap (app_req_wrap ), + .req_wr_n (app_req_wr_n ), + .req_ack (app_req_ack ), + + /* Req to bank_ctl */ + .r2b_req (r2b_req ), + .r2b_req_id (r2b_req_id ), + .r2b_start (r2b_start ), + .r2b_last (r2b_last ), + .r2b_wrap (r2b_wrap ), + .r2b_ba (r2b_ba ), + .r2b_raddr (r2b_raddr ), + .r2b_caddr (r2b_caddr ), + .r2b_len (r2b_len ), + .r2b_write (r2b_write ), + .b2r_ack (b2r_ack ), + .b2r_arb_ok (b2r_arb_ok ) + ); + + /****************************************************************************/ + // Instantiate sdr_bank_ctl + // This module takes requests from sdr_req_gen, checks for page hit/miss and + // issues precharge/activate commands and then passes the request to + // sdr_xfr_ctl. + +sdrc_bank_ctl #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_bank_ctl ( + .clk (clk ), + .reset_n (reset_n ), + .a2b_req_depth (cfg_req_depth ), + + /* Req from req_gen */ + .r2b_req (r2b_req ), + .r2b_req_id (r2b_req_id ), + .r2b_start (r2b_start ), + .r2b_last (r2b_last ), + .r2b_wrap (r2b_wrap ), + .r2b_ba (r2b_ba ), + .r2b_raddr (r2b_raddr ), + .r2b_caddr (r2b_caddr ), + .r2b_len (r2b_len ), + .r2b_write (r2b_write ), + .b2r_arb_ok (b2r_arb_ok ), + .b2r_ack (b2r_ack ), + + /* Transfer request to xfr_ctl */ + .b2x_idle (b2x_idle ), + .b2x_req (b2x_req ), + .b2x_start (b2x_start ), + .b2x_last (b2x_last ), + .b2x_wrap (b2x_wrap ), + .b2x_id (b2x_id ), + .b2x_ba (b2x_ba ), + .b2x_addr (b2x_addr ), + .b2x_len (b2x_len ), + .b2x_cmd (b2x_cmd ), + .x2b_ack (x2b_ack ), + + /* Status from xfr_ctl */ + .b2x_tras_ok (b2x_tras_ok ), + .x2b_refresh (x2b_refresh ), + .x2b_pre_ok (x2b_pre_ok ), + .x2b_act_ok (x2b_act_ok ), + .x2b_rdok (x2b_rdok ), + .x2b_wrok (x2b_wrok ), + + /* for generate cuurent xfr address msb */ + .sdr_req_norm_dma_last(app_req_dma_last), + .xfr_bank_sel (xfr_bank_sel ), + + /* SDRAM Timing */ + .tras_delay (cfg_sdr_tras_d ), + .trp_delay (cfg_sdr_trp_d ), + .trcd_delay (cfg_sdr_trcd_d ) + ); + + /****************************************************************************/ + // Instantiate sdr_xfr_ctl + // This module takes requests from sdr_bank_ctl, runs the transfer and + // controls data flow to/from the app. At the end of the transfer it issues a + // burst terminate if not at the end of a burst and another command to this + // bank is not available. + +sdrc_xfr_ctl #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_xfr_ctl ( + .clk (clk ), + .reset_n (reset_n ), + + /* Transfer request from bank_ctl */ + .r2x_idle (r2x_idle ), + .b2x_idle (b2x_idle ), + .b2x_req (b2x_req ), + .b2x_start (b2x_start ), + .b2x_last (b2x_last ), + .b2x_wrap (b2x_wrap ), + .b2x_id (b2x_id ), + .b2x_ba (b2x_ba ), + .b2x_addr (b2x_addr ), + .b2x_len (b2x_len ), + .b2x_cmd (b2x_cmd ), + .x2b_ack (x2b_ack ), + + /* Status to bank_ctl, req_gen */ + .b2x_tras_ok (b2x_tras_ok ), + .x2b_refresh (x2b_refresh ), + .x2b_pre_ok (x2b_pre_ok ), + .x2b_act_ok (x2b_act_ok ), + .x2b_rdok (x2b_rdok ), + .x2b_wrok (x2b_wrok ), + + /* SDRAM I/O */ + .sdr_cs_n (sdr_cs_n ), + .sdr_cke (sdr_cke ), + .sdr_ras_n (sdr_ras_n ), + .sdr_cas_n (sdr_cas_n ), + .sdr_we_n (sdr_we_n ), + .sdr_dqm (sdr_dqm ), + .sdr_ba (sdr_ba ), + .sdr_addr (sdr_addr ), + .sdr_din (pad_sdr_din2 ), + .sdr_dout (sdr_dout_int ), + .sdr_den_n (sdr_den_n_int ), + /* Data Flow to the app */ + .x2a_rdstart (x2a_rdstart ), + .x2a_wrstart (x2a_wrstart ), + .x2a_id (xfr_id ), + .x2a_rdlast (x2a_rdlast ), + .x2a_wrlast (x2a_wrlast ), + .a2x_wrdt (a2x_wrdt ), + .a2x_wren_n (a2x_wren_n ), + .x2a_wrnext (x2a_wrnext ), + .x2a_rddt (x2a_rddt ), + .x2a_rdok (x2a_rdok ), + .sdr_init_done (sdr_init_done ), + + /* SDRAM Parameters */ + .sdram_enable (cfg_sdr_en ), + .sdram_mode_reg (cfg_sdr_mode_reg ), + + /* current xfr bank */ + .xfr_bank_sel (xfr_bank_sel ), + + /* SDRAM Timing */ + .cas_latency (cfg_sdr_cas ), + .trp_delay (cfg_sdr_trp_d ), + .trcar_delay (cfg_sdr_trcar_d ), + .twr_delay (cfg_sdr_twr_d ), + .rfsh_time (cfg_sdr_rfsh ), + .rfsh_rmax (cfg_sdr_rfmax ) + ); + + /****************************************************************************/ + // Instantiate sdr_bs_convert + // This model handle the bus with transaltion from application layer to + // 8/16/32 SDRAM Memory format + // During Write Phase, this block split the data as per SDRAM Width + // During Read Phase, This block does the re-packing based on SDRAM + // Width + //--------------------------------------------------------------------------- +sdrc_bs_convert #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_bs_convert ( + .clk (clk ), + .reset_n (reset_n ), + .sdr_width (sdr_width ), + + /* Control Signal from xfr ctrl */ + // Read Interface Inputs + .x2a_rdstart (x2a_rdstart ), + .x2a_rdlast (x2a_rdlast ), + .x2a_rdok (x2a_rdok ), + // Read Interface outputs + .x2a_rddt (x2a_rddt ), + + // Write Interface, Inputs + .x2a_wrstart (x2a_wrstart ), + .x2a_wrlast (x2a_wrlast ), + .x2a_wrnext (x2a_wrnext ), + + // Write Interface, Outputs + .a2x_wrdt (a2x_wrdt ), + .a2x_wren_n (a2x_wren_n ), + + /* Control Signal from sdrc_bank_ctl */ + + /* Control Signal from/to to application i/f */ + .app_wr_data (app_wr_data ), + .app_wr_en_n (app_wr_en_n ), + .app_wr_next (app_wr_next_req ), + .app_last_wr (app_last_wr ), + .app_rd_data (app_rd_data ), + .app_rd_valid (app_rd_valid ), + .app_last_rd (app_last_rd ) + + ); + +endmodule // sdrc_core
caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_core.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_req_gen.v =================================================================== --- caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_req_gen.v (nonexistent) +++ caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_req_gen.v (revision 19) @@ -0,0 +1,340 @@ +/********************************************************************* + + SDRAM Controller Request Generation + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SDRAM Controller Reguest Generation + + Address Generation Based on cfg_colbits + cfg_colbits= 2'b00 + Address[7:0] - Column Address + Address[9:8] - Bank Address + Address[22:10] - Row Address + cfg_colbits= 2'b01 + Address[8:0] - Column Address + Address[10:9] - Bank Address + Address[23:11] - Row Address + cfg_colbits= 2'b10 + Address[9:0] - Column Address + Address[11:10] - Bank Address + Address[24:12] - Row Address + cfg_colbits= 2'b11 + Address[10:0] - Column Address + Address[12:11] - Bank Address + Address[25:13] - Row Address + + The SDRAMs are operated in 4 beat burst mode. + + If Wrap = 0; + If the current burst cross the page boundary, then this block split the request + into two coressponding change in address and request length + + if the current burst cross the page boundar. + This module takes requests from the memory controller, + chops them to page boundaries if wrap=0, + and passes the request to bank_ctl + + Note: With Wrap = 0, each request from Application layer will be splited into two request, + if the current burst cross the page boundary. + + To Do: + nothing + + Author(s): + - Dinesh Annayya, dinesha@opencores.org + Version : 0.0 - 8th Jan 2012 + 0.1 - 5th Feb 2012, column/row/bank address are register to improve the timing issue in FPGA synthesis + + + + 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_define.v" + +module sdrc_req_gen (clk, + reset_n, + cfg_colbits, + sdr_width, + + /* Request from app */ + req, // Transfer Request + req_id, // ID for this transfer + req_addr, // SDRAM Address + req_len, // Burst Length (in 32 bit words) + req_wrap, // Wrap mode request (xfr_len = 4) + req_wr_n, // 0 => Write request, 1 => read req + req_ack, // Request has been accepted + + /* Req to xfr_ctl */ + r2x_idle, + + /* Req to bank_ctl */ + r2b_req, // request + r2b_req_id, // ID + r2b_start, // First chunk of burst + r2b_last, // Last chunk of burst + r2b_wrap, // Wrap Mode + r2b_ba, // bank address + r2b_raddr, // row address + r2b_caddr, // col address + r2b_len, // length + r2b_write, // write request + b2r_ack, + b2r_arb_ok + ); + +parameter APP_AW = 26; // 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 ; +input reset_n ; +input [1:0] cfg_colbits ; // 2'b00 - 8 Bit column address, 2'b01 - 9 Bit, 10 - 10 bit, 11 - 11Bits + +/* Request from app */ +input req ; // Request +input [`SDR_REQ_ID_W-1:0] req_id ; // Request ID +input [APP_AW-1:0] req_addr ; // Request Address +input [APP_RW-1:0] req_len ; // Request length +input req_wr_n ; // 0 -Write, 1 - Read +input req_wrap ; // 1 - Wrap the Address on page boundary +output req_ack ; // Request Ack + +/* Req to bank_ctl */ +output r2x_idle ; +output r2b_req ; // Request +output r2b_start ; // First Junk of the Burst Access +output r2b_last ; // Last Junk of the Burst Access +output r2b_write ; // 1 - Write, 0 - Read +output r2b_wrap ; // 1 - Wrap the Address at the page boundary. +output [`SDR_REQ_ID_W-1:0] r2b_req_id; +output [1:0] r2b_ba ; // Bank Address +output [12:0] r2b_raddr ; // Row Address +output [12:0] r2b_caddr ; // Column Address +output [`REQ_BW-1:0] r2b_len ; // Burst Length +input b2r_ack ; // Request Ack +input b2r_arb_ok ; // Bank controller fifo is not full and ready to accept the command +// +input [1:0] sdr_width; // 2'b00 - 32 Bit, 2'b01 - 16 Bit, 2'b1x - 8Bit + + + /****************************************************************************/ + // Internal Nets + + `define REQ_IDLE 2'b00 + `define REQ_ACTIVE 2'b01 + `define REQ_PAGE_WRAP 2'b10 + + reg [1:0] req_st, next_req_st; + reg r2x_idle, req_ack, r2b_req, r2b_start, + r2b_write, req_idle, req_ld, lcl_wrap; + reg [`SDR_REQ_ID_W-1:0] r2b_req_id; + reg [`REQ_BW-1:0] lcl_req_len; + + wire r2b_last, page_ovflw; + reg page_ovflw_r; + wire [`REQ_BW-1:0] r2b_len, next_req_len; + wire [12:0] max_r2b_len; + reg [12:0] max_r2b_len_r; + + reg [1:0] r2b_ba; + reg [12:0] r2b_raddr; + reg [12:0] r2b_caddr; + + reg [APP_AW-1:0] curr_sdr_addr ; + wire [APP_AW-1:0] next_sdr_addr ; + + +//-------------------------------------------------------------------- +// Generate the internal Adress and Burst length Based on sdram width +//-------------------------------------------------------------------- +reg [APP_AW:0] req_addr_int; +reg [APP_RW-1:0] req_len_int; + +always @(*) begin + if(sdr_width == 2'b00) begin // 32 Bit SDR Mode + req_addr_int = {1'b0,req_addr}; + req_len_int = req_len; + end else if(sdr_width == 2'b01) begin // 16 Bit SDR Mode + // Changed the address and length to match the 16 bit SDR Mode + req_addr_int = {req_addr,1'b0}; + req_len_int = {req_len,1'b0}; + end else begin // 8 Bit SDR Mode + // Changed the address and length to match the 16 bit SDR Mode + req_addr_int = {req_addr,2'b0}; + req_len_int = {req_len,2'b0}; + end +end + + // + // Identify the page over flow. + // Find the Maximum Burst length allowed from the selected column + // address, If the requested burst length is more than the allowed Maximum + // burst length, then we need to handle the bank cross over case and we + // need to split the reuest. + // + assign max_r2b_len = (cfg_colbits == 2'b00) ? (12'h100 - {4'b0, req_addr_int[7:0]}) : + (cfg_colbits == 2'b01) ? (12'h200 - {3'b0, req_addr_int[8:0]}) : + (cfg_colbits == 2'b10) ? (12'h400 - {2'b0, req_addr_int[9:0]}) : (12'h800 - {1'b0, req_addr_int[10:0]}); + + + // If the wrap = 0 and current application burst length is crossing the page boundary, + // then request will be split into two with corresponding change in request address and request length. + // + // If the wrap = 0 and current burst length is not crossing the page boundary, + // then request from application layer will be transparently passed on the bank control block. + + // + // if the wrap = 1, then this block will not modify the request address and length. + // The wrapping functionality will be handle by the bank control module and + // column address will rewind back as follows XX -> FF ? 00 ? 1 + // + // Note: With Wrap = 0, each request from Application layer will be spilited into two request, + // if the current burst cross the page boundary. + assign page_ovflw = ({1'b0, req_len_int} > max_r2b_len) ? ~r2b_wrap : 1'b0; + + assign r2b_len = r2b_start ? ((page_ovflw_r) ? max_r2b_len_r : lcl_req_len) : + lcl_req_len; + + assign next_req_len = lcl_req_len - r2b_len; + + assign next_sdr_addr = curr_sdr_addr + r2b_len; + + + assign r2b_wrap = lcl_wrap; + + assign r2b_last = (r2b_start & !page_ovflw_r) | (req_st == `REQ_PAGE_WRAP); +// +// +// + always @ (posedge clk) begin + + page_ovflw_r <= (req_ack) ? page_ovflw: 'h0; + + max_r2b_len_r <= (req_ack) ? max_r2b_len: 'h0; + r2b_start <= (req_ack) ? 1'b1 : + (b2r_ack) ? 1'b0 : r2b_start; + + r2b_write <= (req_ack) ? ~req_wr_n : r2b_write; + + r2b_req_id <= (req_ack) ? req_id : r2b_req_id; + + lcl_wrap <= (req_ack) ? req_wrap : lcl_wrap; + + lcl_req_len <= (req_ack) ? req_len_int : + (req_ld) ? next_req_len : lcl_req_len; + + curr_sdr_addr <= (req_ack) ? req_addr_int : + (req_ld) ? next_sdr_addr : curr_sdr_addr; + + end // always @ (posedge clk) + + always @ (*) begin + r2x_idle = 1'b0; + req_idle = 1'b0; + req_ack = 1'b0; + req_ld = 1'b0; + r2b_req = 1'b0; + next_req_st = `REQ_IDLE; + + case (req_st) // synopsys full_case parallel_case + + `REQ_IDLE : begin + r2x_idle = ~req; + req_idle = 1'b1; + req_ack = req & b2r_arb_ok; + req_ld = 1'b0; + r2b_req = 1'b0; + next_req_st = (req & b2r_arb_ok) ? `REQ_ACTIVE : `REQ_IDLE; + end // case: `REQ_IDLE + + `REQ_ACTIVE : begin + r2x_idle = 1'b0; + req_idle = 1'b0; + req_ack = 1'b0; + req_ld = b2r_ack; + r2b_req = 1'b1; // req_gen to bank_req + next_req_st = (b2r_ack ) ? ((page_ovflw_r) ? `REQ_PAGE_WRAP :`REQ_IDLE) : `REQ_ACTIVE; + end // case: `REQ_ACTIVE + `REQ_PAGE_WRAP : begin + r2x_idle = 1'b0; + req_idle = 1'b0; + req_ack = 1'b0; + req_ld = b2r_ack; + r2b_req = 1'b1; // req_gen to bank_req + next_req_st = (b2r_ack) ? `REQ_IDLE : `REQ_PAGE_WRAP; + end // case: `REQ_ACTIVE + + endcase // case(req_st) + + end // always @ (req_st or ....) + + always @ (posedge clk) + if (~reset_n) begin + req_st <= `REQ_IDLE; + end // if (~reset_n) + else begin + req_st <= next_req_st; + end // else: !if(~reset_n) +// +// addrs bits for the bank, row and column +// +// Register row/column/bank to improve fpga timing issue +wire [APP_AW-1:0] map_address ; + +assign map_address = (req_ack) ? req_addr_int : + (req_ld) ? next_sdr_addr : curr_sdr_addr; + +always @ (posedge clk) begin +// Bank Bits are always - 2 Bits + r2b_ba <= (cfg_colbits == 2'b00) ? {map_address[9:8]} : + (cfg_colbits == 2'b01) ? {map_address[10:9]} : + (cfg_colbits == 2'b10) ? {map_address[11:10]} : map_address[12:11]; + +/******************** +* Colbits Mapping: +* 2'b00 - 8 Bit +* 2'b01 - 16 Bit +* 2'b10 - 10 Bit +* 2'b11 - 11 Bits +************************/ + r2b_caddr <= (cfg_colbits == 2'b00) ? {5'b0, map_address[7:0]} : + (cfg_colbits == 2'b01) ? {4'b0, map_address[8:0]} : + (cfg_colbits == 2'b10) ? {3'b0, map_address[9:0]} : {2'b0, map_address[10:0]}; + + r2b_raddr <= (cfg_colbits == 2'b00) ? map_address[22:10] : + (cfg_colbits == 2'b01) ? map_address[23:11] : + (cfg_colbits == 2'b10) ? map_address[24:12] : map_address[25:13]; +end + +endmodule // sdr_req_gen
caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_req_gen.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_xfr_ctl.v =================================================================== --- caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_xfr_ctl.v (nonexistent) +++ caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_xfr_ctl.v (revision 19) @@ -0,0 +1,772 @@ +/********************************************************************* + + SDRAM Controller Transfer control + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SDRAM Controller Transfer control + + This module takes requests from sdrc_bank_ctl and runs the + transfer. The input request is guaranteed to be in a bank that is + precharged and activated. This block runs the transfer until a + burst boundary is reached, then issues another read/write command + to sequentially step thru memory if wrap=0, until the transfer is + completed. + + if a read transfer finishes and the caddr is not at a burst boundary + a burst terminate command is issued unless another read/write or + precharge to the same bank is pending. + + if a write transfer finishes and the caddr is not at a burst boundary + a burst terminate command is issued unless a read/write is pending. + + If a refresh request is made, the bank_ctl will be held off until + the number of refreshes requested are completed. + + This block also handles SDRAM initialization. + + + 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_define.v" + +module sdrc_xfr_ctl (clk, + reset_n, + + /* Transfer request from bank_ctl */ + r2x_idle, // Req is idle + b2x_idle, // All banks are idle + b2x_req, // Req from bank_ctl + b2x_start, // first chunk of transfer + b2x_last, // last chunk of transfer + b2x_id, // Transfer ID + b2x_ba, // bank address + b2x_addr, // row/col address + b2x_len, // transfer length + b2x_cmd, // transfer command + b2x_wrap, // Wrap mode transfer + x2b_ack, // command accepted + + /* Status to bank_ctl, req_gen */ + b2x_tras_ok, // Tras for all banks expired + 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 + + /* SDRAM I/O */ + sdr_cs_n, + sdr_cke, + sdr_ras_n, + sdr_cas_n, + sdr_we_n, + sdr_dqm, + sdr_ba, + sdr_addr, + sdr_din, + sdr_dout, + sdr_den_n, + + /* Data Flow to the app */ + x2a_rdstart, + x2a_wrstart, + x2a_rdlast, + x2a_wrlast, + x2a_id, + a2x_wrdt, + a2x_wren_n, + x2a_wrnext, + x2a_rddt, + x2a_rdok, + sdr_init_done, + + /* SDRAM Parameters */ + sdram_enable, + sdram_mode_reg, + + /* output for generate row address of the transfer */ + xfr_bank_sel, + + /* SDRAM Timing */ + cas_latency, + trp_delay, // Precharge to refresh delay + trcar_delay, // Auto-refresh period + twr_delay, // Write recovery delay + rfsh_time, // time per row (31.25 or 15.6125 uS) + rfsh_rmax); // Number of rows to rfsh at a time (<120uS) + +parameter SDR_DW = 16; // SDR Data Width +parameter SDR_BW = 2; // SDR Byte Width + + +input clk, reset_n; + + /* Req from bank_ctl */ +input b2x_req, b2x_start, b2x_last, b2x_tras_ok, + b2x_wrap, r2x_idle, b2x_idle; +input [`SDR_REQ_ID_W-1:0] b2x_id; +input [1:0] b2x_ba; +input [12:0] b2x_addr; +input [`REQ_BW-1:0] b2x_len; +input [1:0] b2x_cmd; +output x2b_ack; + +/* Status to bank_ctl */ +output [3:0] x2b_pre_ok; +output x2b_refresh, x2b_act_ok, x2b_rdok, + x2b_wrok; +/* Data Flow to the app */ +output x2a_rdstart, x2a_wrstart, x2a_rdlast, x2a_wrlast; +output [`SDR_REQ_ID_W-1:0] x2a_id; + +input [SDR_DW-1:0] a2x_wrdt; +input [SDR_BW-1:0] a2x_wren_n; +output [SDR_DW-1:0] x2a_rddt; +output x2a_wrnext, x2a_rdok, sdr_init_done; + +/* Interface to SDRAMs */ +output sdr_cs_n, sdr_cke, sdr_ras_n, sdr_cas_n, + sdr_we_n; +output [SDR_BW-1:0] sdr_dqm; +output [1:0] sdr_ba; +output [12:0] sdr_addr; +input [SDR_DW-1:0] sdr_din; +output [SDR_DW-1:0] sdr_dout; +output [SDR_BW-1:0] sdr_den_n; + + output [1:0] xfr_bank_sel; + + input sdram_enable; + input [12:0] sdram_mode_reg; + input [2:0] cas_latency; + input [3:0] trp_delay, trcar_delay, twr_delay; + input [`SDR_RFSH_TIMER_W-1 : 0] rfsh_time; + input [`SDR_RFSH_ROW_CNT_W-1:0] rfsh_rmax; + + + /************************************************************************/ + // Internal Nets + + `define XFR_IDLE 2'b00 + `define XFR_WRITE 2'b01 + `define XFR_READ 2'b10 + `define XFR_RDWT 2'b11 + + reg [1:0] xfr_st, next_xfr_st; + reg [12:0] xfr_caddr; + wire last_burst; + wire x2a_rdstart, x2a_wrstart, x2a_rdlast, x2a_wrlast; + reg l_start, l_last, l_wrap; + wire [`SDR_REQ_ID_W-1:0] x2a_id; + reg [`SDR_REQ_ID_W-1:0] l_id; + wire [1:0] xfr_ba; + reg [1:0] l_ba; + wire [12:0] xfr_addr; + wire [`REQ_BW-1:0] xfr_len, next_xfr_len; + reg [`REQ_BW-1:0] l_len; + + reg mgmt_idle, mgmt_req; + reg [3:0] mgmt_cmd; + reg [12:0] mgmt_addr; + reg [1:0] mgmt_ba; + + reg sel_mgmt, sel_b2x; + reg cb_pre_ok, rdok, wrok, wr_next, + rd_next, sdr_init_done, act_cmd, d_act_cmd; + wire [3:0] b2x_sdr_cmd, xfr_cmd; + reg [3:0] i_xfr_cmd; + wire mgmt_ack, x2b_ack, b2x_read, b2x_write, + b2x_prechg, d_rd_next, dt_next, xfr_end, + rd_pipe_mt, ld_xfr, rd_last, d_rd_last, + wr_last, l_xfr_end, rd_start, d_rd_start, + wr_start, page_hit, burst_bdry, xfr_wrap, + b2x_prechg_hit; + reg [6:0] l_rd_next, l_rd_start, l_rd_last; + + assign b2x_read = (b2x_cmd == `OP_RD) ? 1'b1 : 1'b0; + + assign b2x_write = (b2x_cmd == `OP_WR) ? 1'b1 : 1'b0; + + assign b2x_prechg = (b2x_cmd == `OP_PRE) ? 1'b1 : 1'b0; + + assign b2x_sdr_cmd = (b2x_cmd == `OP_PRE) ? `SDR_PRECHARGE : + (b2x_cmd == `OP_ACT) ? `SDR_ACTIVATE : + (b2x_cmd == `OP_RD) ? `SDR_READ : + (b2x_cmd == `OP_WR) ? `SDR_WRITE : `SDR_DESEL; + + assign page_hit = (b2x_ba == l_ba) ? 1'b1 : 1'b0; + + assign b2x_prechg_hit = b2x_prechg & page_hit; + + assign xfr_cmd = (sel_mgmt) ? mgmt_cmd : + (sel_b2x) ? b2x_sdr_cmd : i_xfr_cmd; + + assign xfr_addr = (sel_mgmt) ? mgmt_addr : + (sel_b2x) ? b2x_addr : xfr_caddr+1; + + assign mgmt_ack = sel_mgmt; + + assign x2b_ack = sel_b2x; + + assign ld_xfr = sel_b2x & (b2x_read | b2x_write); + + assign xfr_len = (ld_xfr) ? b2x_len : l_len; + + //assign next_xfr_len = (l_xfr_end && !ld_xfr) ? l_len : xfr_len - 1; + assign next_xfr_len = (ld_xfr) ? b2x_len : + (l_xfr_end) ? l_len: l_len - 1; + + assign d_rd_next = (cas_latency == 3'b001) ? l_rd_next[2] : + (cas_latency == 3'b010) ? l_rd_next[3] : + (cas_latency == 3'b011) ? l_rd_next[4] : + (cas_latency == 3'b100) ? l_rd_next[5] : + l_rd_next[6]; + + assign d_rd_last = (cas_latency == 3'b001) ? l_rd_last[2] : + (cas_latency == 3'b010) ? l_rd_last[3] : + (cas_latency == 3'b011) ? l_rd_last[4] : + (cas_latency == 3'b100) ? l_rd_last[5] : + l_rd_last[6]; + + assign d_rd_start = (cas_latency == 3'b001) ? l_rd_start[2] : + (cas_latency == 3'b010) ? l_rd_start[3] : + (cas_latency == 3'b011) ? l_rd_start[4] : + (cas_latency == 3'b100) ? l_rd_start[5] : + l_rd_start[6]; + + assign rd_pipe_mt = (cas_latency == 3'b001) ? ~|l_rd_next[1:0] : + (cas_latency == 3'b010) ? ~|l_rd_next[2:0] : + (cas_latency == 3'b011) ? ~|l_rd_next[3:0] : + (cas_latency == 3'b100) ? ~|l_rd_next[4:0] : + ~|l_rd_next[5:0]; + + assign dt_next = wr_next | d_rd_next; + + assign xfr_end = ~|xfr_len; + + assign l_xfr_end = ~|(l_len-1); + + assign rd_start = ld_xfr & b2x_read & b2x_start; + + assign wr_start = ld_xfr & b2x_write & b2x_start; + + assign rd_last = rd_next & last_burst & ~|xfr_len[`REQ_BW-1:1]; + + //assign wr_last = wr_next & last_burst & ~|xfr_len[APP_RW-1:1]; + + assign wr_last = last_burst & ~|xfr_len[`REQ_BW-1:1]; + + //assign xfr_ba = (ld_xfr) ? b2x_ba : l_ba; + assign xfr_ba = (sel_mgmt) ? mgmt_ba : + (sel_b2x) ? b2x_ba : l_ba; + + assign xfr_wrap = (ld_xfr) ? b2x_wrap : l_wrap; + +// assign burst_bdry = ~|xfr_caddr[2:0]; + wire [1:0] xfr_caddr_lsb = (xfr_caddr[1:0]+1); + assign burst_bdry = ~|(xfr_caddr_lsb[1:0]); + + always @ (posedge clk) begin + if (~reset_n) begin + xfr_caddr <= 13'b0; + l_start <= 1'b0; + l_last <= 1'b0; + l_wrap <= 1'b0; + l_id <= 0; + l_ba <= 0; + l_len <= 0; + l_rd_next <= 7'b0; + l_rd_start <= 7'b0; + l_rd_last <= 7'b0; + act_cmd <= 1'b0; + d_act_cmd <= 1'b0; + xfr_st <= `XFR_IDLE; + end // if (~reset_n) + + else begin + xfr_caddr <= (ld_xfr) ? b2x_addr : + (rd_next | wr_next) ? xfr_caddr + 1 : xfr_caddr; + l_start <= (dt_next) ? 1'b0 : + (ld_xfr) ? b2x_start : l_start; + l_last <= (ld_xfr) ? b2x_last : l_last; + l_wrap <= (ld_xfr) ? b2x_wrap : l_wrap; + l_id <= (ld_xfr) ? b2x_id : l_id; + l_ba <= (ld_xfr) ? b2x_ba : l_ba; + l_len <= next_xfr_len; + l_rd_next <= {l_rd_next[5:0], rd_next}; + l_rd_start <= {l_rd_start[5:0], rd_start}; + l_rd_last <= {l_rd_last[5:0], rd_last}; + act_cmd <= (xfr_cmd == `SDR_ACTIVATE) ? 1'b1 : 1'b0; + d_act_cmd <= act_cmd; + xfr_st <= next_xfr_st; + end // else: !if(~reset_n) + + end // always @ (posedge clk) + + + always @ (*) begin + case (xfr_st) + + `XFR_IDLE : begin + + sel_mgmt = mgmt_req; + sel_b2x = ~mgmt_req & sdr_init_done & b2x_req; + i_xfr_cmd = `SDR_DESEL; + rd_next = ~mgmt_req & sdr_init_done & b2x_req & b2x_read; + wr_next = ~mgmt_req & sdr_init_done & b2x_req & b2x_write; + rdok = ~mgmt_req; + cb_pre_ok = 1'b1; + wrok = ~mgmt_req; + next_xfr_st = (mgmt_req | ~sdr_init_done) ? `XFR_IDLE : + (~b2x_req) ? `XFR_IDLE : + (b2x_read) ? `XFR_READ : + (b2x_write) ? `XFR_WRITE : `XFR_IDLE; + + end // case: `XFR_IDLE + + `XFR_READ : begin + rd_next = ~l_xfr_end | + l_xfr_end & ~mgmt_req & b2x_req & b2x_read; + wr_next = 1'b0; + rdok = l_xfr_end & ~mgmt_req; + // Break the timing path for FPGA Based Design + cb_pre_ok = (`TARGET_DESIGN == `FPGA) ? 1'b0 : l_xfr_end; + wrok = 1'b0; + sel_mgmt = 1'b0; + + if (l_xfr_end) begin // end of transfer + + if (~l_wrap) begin + // Current transfer was not wrap mode, may need BT + // If next cmd is a R or W or PRE to same bank allow + // it else issue BT + // This is a little pessimistic since BT is issued + // for non-wrap mode transfers even if the transfer + // ends on a burst boundary, but is felt to be of + // minimal performance impact. + + i_xfr_cmd = `SDR_BT; + sel_b2x = b2x_req & ~mgmt_req & (b2x_read | b2x_prechg_hit); + + end // if (~l_wrap) + + else begin + // Wrap mode transfer, by definition is end of burst + // boundary + + i_xfr_cmd = `SDR_DESEL; + sel_b2x = b2x_req & ~mgmt_req & ~b2x_write; + + end // else: !if(~l_wrap) + + next_xfr_st = (sdr_init_done) ? ((b2x_req & ~mgmt_req & b2x_read) ? `XFR_READ : `XFR_RDWT) : `XFR_IDLE; + + end // if (l_xfr_end) + + else begin + // Not end of transfer + // If current transfer was not wrap mode and we are at + // the start of a burst boundary issue another R cmd to + // step sequemtially thru memory, ELSE, + // issue precharge/activate commands from the bank control + + i_xfr_cmd = (burst_bdry & ~l_wrap) ? `SDR_READ : `SDR_DESEL; + sel_b2x = ~(burst_bdry & ~l_wrap) & b2x_req; + next_xfr_st = `XFR_READ; + + end // else: !if(l_xfr_end) + + end // case: `XFR_READ + + `XFR_RDWT : begin + rd_next = ~mgmt_req & b2x_req & b2x_read; + wr_next = rd_pipe_mt & ~mgmt_req & b2x_req & b2x_write; + rdok = ~mgmt_req; + cb_pre_ok = 1'b1; + wrok = rd_pipe_mt & ~mgmt_req; + + sel_mgmt = mgmt_req; + + sel_b2x = ~mgmt_req & b2x_req; + + i_xfr_cmd = `SDR_DESEL; + + next_xfr_st = (~mgmt_req & b2x_req & b2x_read) ? `XFR_READ : + (~rd_pipe_mt) ? `XFR_RDWT : + (~mgmt_req & b2x_req & b2x_write) ? `XFR_WRITE : + `XFR_IDLE; + + end // case: `XFR_RDWT + + `XFR_WRITE : begin + rd_next = l_xfr_end & ~mgmt_req & b2x_req & b2x_read; + wr_next = ~l_xfr_end | + l_xfr_end & ~mgmt_req & b2x_req & b2x_write; + rdok = l_xfr_end & ~mgmt_req; + cb_pre_ok = 1'b0; + wrok = l_xfr_end & ~mgmt_req; + sel_mgmt = 1'b0; + + if (l_xfr_end) begin // End of transfer + + if (~l_wrap) begin + // Current transfer was not wrap mode, may need BT + // If next cmd is a R or W allow it else issue BT + // This is a little pessimistic since BT is issued + // for non-wrap mode transfers even if the transfer + // ends on a burst boundary, but is felt to be of + // minimal performance impact. + + + sel_b2x = b2x_req & ~mgmt_req & (b2x_read | b2x_write); + i_xfr_cmd = `SDR_BT; + end // if (~l_wrap) + + else begin + // Wrap mode transfer, by definition is end of burst + // boundary + + sel_b2x = b2x_req & ~mgmt_req & ~b2x_prechg_hit; + i_xfr_cmd = `SDR_DESEL; + end // else: !if(~l_wrap) + + next_xfr_st = (~mgmt_req & b2x_req & b2x_read) ? `XFR_READ : + (~mgmt_req & b2x_req & b2x_write) ? `XFR_WRITE : + `XFR_IDLE; + + end // if (l_xfr_end) + + else begin + // Not end of transfer + // If current transfer was not wrap mode and we are at + // the start of a burst boundary issue another R cmd to + // step sequemtially thru memory, ELSE, + // issue precharge/activate commands from the bank control + + if (burst_bdry & ~l_wrap) begin + sel_b2x = 1'b0; + i_xfr_cmd = `SDR_WRITE; + end // if (burst_bdry & ~l_wrap) + + else begin + sel_b2x = b2x_req & ~mgmt_req; + i_xfr_cmd = `SDR_DESEL; + end // else: !if(burst_bdry & ~l_wrap) + + next_xfr_st = `XFR_WRITE; + end // else: !if(l_xfr_end) + + end // case: `XFR_WRITE + + endcase // case(xfr_st) + + end // always @ (xfr_st or ...) + + // signals to bank_ctl (x2b_refresh, x2b_act_ok, x2b_rdok, x2b_wrok, + // x2b_pre_ok[3:0] + + assign x2b_refresh = (xfr_cmd == `SDR_REFRESH) ? 1'b1 : 1'b0; + + assign x2b_act_ok = ~act_cmd & ~d_act_cmd; + + assign x2b_rdok = rdok; + + assign x2b_wrok = wrok; + + //assign x2b_pre_ok[0] = (l_ba == 2'b00) ? cb_pre_ok : 1'b1; + //assign x2b_pre_ok[1] = (l_ba == 2'b01) ? cb_pre_ok : 1'b1; + //assign x2b_pre_ok[2] = (l_ba == 2'b10) ? cb_pre_ok : 1'b1; + //assign x2b_pre_ok[3] = (l_ba == 2'b11) ? cb_pre_ok : 1'b1; + + assign x2b_pre_ok[0] = cb_pre_ok; + assign x2b_pre_ok[1] = cb_pre_ok; + assign x2b_pre_ok[2] = cb_pre_ok; + assign x2b_pre_ok[3] = cb_pre_ok; + assign last_burst = (ld_xfr) ? b2x_last : l_last; + + /************************************************************************/ + // APP Data I/F + + wire [SDR_DW-1:0] x2a_rddt; + + //assign x2a_start = (ld_xfr) ? b2x_start : l_start; + assign x2a_rdstart = d_rd_start; + assign x2a_wrstart = wr_start; + + assign x2a_rdlast = d_rd_last; + assign x2a_wrlast = wr_last; + + assign x2a_id = (ld_xfr) ? b2x_id : l_id; + + assign x2a_rddt = sdr_din; + + assign x2a_wrnext = wr_next; + + assign x2a_rdok = d_rd_next; + + /************************************************************************/ + // SDRAM I/F + + reg sdr_cs_n, sdr_cke, sdr_ras_n, sdr_cas_n, + sdr_we_n; + reg [SDR_BW-1:0] sdr_dqm; + reg [1:0] sdr_ba; + reg [12:0] sdr_addr; + reg [SDR_DW-1:0] sdr_dout; + reg [SDR_BW-1:0] sdr_den_n; + + always @ (posedge clk) + if (~reset_n) begin + sdr_cs_n <= 1'b1; + sdr_cke <= 1'b1; + sdr_ras_n <= 1'b1; + sdr_cas_n <= 1'b1; + sdr_we_n <= 1'b1; + sdr_dqm <= {SDR_BW{1'b1}}; + sdr_den_n <= {SDR_BW{1'b1}}; + end // if (~reset_n) + else begin + sdr_cs_n <= xfr_cmd[3]; + sdr_ras_n <= xfr_cmd[2]; + sdr_cas_n <= xfr_cmd[1]; + sdr_we_n <= xfr_cmd[0]; + sdr_cke <= (xfr_st != `XFR_IDLE) ? 1'b1 : + ~(mgmt_idle & b2x_idle & r2x_idle); + sdr_dqm <= (wr_next) ? a2x_wren_n : {SDR_BW{1'b0}}; + sdr_den_n <= (wr_next) ? {SDR_BW{1'b0}} : {SDR_BW{1'b1}}; + end // else: !if(~reset_n) + + always @ (posedge clk) begin + + if (~xfr_cmd[3]) begin + sdr_addr <= xfr_addr; + sdr_ba <= xfr_ba; + end // if (~xfr_cmd[3]) + + sdr_dout <= (wr_next) ? a2x_wrdt : sdr_dout; + + end // always @ (posedge clk) + + /************************************************************************/ + // Refresh and Initialization + + `define MGM_POWERUP 3'b000 + `define MGM_PRECHARGE 3'b001 + `define MGM_PCHWT 3'b010 + `define MGM_REFRESH 3'b011 + `define MGM_REFWT 3'b100 + `define MGM_MODE_REG 3'b101 + `define MGM_MODE_WT 3'b110 + `define MGM_ACTIVE 3'b111 + + reg [2:0] mgmt_st, next_mgmt_st; + reg [3:0] tmr0, tmr0_d; + reg [3:0] cntr1, cntr1_d; + wire tmr0_tc, cntr1_tc, rfsh_timer_tc, ref_req, precharge_ok; + reg ld_tmr0, ld_cntr1, dec_cntr1, set_sdr_init_done; + reg [`SDR_RFSH_TIMER_W-1 : 0] rfsh_timer; + reg [`SDR_RFSH_ROW_CNT_W-1:0] rfsh_row_cnt; + + always @ (posedge clk) + if (~reset_n) begin + mgmt_st <= `MGM_POWERUP; + tmr0 <= 4'b0; + cntr1 <= 4'h7; + rfsh_timer <= 0; + rfsh_row_cnt <= 0; + sdr_init_done <= 1'b0; + end // if (~reset_n) + else begin + mgmt_st <= next_mgmt_st; + tmr0 <= (ld_tmr0) ? tmr0_d : + (~tmr0_tc) ? tmr0 - 1 : tmr0; + cntr1 <= (ld_cntr1) ? cntr1_d : + (dec_cntr1) ? cntr1 - 1 : cntr1; + sdr_init_done <= (set_sdr_init_done | sdr_init_done) & sdram_enable; + rfsh_timer <= (rfsh_timer_tc) ? 0 : rfsh_timer + 1; + rfsh_row_cnt <= (~set_sdr_init_done) ? 0 : + (rfsh_timer_tc) ? rfsh_row_cnt + 1 : rfsh_row_cnt; + end // else: !if(~reset_n) + + assign tmr0_tc = ~|tmr0; + + assign cntr1_tc = ~|cntr1; + + assign rfsh_timer_tc = (rfsh_timer == rfsh_time) ? 1'b1 : 1'b0; + + assign ref_req = (rfsh_row_cnt >= rfsh_rmax) ? 1'b1 : 1'b0; + + assign precharge_ok = cb_pre_ok & b2x_tras_ok; + + assign xfr_bank_sel = l_ba; + + always @ (mgmt_st or sdram_enable or mgmt_ack or trp_delay or tmr0_tc or + cntr1_tc or trcar_delay or rfsh_row_cnt or ref_req or sdr_init_done + or precharge_ok or sdram_mode_reg) begin + + case (mgmt_st) // synopsys full_case parallel_case + + `MGM_POWERUP : begin + mgmt_idle = 1'b0; + mgmt_req = 1'b0; + mgmt_cmd = `SDR_DESEL; + mgmt_ba = 2'b0; + mgmt_addr = 13'h400; // A10 = 1 => all banks + ld_tmr0 = 1'b0; + tmr0_d = 4'b0; + dec_cntr1 = 1'b0; + ld_cntr1 = 1'b1; + cntr1_d = 4'hf; // changed for sdrams with higher refresh cycles during initialization + set_sdr_init_done = 1'b0; + next_mgmt_st = (sdram_enable) ? `MGM_PRECHARGE : `MGM_POWERUP; + end // case: `MGM_POWERUP + + `MGM_PRECHARGE : begin // Precharge all banks + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = (precharge_ok) ? `SDR_PRECHARGE : `SDR_DESEL; + mgmt_ba = 2'b0; + mgmt_addr = 13'h400; // A10 = 1 => all banks + ld_tmr0 = mgmt_ack; + tmr0_d = trp_delay; + ld_cntr1 = 1'b0; + cntr1_d = 4'h7; + dec_cntr1 = 1'b0; + set_sdr_init_done = 1'b0; + next_mgmt_st = (precharge_ok & mgmt_ack) ? `MGM_PCHWT : `MGM_PRECHARGE; + end // case: `MGM_PRECHARGE + + `MGM_PCHWT : begin // Wait for Trp + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_DESEL; + mgmt_ba = 2'b0; + mgmt_addr = 13'h400; // A10 = 1 => all banks + ld_tmr0 = 1'b0; + tmr0_d = trp_delay; + ld_cntr1 = 1'b0; + cntr1_d = 4'b0; + dec_cntr1 = 1'b0; + set_sdr_init_done = 1'b0; + next_mgmt_st = (tmr0_tc) ? `MGM_REFRESH : `MGM_PCHWT; + end // case: `MGM_PRECHARGE + + `MGM_REFRESH : begin // Refresh + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_REFRESH; + mgmt_ba = 2'b0; + mgmt_addr = 13'h400; // A10 = 1 => all banks + ld_tmr0 = mgmt_ack; + tmr0_d = trcar_delay; + dec_cntr1 = mgmt_ack; + ld_cntr1 = 1'b0; + cntr1_d = 4'h7; + set_sdr_init_done = 1'b0; + next_mgmt_st = (mgmt_ack) ? `MGM_REFWT : `MGM_REFRESH; + end // case: `MGM_REFRESH + + `MGM_REFWT : begin // Wait for trcar + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_DESEL; + mgmt_ba = 2'b0; + mgmt_addr = 13'h400; // A10 = 1 => all banks + ld_tmr0 = 1'b0; + tmr0_d = trcar_delay; + dec_cntr1 = 1'b0; + ld_cntr1 = 1'b0; + cntr1_d = 4'h7; + set_sdr_init_done = 1'b0; + next_mgmt_st = (~tmr0_tc) ? `MGM_REFWT : + (~cntr1_tc) ? `MGM_REFRESH : + (sdr_init_done) ? `MGM_ACTIVE : `MGM_MODE_REG; + end // case: `MGM_REFWT + + `MGM_MODE_REG : begin // Program mode Register & wait for + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_MODE; + mgmt_ba = {1'b0, sdram_mode_reg[11]}; + mgmt_addr = sdram_mode_reg; + ld_tmr0 = mgmt_ack; + tmr0_d = 4'h7; + dec_cntr1 = 1'b0; + ld_cntr1 = 1'b0; + cntr1_d = 4'h7; + set_sdr_init_done = 1'b0; + next_mgmt_st = (mgmt_ack) ? `MGM_MODE_WT : `MGM_MODE_REG; + end // case: `MGM_MODE_REG + + `MGM_MODE_WT : begin // Wait for tMRD + mgmt_idle = 1'b0; + mgmt_req = 1'b1; + mgmt_cmd = `SDR_DESEL; + mgmt_ba = 2'bx; + mgmt_addr = 13'bx; + ld_tmr0 = 1'b0; + tmr0_d = 4'h7; + dec_cntr1 = 1'b0; + ld_cntr1 = 1'b0; + cntr1_d = 4'h7; + set_sdr_init_done = 1'b0; + next_mgmt_st = (~tmr0_tc) ? `MGM_MODE_WT : `MGM_ACTIVE; + end // case: `MGM_MODE_WT + + `MGM_ACTIVE : begin // Wait for ref_req + mgmt_idle = ~ref_req; + mgmt_req = 1'b0; + mgmt_cmd = `SDR_DESEL; + mgmt_ba = 2'bx; + mgmt_addr = 13'bx; + ld_tmr0 = 1'b0; + tmr0_d = 4'h7; + dec_cntr1 = 1'b0; + ld_cntr1 = ref_req; + cntr1_d = rfsh_row_cnt; + set_sdr_init_done = 1'b1; + next_mgmt_st = (~sdram_enable) ? `MGM_POWERUP : + (ref_req) ? `MGM_PRECHARGE : `MGM_ACTIVE; + end // case: `MGM_MODE_WT + + endcase // case(mgmt_st) + + end // always @ (mgmt_st or ....) + + + +endmodule // sdr_xfr_ctl
caravel_yifive/verilog/rtl/sdram_ctrl/src/core/sdrc_xfr_ctl.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/sdram_ctrl/src/defs/sdrc_define.v =================================================================== --- caravel_yifive/verilog/rtl/sdram_ctrl/src/defs/sdrc_define.v (nonexistent) +++ caravel_yifive/verilog/rtl/sdram_ctrl/src/defs/sdrc_define.v (revision 19) @@ -0,0 +1,31 @@ + +`define SDR_REQ_ID_W 4 + +`define SDR_RFSH_TIMER_W 12 +`define SDR_RFSH_ROW_CNT_W 3 + +// B2X Command + +`define OP_PRE 2'b00 +`define OP_ACT 2'b01 +`define OP_RD 2'b10 +`define OP_WR 2'b11 + +// SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N) + +`define SDR_DESEL 4'b1111 +`define SDR_NOOP 4'b0111 +`define SDR_ACTIVATE 4'b0011 +`define SDR_READ 4'b0101 +`define SDR_WRITE 4'b0100 +`define SDR_BT 4'b0110 +`define SDR_PRECHARGE 4'b0010 +`define SDR_REFRESH 4'b0001 +`define SDR_MODE 4'b0000 + +`define ASIC 1'b1 +`define FPGA 1'b0 +`define TARGET_DESIGN `FPGA +// 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits +`define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width +
caravel_yifive/verilog/rtl/sdram_ctrl/src/defs/sdrc_define.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/sdram_ctrl/src/top/sdrc_top.v =================================================================== --- caravel_yifive/verilog/rtl/sdram_ctrl/src/top/sdrc_top.v (nonexistent) +++ caravel_yifive/verilog/rtl/sdram_ctrl/src/top/sdrc_top.v (revision 19) @@ -0,0 +1,297 @@ +/********************************************************************* + + SDRAM Controller top File + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SDRAM Controller Top Module. + Support 81/6/32 Bit SDRAM. + Column Address is Programmable + Bank Bit are 2 Bit + Row Bits are 12 Bits + + This block integrate following sub modules + + sdrc_core + SDRAM Controller file + wb2sdrc + This module transalate the bus protocl from wishbone to custome + sdram controller + + To Do: + nothing + + Author(s): Dinesh Annayya, dinesha@opencores.org + Version : 0.0 - 8th Jan 2012 + Initial version with 16/32 Bit SDRAM Support + : 0.1 - 24th Jan 2012 + 8 Bit SDRAM Support is added + 0.2 - 31st Jan 2012 + sdram_dq and sdram_pad_clk are internally generated + 0.3 - 26th April 2013 + Sdram Address witdh is increased from 12 to 13bits + + + 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_define.v" +module sdrc_top + ( + cfg_sdr_width , + cfg_colbits , + + // WB bus + wb_rst_i , + wb_clk_i , + + wb_stb_i , + wb_ack_o , + wb_addr_i , + wb_we_i , + wb_dat_i , + wb_sel_i , + wb_dat_o , + wb_cyc_i , + wb_cti_i , + + + /* Interface to SDRAMs */ + sdram_clk , + sdram_resetn , + sdr_cs_n , + sdr_cke , + sdr_ras_n , + sdr_cas_n , + sdr_we_n , + sdr_dqm , + sdr_ba , + sdr_addr , + sdr_dq , + + /* Parameters */ + sdr_init_done , + cfg_req_depth , //how many req. buffer should hold + cfg_sdr_en , + cfg_sdr_mode_reg , + cfg_sdr_tras_d , + cfg_sdr_trp_d , + cfg_sdr_trcd_d , + cfg_sdr_cas , + cfg_sdr_trcar_d , + cfg_sdr_twr_d , + cfg_sdr_rfsh , + cfg_sdr_rfmax + ); + +parameter APP_AW = 26; // 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 + +parameter dw = 32; // data width +parameter tw = 8; // tag id width +parameter bl = 9; // burst_lenght_width + +//----------------------------------------------- +// Global Variable +// ---------------------------------------------- +input sdram_clk ; // SDRAM Clock +input sdram_resetn ; // Reset Signal +input [1:0] cfg_sdr_width ; // 2'b00 - 32 Bit SDR, 2'b01 - 16 Bit SDR, 2'b1x - 8 Bit +input [1:0] cfg_colbits ; // 2'b00 - 8 Bit column address, + // 2'b01 - 9 Bit, 10 - 10 bit, 11 - 11Bits + +//-------------------------------------- +// Wish Bone Interface +// ------------------------------------- +input wb_rst_i ; +input wb_clk_i ; + +input wb_stb_i ; +output wb_ack_o ; +input [APP_AW-1:0] wb_addr_i ; +input wb_we_i ; // 1 - Write, 0 - Read +input [dw-1:0] wb_dat_i ; +input [dw/8-1:0] wb_sel_i ; // Byte enable +output [dw-1:0] wb_dat_o ; +input wb_cyc_i ; +input [2:0] wb_cti_i ; + +//------------------------------------------------ +// Interface to SDRAMs +//------------------------------------------------ +output sdr_cke ; // SDRAM CKE +output sdr_cs_n ; // SDRAM Chip Select +output sdr_ras_n ; // SDRAM ras +output sdr_cas_n ; // SDRAM cas +output sdr_we_n ; // SDRAM write enable +output [SDR_BW-1:0] sdr_dqm ; // SDRAM Data Mask +output [1:0] sdr_ba ; // SDRAM Bank Enable +output [12:0] sdr_addr ; // SDRAM Address +inout [SDR_DW-1:0] sdr_dq ; // SDRA Data Input/output + +//------------------------------------------------ +// Configuration Parameter +//------------------------------------------------ +output sdr_init_done ; // Indicate SDRAM Initialisation Done +input [3:0] cfg_sdr_tras_d ; // Active to precharge delay +input [3:0] cfg_sdr_trp_d ; // Precharge to active delay +input [3:0] cfg_sdr_trcd_d ; // Active to R/W delay +input cfg_sdr_en ; // Enable SDRAM controller +input [1:0] cfg_req_depth ; // Maximum Request accepted by SDRAM controller +input [12:0] cfg_sdr_mode_reg ; +input [2:0] cfg_sdr_cas ; // SDRAM CAS Latency +input [3:0] cfg_sdr_trcar_d ; // Auto-refresh period +input [3:0] cfg_sdr_twr_d ; // Write recovery delay +input [`SDR_RFSH_TIMER_W-1 : 0] cfg_sdr_rfsh; +input [`SDR_RFSH_ROW_CNT_W -1 : 0] cfg_sdr_rfmax; + +//-------------------------------------------- +// SDRAM controller Interface +//-------------------------------------------- +wire app_req ; // SDRAM request +wire [APP_AW-1:0] app_req_addr ; // SDRAM Request Address +wire [bl-1:0] app_req_len ; +wire app_req_wr_n ; // 0 - Write, 1 -> Read +wire app_req_ack ; // SDRAM request Accepted +wire app_busy_n ; // 0 -> sdr busy +wire [dw/8-1:0] app_wr_en_n ; // Active low sdr byte-wise write data valid +wire app_wr_next_req ; // Ready to accept the next write +wire app_rd_valid ; // sdr read valid +wire app_last_rd ; // Indicate last Read of Burst Transfer +wire app_last_wr ; // Indicate last Write of Burst Transfer +wire [dw-1:0] app_wr_data ; // sdr write data +wire [dw-1:0] app_rd_data ; // sdr read data + +/**************************************** +* These logic has to be implemented using Pads +* **************************************/ +wire [SDR_DW-1:0] pad_sdr_din ; // SDRA Data Input +wire [SDR_DW-1:0] sdr_dout ; // SDRAM Data Output +wire [SDR_BW-1:0] sdr_den_n ; // SDRAM Data Output enable + + +assign sdr_dq = (&sdr_den_n == 1'b0) ? sdr_dout : {SDR_DW{1'bz}}; +assign pad_sdr_din = sdr_dq; + +// sdram pad clock is routed back through pad +// SDRAM Clock from Pad, used for registering Read Data +wire #(1.0) sdram_pad_clk = sdram_clk; + +/************** Ends Here **************************/ +wb2sdrc #(.dw(dw),.tw(tw),.bl(bl)) u_wb2sdrc ( + // WB bus + .wb_rst_i (wb_rst_i ) , + .wb_clk_i (wb_clk_i ) , + + .wb_stb_i (wb_stb_i ) , + .wb_ack_o (wb_ack_o ) , + .wb_addr_i (wb_addr_i ) , + .wb_we_i (wb_we_i ) , + .wb_dat_i (wb_dat_i ) , + .wb_sel_i (wb_sel_i ) , + .wb_dat_o (wb_dat_o ) , + .wb_cyc_i (wb_cyc_i ) , + .wb_cti_i (wb_cti_i ) , + + + //SDRAM Controller Hand-Shake Signal + .sdram_clk (sdram_clk ) , + .sdram_resetn (sdram_resetn ) , + .sdr_req (app_req ) , + .sdr_req_addr (app_req_addr ) , + .sdr_req_len (app_req_len ) , + .sdr_req_wr_n (app_req_wr_n ) , + .sdr_req_ack (app_req_ack ) , + .sdr_busy_n (app_busy_n ) , + .sdr_wr_en_n (app_wr_en_n ) , + .sdr_wr_next (app_wr_next_req ) , + .sdr_rd_valid (app_rd_valid ) , + .sdr_last_rd (app_last_rd ) , + .sdr_wr_data (app_wr_data ) , + .sdr_rd_data (app_rd_data ) + + ); + + +sdrc_core #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_sdrc_core ( + .clk (sdram_clk ) , + .pad_clk (sdram_pad_clk ) , + .reset_n (sdram_resetn ) , + .sdr_width (cfg_sdr_width ) , + .cfg_colbits (cfg_colbits ) , + + /* Request from app */ + .app_req (app_req ) ,// Transfer Request + .app_req_addr (app_req_addr ) ,// SDRAM Address + .app_req_len (app_req_len ) ,// Burst Length (in 16 bit words) + .app_req_wrap (1'b0 ) ,// Wrap mode request + .app_req_wr_n (app_req_wr_n ) ,// 0 => Write request, 1 => read req + .app_req_ack (app_req_ack ) ,// Request has been accepted + .cfg_req_depth (cfg_req_depth ) ,//how many req. buffer should hold + + .app_wr_data (app_wr_data ) , + .app_wr_en_n (app_wr_en_n ) , + .app_rd_data (app_rd_data ) , + .app_rd_valid (app_rd_valid ) , + .app_last_rd (app_last_rd ) , + .app_last_wr (app_last_wr ) , + .app_wr_next_req (app_wr_next_req ) , + .sdr_init_done (sdr_init_done ) , + .app_req_dma_last (app_req ) , + + /* Interface to SDRAMs */ + .sdr_cs_n (sdr_cs_n ) , + .sdr_cke (sdr_cke ) , + .sdr_ras_n (sdr_ras_n ) , + .sdr_cas_n (sdr_cas_n ) , + .sdr_we_n (sdr_we_n ) , + .sdr_dqm (sdr_dqm ) , + .sdr_ba (sdr_ba ) , + .sdr_addr (sdr_addr ) , + .pad_sdr_din (pad_sdr_din ) , + .sdr_dout (sdr_dout ) , + .sdr_den_n (sdr_den_n ) , + + /* Parameters */ + .cfg_sdr_en (cfg_sdr_en ) , + .cfg_sdr_mode_reg (cfg_sdr_mode_reg ) , + .cfg_sdr_tras_d (cfg_sdr_tras_d ) , + .cfg_sdr_trp_d (cfg_sdr_trp_d ) , + .cfg_sdr_trcd_d (cfg_sdr_trcd_d ) , + .cfg_sdr_cas (cfg_sdr_cas ) , + .cfg_sdr_trcar_d (cfg_sdr_trcar_d ) , + .cfg_sdr_twr_d (cfg_sdr_twr_d ) , + .cfg_sdr_rfsh (cfg_sdr_rfsh ) , + .cfg_sdr_rfmax (cfg_sdr_rfmax ) + ); + +endmodule // sdrc_core
caravel_yifive/verilog/rtl/sdram_ctrl/src/top/sdrc_top.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/sdram_ctrl/src/wb2sdrc/wb2sdrc.v =================================================================== --- caravel_yifive/verilog/rtl/sdram_ctrl/src/wb2sdrc/wb2sdrc.v (nonexistent) +++ caravel_yifive/verilog/rtl/sdram_ctrl/src/wb2sdrc/wb2sdrc.v (revision 19) @@ -0,0 +1,371 @@ +/********************************************************************* + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: WISHBONE to SDRAM Controller Bus Transalator + 1. This module translate the WISHBONE protocol to custom sdram controller i/f + 2. Also Handle the clock domain change from Application layer to Sdram layer + + To Do: + nothing + + Author(s): Dinesh Annayya, dinesha@opencores.org + Version : 0.0 - Initial Release + 0.1 - 2nd Feb 2012 + Async Fifo towards the application layer is selected + with Registered Full Generation + 0.2 - 2nd Feb 2012 + Pending Read generation bug fix done to handle backto back write + followed by read request + + 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 + +*******************************************************************/ + + +module wb2sdrc ( + // WB bus + wb_rst_i , + wb_clk_i , + + wb_stb_i , + wb_ack_o , + wb_addr_i , + wb_we_i , + wb_dat_i , + wb_sel_i , + wb_dat_o , + wb_cyc_i , + wb_cti_i , + + + //SDRAM Controller Hand-Shake Signal + sdram_clk , + sdram_resetn , + sdr_req , + sdr_req_addr , + sdr_req_len , + sdr_req_wr_n , + sdr_req_ack , + sdr_busy_n , + sdr_wr_en_n , + sdr_wr_next , + sdr_rd_valid , + sdr_last_rd , + sdr_wr_data , + sdr_rd_data + + ); + +parameter dw = 32; // data width +parameter tw = 8; // tag id width +parameter bl = 9; // burst_lenght_width +parameter APP_AW = 26; // Application Address Width +//-------------------------------------- +// Wish Bone Interface +// ------------------------------------- +input wb_rst_i ; +input wb_clk_i ; + +input wb_stb_i ; +output wb_ack_o ; +input [APP_AW-1:0] wb_addr_i ; +input wb_we_i ; // 1 - Write , 0 - Read +input [dw-1:0] wb_dat_i ; +input [dw/8-1:0] wb_sel_i ; // Byte enable +output [dw-1:0] wb_dat_o ; +input wb_cyc_i ; +input [2:0] wb_cti_i ; +/*************************************************** +The Cycle Type Idenfier [CTI_IO()] Address Tag provides +additional information about the current cycle. +The MASTER sends this information to the SLAVE. The SLAVE can use this +information to prepare the response for the next cycle. +Table 4-2 Cycle Type Identifiers +CTI_O(2:0) Description +‘000’ Classic cycle. +‘001’ Constant address burst cycle +‘010’ Incrementing burst cycle +‘011’ Reserved +‘100’ Reserved +‘101 Reserved +‘110’ Reserved +‘111’ End-of-Burst +****************************************************/ +//-------------------------------------------- +// SDRAM controller Interface +//-------------------------------------------- +input sdram_clk ; // sdram clock +input sdram_resetn ; // sdram reset +output sdr_req ; // SDRAM request +output [APP_AW-1:0] sdr_req_addr ; // SDRAM Request Address +output [bl-1:0] sdr_req_len ; +output sdr_req_wr_n ; // 0 - Write, 1 -> Read +input sdr_req_ack ; // SDRAM request Accepted +input sdr_busy_n ; // 0 -> sdr busy +output [dw/8-1:0] sdr_wr_en_n ; // Active low sdr byte-wise write data valid +input sdr_wr_next ; // Ready to accept the next write +input sdr_rd_valid ; // sdr read valid +input sdr_last_rd ; // Indicate last Read of Burst Transfer +output [dw-1:0] sdr_wr_data ; // sdr write data +input [dw-1:0] sdr_rd_data ; // sdr read data + +//---------------------------------------------------- +// Wire Decleration +// --------------------------------------------------- +wire cmdfifo_full ; +wire cmdfifo_empty ; +wire wrdatafifo_full ; +wire wrdatafifo_empty ; +wire tagfifo_full ; +wire tagfifo_empty ; +wire rddatafifo_empty ; +wire rddatafifo_full ; + +reg pending_read ; + + +//----------------------------------------------------------------------------- +// Ack Generaltion Logic +// If Write Request - Acknowledge if the command and write FIFO are not full +// If Read Request - Generate the Acknowledgment once read fifo has data +// available +//----------------------------------------------------------------------------- + +assign wb_ack_o = (wb_stb_i && wb_cyc_i && wb_we_i) ? // Write Phase + ((!cmdfifo_full) && (!wrdatafifo_full)) : + (wb_stb_i && wb_cyc_i && !wb_we_i) ? // Read Phase + !rddatafifo_empty : 1'b0; + +//--------------------------------------------------------------------------- +// Command FIFO Write Generation +// If Write Request - Generate write, when Write fifo and command fifo is +// not full +// If Read Request - Generate write, when command fifo not full and there +// is no pending read request. +//--------------------------------------------------------------------------- +wire cmdfifo_wr = (wb_stb_i && wb_cyc_i && wb_we_i && (!cmdfifo_full) ) ? wb_ack_o : + (wb_stb_i && wb_cyc_i && !wb_we_i && (!cmdfifo_full)) ? !pending_read: 1'b0 ; + +//--------------------------------------------------------------------------- +// command fifo read generation +// Command FIFo read will be generated, whenever SDRAM Controller +// Acknowldge the Request +//---------------------------------------------------------------------------- + +wire cmdfifo_rd = sdr_req_ack; + +//--------------------------------------------------------------------------- +// Application layer request is generated towards the controller, whenever +// Command FIFO is not full +// -------------------------------------------------------------------------- +assign sdr_req = !cmdfifo_empty; + +//---------------------------------------------------------------------------- +// Since Burst length is not known at the start of the Burst, It's assumed as +// Single Cycle Burst. We need to improvise this ... +// -------------------------------------------------------------------------- +wire [bl-1:0] burst_length = 1; // 0 Mean 1 Transfer + +//----------------------------------------------------------------------------- +// In Wish Bone Spec, For Read Request has to be acked along with data. +// We need to identify the pending read request. +// Once we accept the read request, we should not accept one more read +// request, untill we have transmitted the read data. +// Pending Read will +// set - with Read Request +// reset - with Read Request + Ack +// ---------------------------------------------------------------------------- +always @(posedge wb_rst_i or posedge wb_clk_i) begin + if(wb_rst_i) begin + pending_read <= 1'b0; + end else begin + //pending_read <= wb_stb_i & wb_cyc_i & !wb_we_i & !wb_ack_o; + pending_read <= (cmdfifo_wr && !wb_we_i) ? 1'b1: + (wb_stb_i & wb_cyc_i & !wb_we_i & wb_ack_o) ? 1'b0: pending_read; + end +end + +//--------------------------------------------------------------------- +// Async Command FIFO. This block handle the clock domain change from +// Application layer to SDRAM Controller +// ------------------------------------------------------------------ + // Address + Burst Length + W/R Request + async_fifo #(.W(APP_AW+bl+1),.DP(4),.WR_FAST(1'b0), .RD_FAST(1'b0)) u_cmdfifo ( + // Write Path Sys CLock Domain + .wr_clk (wb_clk_i ), + .wr_reset_n (!wb_rst_i ), + .wr_en (cmdfifo_wr ), + .wr_data ({burst_length, + !wb_we_i, + wb_addr_i} ), + .afull ( ), + .full (cmdfifo_full ), + + // Read Path, SDRAM clock domain + .rd_clk (sdram_clk ), + .rd_reset_n (sdram_resetn ), + .aempty ( ), + .empty (cmdfifo_empty ), + .rd_en (cmdfifo_rd ), + .rd_data ({sdr_req_len, + sdr_req_wr_n, + sdr_req_addr} ) + ); + +// synopsys translate_off +always @(posedge wb_clk_i) begin + if (cmdfifo_full == 1'b1 && cmdfifo_wr == 1'b1) begin + $display("ERROR:%m COMMAND FIFO WRITE OVERFLOW"); + end +end +// synopsys translate_on +// synopsys translate_off +always @(posedge sdram_clk) begin + if (cmdfifo_empty == 1'b1 && cmdfifo_rd == 1'b1) begin + $display("ERROR:%m COMMAND FIFO READ OVERFLOW"); + end +end +// synopsys translate_on + +//--------------------------------------------------------------------- +// Write Data FIFO Write Generation, when ever Acked + Write Request +// Note: Ack signal generation already taking account of FIFO full condition +// --------------------------------------------------------------------- + +wire wrdatafifo_wr = wb_ack_o & wb_we_i ; + +//------------------------------------------------------------------------ +// Write Data FIFO Read Generation, When ever Next Write request generated +// from SDRAM Controller +// ------------------------------------------------------------------------ +wire wrdatafifo_rd = sdr_wr_next; + + +//------------------------------------------------------------------------ +// Async Write Data FIFO +// This block handle the clock domain change over + Write Data + Byte mask +// From Application layer to SDRAM controller layer +//------------------------------------------------------------------------ + + // Write DATA + Data Mask FIFO + async_fifo #(.W(dw+(dw/8)), .DP(8), .WR_FAST(1'b0), .RD_FAST(1'b1)) u_wrdatafifo ( + // Write Path , System clock domain + .wr_clk (wb_clk_i ), + .wr_reset_n (!wb_rst_i ), + .wr_en (wrdatafifo_wr ), + .wr_data ({~wb_sel_i, + wb_dat_i} ), + .afull ( ), + .full (wrdatafifo_full ), + + + // Read Path , SDRAM clock domain + .rd_clk (sdram_clk ), + .rd_reset_n (sdram_resetn ), + .aempty ( ), + .empty (wrdatafifo_empty ), + .rd_en (wrdatafifo_rd ), + .rd_data ({sdr_wr_en_n, + sdr_wr_data} ) + ); +// synopsys translate_off +always @(posedge wb_clk_i) begin + if (wrdatafifo_full == 1'b1 && wrdatafifo_wr == 1'b1) begin + $display("ERROR:%m WRITE DATA FIFO WRITE OVERFLOW"); + end +end + +always @(posedge sdram_clk) begin + if (wrdatafifo_empty == 1'b1 && wrdatafifo_rd == 1'b1) begin + $display("ERROR:%m WRITE DATA FIFO READ OVERFLOW"); + end +end +// synopsys translate_on + +// ------------------------------------------------------------------- +// READ DATA FIFO +// ------------------------------------------------------------------ +wire rd_eop; // last read indication + +// Read FIFO write generation, when ever SDRAM controller issues the read +// valid signal +wire rddatafifo_wr = sdr_rd_valid; + +// Read FIFO read generation, when ever ack is generated along with read +// request. +// Note: Ack generation is already accounted the write FIFO Not Empty +// condition +wire rddatafifo_rd = wb_ack_o & !wb_we_i; + +//------------------------------------------------------------------------- +// Async Read FIFO +// This block handles the clock domain change over + Read data from SDRAM +// controller to Application layer. +// Note: +// 1. READ DATA FIFO depth is kept small, assuming that Sys-CLock > SDRAM Clock +// READ DATA + EOP +// 2. EOP indicate, last transfer of Burst Read Access. use-full for future +// Tag handling per burst +// +// ------------------------------------------------------------------------ + async_fifo #(.W(dw+1), .DP(4), .WR_FAST(1'b0), .RD_FAST(1'b1) ) u_rddatafifo ( + // Write Path , SDRAM clock domain + .wr_clk (sdram_clk ), + .wr_reset_n (sdram_resetn ), + .wr_en (rddatafifo_wr ), + .wr_data ({sdr_last_rd, + sdr_rd_data} ), + .afull ( ), + .full (rddatafifo_full ), + + + // Read Path , SYS clock domain + .rd_clk (wb_clk_i ), + .rd_reset_n (!wb_rst_i ), + .empty (rddatafifo_empty ), + .aempty ( ), + .rd_en (rddatafifo_rd ), + .rd_data ({rd_eop, + wb_dat_o} ) + ); + +// synopsys translate_off +always @(posedge sdram_clk) begin + if (rddatafifo_full == 1'b1 && rddatafifo_wr == 1'b1) begin + $display("ERROR:%m READ DATA FIFO WRITE OVERFLOW"); + end +end + +always @(posedge wb_clk_i) begin + if (rddatafifo_empty == 1'b1 && rddatafifo_rd == 1'b1) begin + $display("ERROR:%m READ DATA FIFO READ OVERFLOW"); + end +end +// synopsys translate_on + + +endmodule
caravel_yifive/verilog/rtl/sdram_ctrl/src/wb2sdrc/wb2sdrc.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/sdram_ctrl/src/filelist_rtl.f =================================================================== --- caravel_yifive/verilog/rtl/sdram_ctrl/src/filelist_rtl.f (nonexistent) +++ caravel_yifive/verilog/rtl/sdram_ctrl/src/filelist_rtl.f (revision 19) @@ -0,0 +1,9 @@ +./top/sdrc_top.v +./wb2sdrc/wb2sdrc.v +../../lib/async_fifo.sv +./core/sdrc_core.v +./core/sdrc_bank_ctl.v +./core/sdrc_bank_fsm.v +./core/sdrc_bs_convert.v +./core/sdrc_req_gen.v +./core/sdrc_xfr_ctl.v
caravel_yifive/verilog/rtl/sdram_ctrl/src/filelist_rtl.f Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/sdram_ctrl/src/run_modelsim =================================================================== --- caravel_yifive/verilog/rtl/sdram_ctrl/src/run_modelsim (nonexistent) +++ caravel_yifive/verilog/rtl/sdram_ctrl/src/run_modelsim (revision 19) @@ -0,0 +1,2 @@ +vlib work +vlog -f filelist_rtl.f +incdir+./defs
caravel_yifive/verilog/rtl/sdram_ctrl/src/run_modelsim Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: caravel_yifive/verilog/rtl/syntacore/scr1/src/top/scr1_dmem_wb.sv =================================================================== --- caravel_yifive/verilog/rtl/syntacore/scr1/src/top/scr1_dmem_wb.sv (revision 18) +++ caravel_yifive/verilog/rtl/syntacore/scr1/src/top/scr1_dmem_wb.sv (revision 19) @@ -339,18 +339,17 @@ wire [SCR1_WB_WIDTH+SCR1_WB_WIDTH+3+4:0] req_fifo_din = {hbel_in,hwrite_in,hwidth_in,haddr_in,hwdata_in}; sync_fifo #( - .DATA_WIDTH(SCR1_WB_WIDTH+SCR1_WB_WIDTH+3+1+4), // Data Width - .ADDR_WIDTH(1), // Address Width - .FIFO_DEPTH(2) // FIFO DEPTH + .W(SCR1_WB_WIDTH+SCR1_WB_WIDTH+3+1+4), // Data Width + .D(2) // FIFO DEPTH ) u_req_fifo( - .dout (req_fifo_dout ), + .rd_data (req_fifo_dout ), - .rstn (rst_n ), + .reset_n (rst_n ), .clk (clk ), .wr_en (req_fifo_wr ), // Write .rd_en (req_fifo_rd ), // Read - .din (req_fifo_din ), + .wr_data (req_fifo_din ), .full (req_fifo_full ), .empty (req_fifo_empty ) );
/caravel_yifive/verilog/rtl/syntacore/scr1/src/top/scr1_imem_wb.sv
168,18 → 168,17
 
 
sync_fifo #(
.DATA_WIDTH(SCR1_WB_WIDTH), // Data Width
.ADDR_WIDTH(1), // Address Width
.FIFO_DEPTH(2) // FIFO DEPTH
.W(SCR1_WB_WIDTH), // Data Width
.D(2) // FIFO DEPTH
) u_req_fifo(
 
.dout (req_fifo_dout ),
.rd_data (req_fifo_dout ),
 
.rstn (rst_n ),
.reset_n (rst_n ),
.clk (clk ),
.wr_en (req_fifo_wr ), // Write
.rd_en (req_fifo_rd ), // Read
.din (imem_addr ),
.wr_data (imem_addr ),
.full (req_fifo_full ),
.empty (req_fifo_empty )
);
/caravel_yifive/verilog/rtl/syntacore/scr1/src/wb_top.files
1,5 → 1,4
top/scr1_dmem_router.sv
top/scr1_imem_router.sv
top/scr1_dp_memory.sv
top/scr1_tcm.sv
top/scr1_timer.sv
6,4 → 5,4
top/scr1_dmem_wb.sv
top/scr1_imem_wb.sv
top/scr1_top_wb.sv
../../lib/sync_fifo.sv
../../../lib/sync_fifo.sv

powered by: WebSVN 2.1.0

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