sdram控制器设计要点-初始化

in WhereIN3 years ago

sdram控制器设计要点-初始化

最近学习fpga sdram控制器的设计。总结了一些巧妙的设计思路。有时,自己不禁想,为什有些方法自己不能信手拈来呢?

sdram上电后不能立即使用,需要进行初始化后才能使用。它的初始化有一定的时序要求,这也是逻辑设计电路的共性了。所以对于时序的理解至关重要。从它的初始化设计代码里就可以体会的到。

根据它的初始化时序图,可知,sdram上电后,需要等待100us的等待时间,以便电源和时钟达到稳定状态。【在程序里这个参数值被调整到了200us,sdram的时钟采用100MHz,那么计数值就是20000】。也就是用计数器计数,计数值达到20000,就相当于经过了200us。

然后呢?在下一个时钟(注意,是下一个时钟,也就是说有一个时钟的延时),进行预充电。预充电后,还要等待一段时间等候下一步操作。这个等待时间称为tRP,一般是20ns,编程时采用30ns,也就是计数值是3。

然后就是自动刷新的操作。它也需要等待一段时间,tRFC,一般为66ns。编程时取100ns,计数值是10。自动刷新需要执行2次,每次等待66ns,编程时每次等待100ns。

接下来就是写模式寄存器。写完后还需要等待tMRD的时间,一般为2个时钟周期(sdram时钟),即2*CLK。编程时计数值为2。

如此,初始化完成。

一开始我选择用状态机,一开始是NOP1状态,然后跳到PRECHARGE状态,然后跳到AUTO_REFRESH状态,再跳到NOP2状态,再跳到AUTO_REFRESH2状态,再跳到NOP3状态,再跳到LOAD_MODE_REGISTER状态,再跳到NOP4状态。由状态机来实现本来是没有问题的,但是,后来发现的线性序列机方法简洁方便,于是就放弃了状态机的写法。

线性序列机的思想就是将整个初始化的过程看成一个整体,整个时间用同一个计数器来计数,到特定时刻执行特定的操作。

初始化的整个时间包含“上电等待时间”,“预充电后等待时间”,“自动刷新后等待时间(2次)”和“装载模式寄存器后等待时间”。

到时细心的人会发现,这里是不是落下了一个时钟周期?对的,就是上电等待时间到达后到预充电之间有一个时钟的延迟,但为什么要扔掉这个时钟周期呢?

其实,这是时序逻辑电路固有的特点,就是输入数据经过一个触发器打一拍会产生一个时钟周期的延迟。具体而言,以两个级联的上升沿D触发器为例,就是触发器输出的数据始终是前一个时钟沿采集到的数据。

所以在处理的时候,初始状态就是NOP状态。假设初始化等待的时间,计数器需要计数20000次,从0开始,直到计数值等于20000,说明200us的延时已经达到。这时将预充电命令送出去,直到下一个时钟才会被读取。所以,这里已经将失去的一个时钟找回来了。

但是预充电命令执行后,执行预刷新命令时,需要提前一个时钟周期发送PRECHARGE命令。所以一个失去的时钟就起了提前的作用。其它的命令也都类似,整个流程就很清晰了。

而初始化完成标志也是在初始化时间结束的那一点。同时也含有提前了一个时钟周期的意思。这里用了组合逻辑电路,与时间结束那一点正好对应,如果用时序逻辑,必然需要提前一个时钟来产生。所以用组合逻辑还是时序逻辑要好好的考虑,二者还是有区别的。

还有一点,就是计数器计数的时候,如果从0到20025,相当于是记了20025个数,一般计数器记满后会清零,从头开始计数,这时就会是20025到0再到20025,这个过程相当于记了20026个数。所以一般的计数器计十个数,会是从0记到9,并且一开始会有一个时钟周期的误差。所以这时可以采用第一次计数从零开始,不是第一次计数从1开始计数。

[WhereIn Android] (http://www.wherein.io)

Sort:  

厉害啊!储这么多币😍

[WhereIn Android] (http://www.wherein.io)

😄,没处卖

[WhereIn Android] (http://www.wherein.io)

👍🏻!shop

[WhereIn Android] (http://www.wherein.io)

谢谢

[WhereIn Android] (http://www.wherein.io)

你好鸭,lucienyong!

@boylikegirl给您叫了一份外卖!

蛋糕

吃饱了吗?跟我猜拳吧! 石头,剪刀,布~

如果您对我的服务满意,请不要吝啬您的点赞~

Coin Marketplace

STEEM 0.16
TRX 0.15
JST 0.028
BTC 55216.42
ETH 2325.60
USDT 1.00
SBD 2.33