• 用ModelSim仿真SDRAM操作


    之前写了两篇关于Modelsim仿真的blog,其中模块管脚的命名可能让人觉得有些奇怪,其实不然,之前的两篇内容都是为了仿真SDRAM操作做铺垫的。

    由于SDRAM的仿真过程相对比较复杂,也比较繁琐。故可能需要不止一篇blog来完成。

    在开始仿真之前,如果对SDRAM原理以及时序不是很了解的朋友,推荐看一下如下这篇文章:

    SDRAM-高手进阶,终极内存技术指南——完整进阶版

    OK,下面正式开始仿真的过程。

    通过看内存技术指南,我们大概可以总结出SDRAM的工作过程:

    1. 上电后进入200us的输入稳定期,空操作(NOP)
    2. 向SDRAM发送1次(1个时钟周期)预充电(precharge)命令,然后保持N个时钟周期NOP操作(N值可查芯片具体SDRAM芯片手册,与SDRAM工作的时钟频率有关)
    3. 向SDRAM发送8次刷新(refresh)命令,具体发送过程后面会介绍
    4. 设置SDRAM工作模式寄存器
    5. 初始化完毕,可以开始读写操作
    PS:除了上述操作外,还有一个周期性的操作就是自刷新。拿我使用的芯片来说,需要每15us进行一次自刷新操作。(15us*4096=61.44ms < 64ms,为什么这么设置,请参考终极内存技术指南)
     
    --------------------------------------------------------------------------------------------------------------------------------------------------------
    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    ---------------------------------------------------------------------------------------------------------------------------------------------------------
    下面贴几张初始化相关的图片:
     
    模式寄存器设置!!!
     
    我的模式寄存器设置值为: 0x023,对应到上图可以看出,我的选择为:
    • 操作模式:突发读/突发写
    • 潜伏期:两个时钟周期
    • 突发传输方式:顺序
    • 突发长度:8 (SDRAM芯片:4Block,1M*16bit,共64Mbit)故突发长度8代表每次读或写命令传输的数据量为8*位宽=8*16bit=128bit=16字节 (暂不考虑数据掩码DQM)
    --------------------------------------------------------------------------------------------------------------------------------------------------------
    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    ---------------------------------------------------------------------------------------------------------------------------------------------------------
    下面开始介绍仿真的过程,其中涉及到PLL模块以及FIFO模块。关于这两个模块的仿真可以参考之前的两篇Blog
    整套系统源码来自特权同学的博客,里面可以下载到源码。
    首先,为了便于观察仿真波形,先列出SDRAM的命令
    SDRAM命令
      CKE CS_n RAS_n CAS_n WE_n
    空操作(NOP) 1 0 1 1 1
    预充电(PRE) 1 0 0 1 0
    刷新 1 0 0 0 1
    行有效 1 0 0 1 1
    开始读 1 0 1 0 1
    开始写 1 0 1 0 0
    模式寄存器设置 1 0 0 0 0
    (PS: _n结尾的信号代表低电平有效)
     
    波形1:PLL完成初始化
    红色的波形为和命令有关的信号。我把它们放到一组为了便于观察,可以看到,在400ns处,时钟有效信号CKE变高,片选信号CS_n变低,SDRAM开始动作,参考命令表,SDRAM启动后的命令为:10111,即NOP操作,这一过程要持续近200us,称之为输入稳定期


     
    波形2:预充电,对应命令10010以及 8次刷新操作,对应命令10001,注意每个命令之后都有执行一段时间的NOP操作,这使得SDRAM有时间执行命令。
     
     
    波形3:模式寄存器设置,可以看到,命令为10000,此时SDRAM_BA[1:0]以及地址线SDRAM_ADDR[11:0]的值分别为0以及0x033(我真实器件使用的是0x023,仿真的时候选择错了,不过不影响看波形),从这幅图中应该可以很清楚的看到,SDRAM时钟频率为100Mhz,同时与FPGA的SDRAM控制器的100MHZ时钟存在相位差,这是必要的。
    因为,在SDRAM控制器的时钟上升沿,产生命令,然后在随后的SDRAM时钟上升沿,命令已经稳定了,这样就方便了SDRAM顺利的取得命令。数据传输也是同样的道理。仿真中我选择的相位差为72度
     
    波形4:写SDRAM数据,结合上一篇文章中的FIFO操作,这个波形应该很容易理解了,最后两行:
    sys_data_in是FIFO传递给SDRAM控制模块的数据,
    sdram_data是SDRAM的数据总线,两者之间有1个时钟周期的延时。
    从图中可以看出,首先SDRAM控制器发出了行有效命令(10011),选中了第0个逻辑块的第0行,然后在两个时钟周期后,发出了写命令(10100),列地址为0,同时不加延迟的把第一个数据0x0000放在了sdram的数据总线上,该命令执行一次,可以看到写入了8个16bit数据,这也就对应了前面所说的突发长度。
    此外,细心的朋友可以看到,在写命令时,地址线的值为 0x400,其中的4对应 A10,给它设置1,表示允许自动预充电。
    那么什么是自动预充电呢?
    SDRAM在每次读取操作后,逻辑为1的数据被读取后会放电,很有可能会导致其逻辑值变为0,故,需要再写入数据,保证读取后值不丢失。所以,自动预充电还是蛮必要的。
     
    波形5:15us一次的自刷新。。对应命令10001。 从图中可以看出,一旦SDRAM开始运行,自刷新将遍布在SDRAM的整个生命周期中,15us一次,不多不少。这是维持SDRAM稳定工作的动力源泉。
     
    ok,关于SDRAM的Modelsim仿真就到这里。为什么不介绍SDRAM的读取仿真呢..你说呢?:)
     
    --------------------------------------------------------------------------------------------------------------------------------------------------------
    $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
    ---------------------------------------------------------------------------------------------------------------------------------------------------------
     
    关于整套系统的仿真源码下载(也包括pll,fifo,data_generator模块的仿真):
    使用时可以把需要的文件加入工程,同时修改system.do文件中的源文件路径,然后执行即可。
    (所有.do文件放在modelsim文件夹下)
    我使用的Modelsim版本为SE10.0C。
     
    本工程所需仿真文件如下所示:
     
     
    来源:http://blog.csdn.net/ruby97/article/details/7356110
  • 相关阅读:
    jacascript 立即执行函数(IIFE)与闭包
    javascript 作用域链与执行环境
    高并发、海量数据处理尽量少使用using也能提升效率
    清理0字节文件和文件夹
    一个朋友面试时遇到的算法题(怎么组合后得到最大整数)
    避免回溯方法
    Linq 查询结果 可能遵循 2 º,2¹,2 ²,......增长计算
    复杂 XML 的 序列化 反序列化
    小米4年600亿背后的10条创业经验
    经典String str = new String("abc")内存分配问题
  • 原文地址:https://www.cnblogs.com/hfyfpga/p/3980974.html
Copyright © 2020-2023  润新知