继续死磕SDRAM控制器
SDRAM控制器
博主上一篇介绍了一些SDRAM的基本原理是否有必要学习使用纯Verilog写一个SDRAM控制器,接下来记录SDRAM控制器的工作原理。首先是上电初始化。
上电初始化
时序图中,tRP、tRC、这些时间参数可以从手册中找到,这里的系统时钟采用50Mhz。
从初始化的时序图可以看出,首先在进行预充电(Precharge)命令之前要等待100us(手册要求是至少100us,我们设定延时200us),等待系统上电稳定和时钟稳定,然后对所有bank进行预充电(Precharge),经历一个trp(20ns,一个时钟周期,手册可以查询)时间,然后进行至少两次自刷新(Auto refresh)(我这里设置进行8次自刷新,),每次自刷新至少需要trc(63ns,四个时钟周期,手册查询)时间,最后进行模式寄存器(MODE register)的配置,需要tmrd(两个时钟周期)时间,初始化完成。
预充电时当A10为高电平对所有的bank进行操作,当A10为低电平时对单个bank进行操作,BA0,BA1选择bank。我们这里预充电时对所有的bank操作,把A10置高即可。
SDRAM初始化流程
- 上电后延时200us
- 对所有的bank进行预充电(Precharge)
- 8个自刷新操作,每次自刷新使用四个时钟周期
- 进行模式寄存器的配置 ,配置完后输出初始化完成标志。
这里先设置SDRAM的突发长度为4 Addr = 12’b0000_0110_0010
SDRAM初始化仿真
这里仿真需要用到SDRAM的仿真模型,通过仿真模型可以把当前SDRAM进行的操作打印出来,如果有错误也会提示错误,这时候再去查看波形时序。这里需要注意的是仿真的时候sdram_dqm信号必须和仿真模型连接,否则数据是写不进去的,设置sdram_dqm = 0就可以了。
将SDRAM仿真模型添加进去后,要对放着模型的参数进行重定义
对于各个参数的值,不同的SDRAM芯片的参数是不同的,具体根据手册而定,mem_sizes设置的是1个bank的容量。Verilog语法笔记:这种方式可以对例化模块里面已有的宏定义进行重定义,写法是defparam + 例化之后的模块名+ . +需要重定义名。
然后在transcript中输入run 200us,先跑200us等待系统上电稳定,在输入run 50us,如上图所示CAS Latency(列选通潜伏期)为3,burst length(突发长度)为4,burst type(突发类型)顺序(Sequrntial)执行,模式寄存器配置都按照我们设置的进行。
SDRAM工作原理
初始化模块设计完成后,对SDRAM已经有了一些简单的了解,下面先来看看SDRAM的工作原理。
粗线——自动跳转,细线——受到命令后才能跳转(看不清楚图片点击阅读原文)
从一个官方给的SDRAM手册的参考状态转移图看,我们可以简单写一下SDRAM的工作流程。这部分用状态机来实现最好不过了。
上电后,给一个Precharge命令,进入Precharge状态,然后自动进入IDLE(初始化)状态,然后给自刷新命令,进入自刷新状态,自刷新完后回到IDLE状态,IDLE状态给一个配置模式寄存器命令,进入模式寄存器的配置,配置完后才能自动回到IDLE状态,然后进行读写状态的操作。
以写操作为例,需要给一个行激发命令,进入行激发状态,给出写命令才能进入写状态,写完后自动返回行激发状态,给一次写命令,会写入一个突发长度的数据,在一行没有写完不需要跳回行激发状态,只需要继续给写命令,只有当一行写完或刷新请求来临或数据写完才会跳出写状态,这里后面设计写模块再讲。数据写完或刷新请求来临或数据写完,需要先进入预充电状态,给一次预充电命令,然后自动跳转到初始状态进行重新等待命令。至于读模块的操作和写模块是完全一样的,读者自行读图。
这里要提的是图中有两个状态WRITEA和READA,这里我们不需要用到,如图也可以看到,这两个状态在进行一次读或写后会自动跳入预充电状态,从而回到初始化状态,这样和WRITE和READ这两个状态相比,读写速度肯定是会慢的,WRITE和READ可以连续给读写命令进行读写,所以直接忽略掉这两个状态不管。
仲裁机制
这里要引出一个设计技巧,初始化完成后,进行自刷新和读写操作状态都是相互独立的,所以我们需要写一个状态机去完后这些状态之间的跳转,大概意思就如下图所示,写一个仲裁状态机,当SDRAM控制器要进行自刷新时,自刷新模块需要给一个刷新请求,仲裁状态收到后,就结束当前进行的状态,给一个刷新使能,刷新模块才会进行刷新操作。同样的,当SDRAM控制器要进行写数据时,写数据模块需要给一个写请求,仲裁状态收到后,就结束当前进行的状态,给一个写使能,写数据模块才会进行写操作。后面的模块相应的也是这样的设计。
刷新模块
手册规定SDRAM自刷新需在64ms内刷新4096次(不同型号的芯片对应的不同),必须64ms是因为SDRAM内部使用电容存储数据的,它保证不断电的时间就是64ms。4096次的意思是,我所使用的这款SDRAM芯片它的行地址为A0~A11,一共是12位,2的12次方一共是4096行,我们每给一次刷新命令实际上是刷新一行,且是四个bank同时刷新,所以说一共要刷新4096次。两次刷新间隔15us。刷新是在SDRAM初始化完成后就要开始进行刷新。
从时序图可以看出,先给一个precharge命令(一般都是对all bank进行操作),经过trp(20ns,一个周期)时间进行一次自刷新命令,再过trc时间,进行再一次自刷新命令,然后trc(63ns, 四个周期)时间后激发读或写命令。
在时序图中我们看到了两次自刷新命令,但是实际上只要给一次自刷新命令即可,所以不要被时序图忽悠了,当然给两次也是没有什么关系的。这里的意思是,每次进行自刷新操作都需要给一次预充电即可。
刷新模块仿真
仿真的时候发现我犯了一个错误,就是每15us的刷新操作是不用每次都给预充电(Percharge)命令,但是从另一个状态跳转到自刷新状态是需要给一个预充电(Percharge)命令。之后便不需要再给了,这上面这里的原因是因为在刷新模块里有预充电(Percharge)命令,所以每次状态跳转到执行刷新模块,都会给一个预充电(Percharge)命令。这个问题已经得到解决。如图每15us进行一个自刷新。
关于SDRAM的读模块和写模块操作,下一篇再写。博主最近基于上次50Mhz下的简易SDRAM控制器的基础上修改成100Mhz的SDRAM控制器,实现用上位机串口发送一副彩色图片到SDRAM存储,再用VGA显示,下一步的目标是实现摄像头实时采集视频流数据显示。目前把最近写的这两个项目工程放到了Github上分享出来,希望能一起讨论,多多指点,这个东西我个人感觉不懂内部的操作时序,想要移植也是很麻烦的,所以干脆直接分享出来,后面博主会继续优化,尽量做成一个像IP Core一样的直接修改参数就可以调用的一个SDRAM控制器。
https://github.com/NingHeChuan/Open-FPGA.git
转载请注明出处:NingHeChuan(宁河川)
个人微信订阅号:开源FPGA
如果你想及时收到个人撰写的博文推送,可以扫描左边二维码(或者长按识别二维码)关注个人微信订阅号
知乎ID:NingHeChuan
微博ID:NingHeChuan
原文地址:http://www.cnblogs.com/ninghechuan/p/8992683.html
继续死磕SDRAM控制器的更多相关文章
- 是否有必要学习使用纯Verilog写一个SDRAM控制器
在做这个SDRAM控制器之前,博主有一个疑问,对于学生来说,是否有必要学习用纯Verilog写一个SDRAM控制器?因为目前X家和A家都有了DDR IP Core,对于要实现一个应用可以直接调用IP ...
- 死磕安卓前序:MVP架构探究之旅—基础篇
前言 了解相关更多技术,可参考<我就死磕安卓了,怎么了?>,接下来谈一谈我们来学习一下MVP的基本认识. 大家对MVC的架构模式再熟悉不过.今天我们就学习一下MVP架构模式. MVC和MV ...
- 【死磕NIO】— 阻塞IO,非阻塞IO,IO复用,信号驱动IO,异步IO,这你真的分的清楚吗?
通过上篇文章([死磕NIO]- 阻塞.非阻塞.同步.异步,傻傻分不清楚),我想你应该能够区分了什么是阻塞.非阻塞.异步.非异步了,这篇文章我们来彻底弄清楚什么是阻塞IO,非阻塞IO,IO复用,信号驱动 ...
- mysql每秒最多能插入多少条数据 ? 死磕性能压测
前段时间搞优化,最后瓶颈发现都在数据库单点上. 问DBA,给我的写入答案是在1W(机械硬盘)左右. 联想起前几天infoQ上一篇文章说他们最好的硬件写入速度在2W后也无法提高(SSD硬盘) 但这东西感 ...
- 【死磕Java并发】-----Java内存模型之happend-before
在上篇博客([死磕Java并发]-–深入分析volatile的实现原理)LZ提到过由于存在线程本地内存和主内存的原因,再加上重排序,会导致多线程环境下存在可见性的问题.那么我们正确使用同步.锁的情况下 ...
- 死磕 java集合之DelayQueue源码分析
问题 (1)DelayQueue是阻塞队列吗? (2)DelayQueue的实现方式? (3)DelayQueue主要用于什么场景? 简介 DelayQueue是java并发包下的延时阻塞队列,常用于 ...
- 死磕 java集合之PriorityBlockingQueue源码分析
问题 (1)PriorityBlockingQueue的实现方式? (2)PriorityBlockingQueue是否需要扩容? (3)PriorityBlockingQueue是怎么控制并发安全的 ...
- 死磕 java集合之PriorityQueue源码分析
问题 (1)什么是优先级队列? (2)怎么实现一个优先级队列? (3)PriorityQueue是线程安全的吗? (4)PriorityQueue就有序的吗? 简介 优先级队列,是0个或多个元素的集合 ...
- 【死磕 Spring】----- IOC 之解析 bean 标签:开启解析进程
原文出自:http://cmsblogs.com import 标签解析完毕了,再看 Spring 中最复杂也是最重要的标签 bean 标签的解析过程. 在方法 parseDefaultElement ...
随机推荐
- H3C数据中心虚拟化解决方案技术白皮书
缩略语清单: 缩略语 英文全名 中文解释 IDC Internet Data Center 互联网数据中心 VRF Virtual Router Forwarding 虚拟路由器转发 SMP Symm ...
- Centos6.6上源码安装Nodejs V4版本
本来就是想在vps上装一个Ghost博客,这个博客依赖的是Nodejs,然后推荐的是V4版本.然后我就对着官网的步骤安装,发现根本没有Centos6 i386的资源了(64位的还是有的), 我只能在那 ...
- 安卓自定义日期控件(仿QQ,IOS7)续
本篇是在原来的基础上修改了界面效果,使其更加接近ios7,qq等日期选择控件,看图: 源码地址:http://download.csdn.net/detail/baiyuliang2013/87601 ...
- 06 Activity显示跳转
<span style="font-size:18px;">package com.fmy.day8_29task; import com.fmy.day8_29tas ...
- SSH深度历险(五) 深入浅出-----IOC AND AOP
IOC就是Inversion of Control,控制反转.在Java开发中,IoC意味着将你设计好的类交给系统(容器)来控制实现,而不是在你的类内部控制.这称为控制反转. 本人理解:就是把原本你自 ...
- Android的事件处理-android学习之旅(四十四)
androd事件处理简介 控制飞机移动的简单实例 package peng.liu.test; import android.app.ActionBar; import android.app.Act ...
- Mysql中limit的用法详解
Mysql中limit的用法详解 在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,为我们提供了limit这样一个功能. SELECT * FROM table LIMIT [offset ...
- 【Unity Shaders】Using Textures for Effects —— 实现Photoshop的色阶效果
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- Chipmunk僵尸物理对象的出现和解决(六)
既然出现了这个问题下面就是如何找到原因. 因为该问题不是每次都出现,偶尔反弹棒碰到五角星时才会多出一个僵尸棒,现象比较随机,较难悉知具体原因. 有时多次触碰又没有出现问题,有时短时间内每次触碰都出现问 ...
- 如何成为一名优秀的web前端工程师
我所遇到的前端程序员分两种: 第一种一直在问:如何学习前端? 第二种总说:前端很简单,就那么一点东西. 我从没有听到有人问:如何做一名优秀.甚至卓越的WEB前端工程师. 何为:前端工程师? 前端工程师 ...