今天主要学习Sdram控制器框架设计
首先来看下整个控制器设计框图
如图1所示
(图1 FPGA内部程序框图)
接下来,分模块来看一下
1.1 时钟产生模块
1.11 实现方式
时钟的输入来源于外部晶振,时钟频率为25MHz,通过PLL产生数据源的时钟62.5MHz和sdram的工作时钟166MHz。另外还需要产生一个相移为180°的166MHz提供给下游芯片sdram,保证时钟在数据中间采样。
1.12 参数设计
参数设计如图2所示
(图2 PLL参数设计)
1.13 接口设计
1.14 重点问题
Locked信号需要等锁相环锁定时钟后,输出的时钟才能有效,此PLL设计使用的是高有效的复位。
1.2 数据源产生模块
1.21 实现方式
数据源产生模块使用PLL倍频出来的62.5MHz时钟,产生数据格式如下:
Addr[8:0] | 0 | 1 | 2 | … | 253 | 254 | 255 |
---|---|---|---|---|---|---|---|
Data[31:0] | 0 | 1 | 2 | … | 253 | 254 | sum |
1.22 顶层设计
En表示什么时候产生数据,顶层结构如图3所示。
(图3 数据源产生模块顶层设计)
1.23 接口设计
1.24 重点问题
产生的数据是以256为一块,最后一个数是前面所有数据的累加和。
1.3 Rdm读写模块
该模块XILINX公司提供的使用简单双端口RAM IP核。
该模块是跨时钟域处理,为了将数据源产生数据的时钟与写sdram操作时钟隔离。该ram控制器的深度为512,宽度为32bits,采用乒乓操作:首先将数据写入地址0~255,然后产生一个wrflag信号;然后再将地址写入256~511,此时产生一个rdflag信号,wrflag信号也要进行取反,表示正在写ram高地址,同时可以读取低地址的数据;因为读时钟快于写时钟,所以当低地址数据读完的时候,写数据可以继续写入低地址,此时可以读高地址的数据。关键控制代码如下:
assign wrflag=(wdatacnt > DATALENGTH-1)?1'b1:1'b0;
assign rdflag=(rdatacnt > DATALENGTH-1)?1'b1:1'b0;
ram控制器的顶层设计如下图4所示:
(图4 Ram乒乓控制器顶层设计)
module WramComtroller
#( parameter DATAWIDTH = 32 ,
parameter ADDRWIDTH = 9 ,
parameter DATALENGTH= 256
)
(
input Clk62M5,
input Clk166M,
input [DATAWIDTH-1:0] din,
input we,
input re,
output [DATAWIDTH-1:0] dout,
output valid
);
数据读出的时候落后时钟一个周期。
1.4 数据校验模块
将从sdram读出的数据进行校验,判断是否正确。
每次读取256个数据(sdram的一行),将前255个数据的累加和与第256个数据比较,如果相等,则表示无误码,led灯不点亮;否则,led保持亮1s。顶层框图如图5所示,valid表示输入的有效数据,led为1-bit输出点亮灯板。
(图5 数据校验顶层设计)
module ResultCheck
#(
parameter ADDRWIDTH = 9 ,
parameter DATAWIDTH = 32 ,
parameter DATALENGTH= 256
)
(
input Clk166M,
input valid,
input [`DQ_BITS-1 :0] data,
output led
);
Valid和数据是同时有效进入,然后进行逻辑操作。输出led如果有错,需要延迟1s。
1.5 Sdrm初始化模块
初始化的时序如图6所示:
(图6 sdram初始化时序)
初始化流程如下:
Ø 上电后要延时200us
Ø Precharge(预充电)所有bank
Ø 等待Trp时间进行 AUTO REFRESH(自动刷新)命令
Ø 等待Trfc时间再次进行AUTO REFRESH命令
Ø 等待Trfc时间进行load mode register命令
Ø 等待Tmrd时间进行ACTIVE命令
初始化顶层框图设计如图6所示。
(图6 初始化模块顶层设计)
module SdramInit
#(
parameter BURST_LENGTH = 3'b000,
parameter BT = 1'b0, //sequential
parameter CAS_LATENCY = 3'b011, //3(166MHz need 3 clocks)
parameter OP_MODE = 2'b00, //standard operation
parameter WRITE_BURST_MODE = 1'b0 //Programmed Burst Length
)
(
input Clk166M ,
output reg [3 :0 ] InitCmd ,
output reg [`ADDR_BITS-1:0 ] InitAddr ,
output reg [`BA_BITS-1 :0 ] InitBa ,
output reg InitDone
);
l 按照时序进行初始化设计
l 模式寄存器配置
l 各种命令组合
1.6 Sdrm刷新模块
刷新时序如图7所示:
(图7 刷新时序)
查手册可知,每两次刷新的最长时间间隔为15.625us,由此设置刷新计数器如下:
//------------------------------------------------------------------------------
// a row Refresh need 15625ns(max)
// refcnt = 15625ns / 6ns = 2604
// there I select refcnt = 2600
// 10'd2604 = 16'ha28
//------------------------------------------------------------------------------
刷新操作流程如下:
Ø Precharge active bank后
Ø 等待Trp时间进行 AUTO REFRESH(自动刷新)命令
Ø 等待Trfc时间再次进行AUTO REFRESH命令
顶层设计如图8所示,途中RefStart信号连接的是初始化完成信号,当初始化完成刷新计数器开始计数,隔一段进行刷新请求,等待仲裁模块响应。
(图8 刷新模块顶层设计)
module SdramRefresh(
input Clk166M ,
output RefReq ,
input RefEn ,
input RefStart ,
output reg [3 : 0] RefCmd ,
output reg [`ADDR_BITS-1: 0] RefAddr ,
output reg [`BA_BITS-1 : 0] RefBa ,
output reg RefDone
);
按照刷新的时序进行设计,而且必须保证在15.625us内进行刷新,否则电容掉电就会丢失数据。
1.7 Sdrm写入数据模块
Sdram写操作时序如图9所示。
(图9 写操作时序)
本模块的功能主要为实现在SDRAM中写入数据, 对于不同的写模式,需要在初始化模块进行配置。
写操作流程如下:
Ø 行激活(ACTIVE)
Ø 等待Trcd时间给出写命令
Ø 写数据
Ø 数据写入完成,Precharge(预充电)所在bank
顶层设计如图10所示,WrTrig信号为外部写请求信号,WrReq信号为写模块向仲裁模块申请,等待WrEn有效才能开始写。
(图10 写模块顶层设计)
module SdaramWrite
#(
parameter BURST_LENGTH = 3'b000,
parameter DATALENGTH= 256
)(
input Clk166M ,
input WrTrig ,
input WrEn ,
input [`DQ_BITS-1 : 0] InData ,
input [`DM_BITS-1 : 0] InDataDM,
output Wbusy , //fetch data from ram
output reg [3 : 0] WrCmd ,
output reg [`ADDR_BITS-1: 0] WrAddr ,
output reg [`BA_BITS-1 : 0] WrBa ,
output reg [`DQ_BITS-1 : 0] WrDq ,
output reg [`DM_BITS-1 : 0] WrDqm ,
output WrReq ,
output reg WrDone
);
l 数据写完必须进行预充电
l 写操作期间一直发送写命令
1.8 Sdrm写入数据模块
Sdram读操作时序如图11所示。
(图11 读操作时序)
该模块的功能主要为实现在SDRAM中读出数据。
读流程:
Ø 行激活(ACTIVE)
Ø 等待Trcd时间给出读命令和行地址
Ø 等待Tcl时间数据才能输出(潜伏期)
Ø 读取数据
Ø 数据读取完成,Precharge(预充电)所在bank
顶层设计如图12所示,OutData为数据输出,valid为数据输出有效信号。
(图12 读模块顶层设计)
module SdramRead
#(
parameter BURST_LENGTH = 3'b000,
parameter DATALENGTH= 256
)(
input Clk166M ,
input RdTrig ,
input RdEn ,
input [`DQ_BITS-1 : 0] RdDq , //data from sdram
output [`DM_BITS-1 : 0] RdDqm ,
output reg [`DQ_BITS-1 : 0] OutData ,
output valid ,
output Rbusy ,
output reg [3 : 0] RdCmd ,
output reg [`ADDR_BITS-1: 0] RdAddr ,
output reg [`BA_BITS-1 : 0] RdBa ,
output RdReq ,
output reg RdDone
);
潜伏期设置(Tcl = 3),本设计的时钟频率166MHz
1.9 Sdrm仲裁模块
SDRAM 有三种必需的操作: 刷新操作、读操作和写操作。这三种操作之间的协调及相互转换就引入了“仲裁机制”。在需要刷新的时候,给出刷新请求,仲裁模块给出使能信号。在需要读取数据的时候,接收外部的读请求,然后仲裁模块给出响应,写入数据操作类似。如图13所示。
(图13 仲裁设计框图)
(图13 仲裁顶层设计)
module SdramArbiter
(
input Clk166M ,
input [3 : 0] InitCmd ,
input [`ADDR_BITS-1: 0] InitAddr,
input [`BA_BITS-1 : 0] InitBa ,
input InitDone,
input RefReq ,
output reg RefEn ,
input [3 : 0] RefCmd ,
input [`ADDR_BITS-1: 0] RefAddr ,
input [`BA_BITS-1 : 0] RefBa ,
input RefDone ,
input WrReq ,
output reg WrEn ,
input [3 : 0] WrCmd ,
input [`ADDR_BITS-1: 0] WrAddr ,
input [`BA_BITS-1 : 0] WrBa ,
input [`DQ_BITS-1 : 0] WrDq ,
input [`DM_BITS-1 : 0] WrDqm ,
input WrDone ,
input RdReq ,
output reg RdEn ,
input [3 : 0] RdCmd ,
input [`ADDR_BITS-1: 0] RdAddr ,
input [`BA_BITS-1 : 0] RdBa ,
output [`DQ_BITS-1 : 0] RdDq ,
input [`DM_BITS-1 : 0] RdDqm ,
input RdDone ,
output reg [3 : 0] Cmd ,
output reg [`ADDR_BITS-1: 0] Addr ,
output reg [`BA_BITS-1 : 0] Ba ,
inout [`DQ_BITS-1 : 0] Dq ,
output reg [`DM_BITS-1 : 0] Dqm
);
Ø 双向端口数据处理
Ø 读、写、刷新的仲裁响应
1.10 Sdrm模型
parameter tAC = 0.0; //test 6.5
parameter tHZ = 0.0;
parameter tOH = 6;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 42.0;
parameter tRC = 60.0;
parameter tRCD = 18.0;
parameter tRP = 18.0;
parameter tRRD = 12.0;
parameter tWRa = 6.0; // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns)
parameter tWRp = 12.0; // A2 Version - Precharge mode only (15 ns)