blob: 6c06615c0960936b3710d86d9a1a5ce6e32c6ccf [file] [log] [blame]
//////////////////////////////////////////////////////////////////////////////
// SPDX-FileCopyrightText: 2021 , Dinesh Annayya
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileContributor: Created by Dinesh Annayya <dinesha@opencores.org>
//
/*********************************************************************
SDRAM Controller Core File
This file is part of the sdram controller project
https://github.com/dineshannayya/yifive_r0.git
http://www.opencores.org/cores/yifive/
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,
debug,
/* 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
output [21:0] debug ;
//------------------------------------------------
// 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 x2a_rdstart;
wire x2a_wrstart;
wire x2a_rdlast;
wire x2a_wrlast;
wire x2a_rdok;
wire x2a_wrnext;
wire x2b_ack;
wire x2b_refresh;
wire x2b_act_ok;
wire x2b_rdok;
wire x2b_wrok;
wire b2x_idle;
wire b2x_req;
wire b2x_start;
wire b2x_last;
wire b2x_wrap;
wire b2x_tras_ok;
wire b2r_ack;
wire b2r_arb_ok;
wire r2b_req;
wire r2b_start;
wire r2b_last;
wire r2b_wrap;
wire r2b_write;
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 r2x_idle;
//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 ;
assign debug = {r2x_idle,r2b_req,r2b_start,r2b_last,b2r_ack,b2r_arb_ok,r2b_write,
b2x_idle,b2x_req,b2x_start,b2x_wrap,x2b_ack,b2x_tras_ok,x2b_refresh,x2b_pre_ok,x2b_act_ok,
x2b_rdok,x2b_wrok,x2a_rdstart,x2a_wrstart,x2a_rdlast,x2a_wrlast};
// 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),.APP_AW(APP_AW)) 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