SDRAM控制器设计之control_interface.v代码解析

描述

前言

control_interface.v文件里已经写了非常详尽的代码备注。本文继续对该文件代码进行讲解,并给出SignalTap波形辅助读者理解。

下图是本案例的功能框图。

代码

control_interface.v文件对应图中SDRAM接口控制模块,该模块主要控制SDRAM命令的产生,包括空操作命令、预充电命令、自动刷新命令、加载模式寄存器命令和读写命令等。如下是该模块的RTL视图:

代码

根据IS42R16320D 的时序图可知该SDRAM上电后约经过 200us 才进入稳定期,在这段时间不可以对 SDRAM 做任何的操作(除了发送NOP命令), 200us 之后要对所有的区块进行预充电,接着再给SDRAM发送 8次自动刷新命令,最后才进行SDRAM模式寄存器的设定。完成了初始化过程之后,SDRAM 才能进行正常的读写操作。整个过程可简化为下图所示:

代码

control_interface.v模块工作时钟100MHz,由Sdram_Control.v的PLL模块提供。以100MHz时钟周期计算,200us需要经历20000个周期。另外,参考IS42R16320D的datasheet或者参考02-SDRAM控制器的设计——解读IS42R16320D的数据手册可知预充电最少要2个时钟周期,自动刷新命令完成需要至少8个时钟周期,模式寄存器的设定至少也要2个时钟周期。为了保险起见,将预充电、自动刷新和模式寄存器设定等操作的等待周期都设定为20个时钟周期(也就是0.2us)。

代码

代码里面首先设计两个计数器,第一个计数器是初始化动作的计时器。为了保险起见,初始化先等待24000个时钟周期:

代码

从SignalTap波形图可以看到INIT_REQ在init_timer从0计数到24000以后拉低了。INIT_REQ拉高(绿色部分)指示了SDRAM开机后的输入稳定期。

代码

把INIT_REQ和init_timer局部放大如下:

代码

代码里面实现预充电操作等待20个时钟周期:

代码

代码

代码里面实现每次自动刷新都等待20个时钟周期(总共8次):

代码

代码

第二个计数器是正常读写时的自动刷新间隔计时器,因为SDRAM必须要不断进行刷新才能保留数据 ,由IS42R16320D数据手册可知每一行刷新的循环周期最多为64ms。DE10-Standard开发板上的SDRAM有13位的行地址,共有8192行,而每一次的刷新命令只能对一行有效,所以在最长 64ms / 8192 = 7.8125us 的时间间隔内,就必须发一次刷新的命令。在工作时钟100M下,这里刷新周期设置为768。

代码

从SignalTap波形图可以看到timer的值在输入稳定等待期(INIT_REQ为高)一直是968:

代码

INIT_REQ拉低以后timer开始倒数计数:

代码

初始化操作结束后timer的计数周期就变成了768:

代码

可能读者疑惑这里为什么中间有三个周期timer的值是65535、65534、65533,而不是马上变为768呢?

其实可以结合这个图看:

代码

1. timer 为0;

2. timer为0 的下个时钟周期 REFRESH_cycle 为1,timer值继续减一,为65535;

3. 继而下个时钟周期 do_refresh 为1,timer值继续减一,为65534;

4. 继而下个时钟周期 REF_ACK 为1,timer值继续减一,为65533;
5. 继而在下个时钟周期的时候 timer 赋值为768。

注意本文件当中REFRESH_init和REFRESH_cycle都是指示自动刷新操作的命令,都会控制SDRAM控制器去发送RASCASWE组合是001的命令,它们只是指示的是不同状态下的自动刷新。

代码

读写指令译码的代码部分如下,当CMD值为000时,对应NOP指令,当CMD值为001对应读指令,当CMD值为010时对应写指令:

代码

再来看CM_ACK和CMD_ACK信号。大家可能会疑惑为什么要弄CM_ACK和CMD_ACK这两个变量呢?

代码

首先看输入信号CM_ACK。由command.v文件可知当do_refresh || do_reada || do_writea || do_precharge || do_load_mode有效时,CM_ACK=1:

代码

而只有接收到WRITEA、READA、PRECHARGE、LOAD_MODE等命令时do_refresh 、 do_reada 、 do_writea 、do_precharge 、 do_load_mode这些信号会拉高:

代码

代码

所以CM_ACK信号用于接收指令。它主要指示预充电指令、初始化状态下的自动更新命令、加载模式寄存器指令和读写指令的接收。

因为接收指令不一定会执行,CMD_ACK用于判断接收到的指令是否执行。所以当CM_ACK有效(接收到了指令),CMD_ACK无效(无效说明当前没有别的指令在执行)时,才令CMD_ACK有效。

CM_ACK与CMD_ACK信号波形参考下图:

代码

PS:本文的波形图来自文件~sdramcontroloutput_filesinterface.stp

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分