转载请注明出处:http://blog.csdn.net/kevin_hee/article/details/78020929。
这篇博文对DDR SDRAM做了粗略的介绍,其中并不涉及DDR SDRAM存储器控制系统具体的Verilog控制代码。实际上对DDR SDRAM的控制系统设计是很复杂的,这篇博文只对存储器的控制原理做简单的介绍,希望对SDRAM比较陌生的人有一个感性的认识。有不对的地方,希望指正。
一、SDRAM存储原理
SDRAM的存储原理可以大致用一个表格表示出来:
BANKn |
Column列地址 |
||||||||
Row行地址 |
0 |
1 |
2 |
3 |
...... |
i |
|||
1 |
|
|
|
|
|
|
|
|
|
2 |
|
|
|
|
|
|
|
|
|
3 |
|
|
|
|
|
|
|
|
|
...... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
||
j |
|
|
|
|
|
|
|
|
在上面的表格中,每一个表格可以想象成一个最小的存储空间。
在索引存储空间的时候,先后指定BANK块地址、Row行地址、Column列地址就能具体找到它。
二、Altera SDRAM IP核控制器原理
Altera DDR2 SDRAM IP核控制器对SDRAM的控制做了三层封装,分别留出三类接口,分别是Local Interface、Controller - AFI和AFI Memory Interface。
在这三类接口中,Local Interface是对用户开放的接口,AFI Memory Interface是对底层硬件开放的接口,Controller - AFI是中间层接口。
在Local Interface接口侧,带有local_*的是用户可以实际操作IP核的地方。用户不需要关心最底层的AFI Memory Interface接口层是如何工作的,只要按照local层正确的时序进行设计,就能实现对SDRAM的控制。
虽然在local层对底层硬件差别做了屏蔽,但是在实际设计中,还是需要清楚IP核的地址组成方式。
ALTERA DDR2 IP核参数设置如下,并选择的全速率(Full rate):
Local_address组成如下所示:
local_address[24:12] = row address[12:0] local_address[11:9] = bank address [2:0] local_address[8:0] = column address[9:1] |
注意在column address中最低位没有包括进去,这是因为在phy_clk时钟控制下,对用户来说,local层一次读写是以64bit(local_data[63:0])为单位的。而我们的SDRAM硬件一个行列地址为32bit,所以local层读写一次需要实际的硬件进行两个列地址的读写。
所以local侧每次地址加1,实际memory侧地址加了2.
另一个需要注意的点是local maximum burst count大小的选择。因为IP核读控制中,在local_read_req拉高一个周期后,实际测试会大约过几十个时钟周期后local_rdata_valid才会拉高,所以读端实际上花费了很多时间。这样在高带宽的读写控制中,可能会面临速度不够的情况。解决方法之一就是提高local maximum burst count的大小,即local_size的大小。让每一次的突发读写(特别是读)传递尽量多的数据,节约多余的控制时间。
三、SDRAM底层控制原理
看一张SDRAM(注意不是DDR,因为找不到一张完整如下图的DDR SDRAM的时序图,就以SDRAM的暂时替代)读写时序图(三星K4S641632C datasheet):
1.读写命令与地址激活
通过在时钟上升沿时保证/CAS和/WE为高,/CS和/RAS为低即可发布BANK激活命令。
BANK地址BA0~BA1选定希望激活哪一BANK,行地址ADDR决定要激活该BANK的哪些行(Row Active)。
在执行读写命令之前,必须先执行BANK激活命令。
在BANK激活命令发布之后,SDRAM在下一个时钟周期就可以接受读或者写命令。
但是如果 R/W命令不能满足tRCD(从行有效到读/写命令发出之间的间隔被定义为tRCD,即RAS to CAS Delay,RAS就是行地址选通脉冲,CAS就是列地址选通脉冲)最小值的规格,那么,在编程时,一定要在R/W命令后加上附加延迟。附加延迟的值必须满足tRCD最小值的要求。附加延迟的值可以是0,1,2,3,4。
列寻址地址和读写命令是同时发出的。
一旦某一个BANK被激活了,那么在下一个BANK激活命令应用到这一个BANK之前,要先对其预充电。BANK激活和预充电时间被分别定义为tRAS和tRP。
对同一个BANK的两个成功的BANK激活命令的时间间隔由芯片的RAS周期时间来决定(tRC)。TBANK激活命令之间的最小时间间隔是tRRD.
BANK激活命令之后,就可以执行读或者写周期了。
通过在时钟上升沿设置/RAS为高,/CS和/CAS为低,同时还必须定义/WE的值以决定访问动作是读还是写(/WE为高表示读操作,/WE为低表示写操作。)
SDRAM提供了一种快速的列访问操作(突发读写)。单个的读或者写命令会导致在接下来的时钟周期中进行一系列的读或者写操作。
2.CAS Latency
列地址被选中之后,将会触发数据传输,但从存储单元中输出到真正出现在内存芯片的 I/O 接口之间还需要一定的时间(数据触发本身就有延迟,而且还需要进行信号放大),这段时间就是非常著名的 CL(CAS Latency,列地址脉冲选通潜伏期)。CL只是针对读取操作。
3.数据同步信号DQS
DQS是DDR SDRAM中的重要信号,它的功能主要用来在一个时钟周期内准确的区分出每个传输周期,并便于接收方准确接收数据。它不是一个连续的脉冲信号,但是完全可以说它就是数据的同步信号。
看一张典型的读写时序图(micron MT46V64M8P-5BF datasheet):
A.FPGA读取DDR时,DQS信号上下沿和DQ的边沿对齐。
实际上并不是严格的对齐,因为在DQS触发到有效数据之间存在一个DQSQ的时间。
Ø DQSQ
看一张数据读取时序图(micron MT46V64M8P-5BF datasheet):
tDQSQ被定义为DQS触发后到有效数据窗口的时间。
因为预取操作使得各个数据位到达发送器端的时间不一致,所以所有数据位有效窗口和DQS的触发时间之间就有了距离。
B.在FPGA写入时,DQS信号上下沿和DQ的中心对齐。
在写入时,一切必须保证同步接收,DDR以发送方传来的DQS 为采集时钟,在数据的中部采集数据。这样做的好处是,由于各数据信号都会有一个逻辑电平保持周期,即使发送时不同步,在 DQS上下沿时都处于保持周期中,此时数据接收触发的准确性无疑是最高的。
Ø 写入时以DQS为采集时钟
看一张DDR部分结构图(micron MT46V64M8P-5BF datasheet):
上图是DDR读写控制部分。可以看到在DDR接收数据时,首先用一个INPUT REGISTERS作数据寄存,然后将寄存后的数据送入WRITE FIFO中,而这两个步骤用的时钟都是DQS。
C.在发出写入命令后,DQS与写入数据要等一段时间才会送达。这个周期被称为 DQSS相对于写入命令的延迟时间(tDQSS,WRITE Command to the first corresponding rising edge of DQS)。
4.刷新和预充电
对DDR SDRAM来说,refresh和precharge是两个重要的操作。Refresh保证了存储器中的数据不会丢失,Precharge用于关闭现有工作行,进入idle状态。
下面一张介绍DDR的整体控制流程图可以很好的看出这两个操作的作用(micron MT46V64M8P-5BF datasheet):
上图中粗体连接线是代表的自动操作(Auto matic sequence),细的连接线代表的是手动命令操作(Command sequence)。
Ø Precharge
在系统初始化完成后,会进入一个idle all banks prechargeed的状态,然后等待ACT激活命令以进入Row active行激活状态。
以左边的Write为例,在发出WRITE A写命令后,系统进入Write A(WRITE with auto precharge,即自动完成预充电)状态或者进入Write(需要手动完成预充电)状态。
在Write A状态,实际上在一行写完后,为了写下一行,系统会自动进行Precharge操作。在预充电完成后,系统进入Precharge PREALL状态,进而到idle状态等待下一个行激活命令。
在Write状态,写完一行后,需要手动发送PRE即预充电命令来进行预充电,在预充电完成后,系统进入Precharge PREALL状态,进而到idle状态等待下一个行激活命令。
Ø Refresh
在idle all banks prechargeed的状态,接收REFA命令进入Auto refresh状态进行自动刷新操作。
在刷新完成后进入Precharge PREALL状态,进而进入idle状态。
如果存储器正在写或读,而刷新时间到了必须进行刷新操作,存储器控制系统会通过PRE即Precharge命令关闭读写工作状态,进入idle状态以等待刷新命令。
四、实现DDR的关键技术
1.如何实现双边沿发送数据
为了实现DDR,存储器件在SDRAM的结构上做出了改进。
看一张典型的DDR SDRAM结构图(micron MT46V64M8P-5BF datasheet):
注意数据位宽为4(DQ0~DQ3)。
看到右边的读写控制器部分,在读端,首先读取8bit的数据到READ LATCH中,然后分成两路4bit数据进入MUX(多路复用器),随后产生一路4bit的数据到DRVRS中。同时在DQS GENERATOR生成的DQS信号和DLL生成的时钟信号的控制下,在时钟上升沿和下降沿分别将4bit数据传递出去。
这种一次读取2*4bit=8bit的方式称为2-bit Prefetch(两位预取).
这就是实现双边沿发送数据的关键技术。
2.FPGA如何正确的采集双边沿数据
从DDR SDRAM发送过来的数据和DQS并不是中心对齐的,为了实现正确的采样,需要产生一个和DQS同频但不同相的采样时钟,通过调制这个采样时钟的相位,使得采样时钟的上下沿对准DQS的中间(对准DQS的中间就大概对准了DQ的中间)。
为了准确的调整采样时钟的相位,可以使用一种叫做DPA(动态相位对齐)的技术来实现在数据中点的正确采样。
具体的技术原理和Xilinx的一篇介绍SERDES DPA的Bit Alignment原理类似(Dynamic_Phase_Alignement_xapp700.pdf)。
在一篇网上的文章中也有对动态相位对齐技术的简单介绍
http://www.docin.com/p-130928926.html
3.CK与CK#
CK#的作用,并不能理解为第二个触发时钟,而是起到触发时钟校准的作用。
由于数据是在 CK的上下沿触发,造成传输周期缩短了一半,因此必须要保证传输周期的稳定以确保数据的正确传输,这就要求CK的上下沿间距要有精确的控制。但因为温度、电阻性能的改变等原因,CK上下沿间距可能发生变化,此时与其反相的CK#就起到纠正的作用(CK上升快下降慢,CK#则是上升慢下降快)。而由于上下沿触发的原因,也使CL=1.5和2.5成为可能,并容易实现。
图片来自网络。