继续死磕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 ...
随机推荐
- 剑指Offer——二叉树
剑指Offer--二叉树 前言 数据结构通常是编程面试中考察的重点.在参加面试之前,应聘者需要熟练掌握链表.树.栈.队列和哈希表等数据结构,以及它们的操作.本片博文主要讲解二叉树操作的相关知识,主要包 ...
- 【Unity Shaders】使用Unity Render Textures实现画面特效——建立画面特效脚本系统
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- UNIX/LINUX程序设计教程(1)-- 获取系统信息
1.主机标识 每一台机器都有一个主机名,主机名由系统管理员指定,在网络中主机名可能是一个网络域名. 函数 gethostname() 和 sethostname() 可以用来获取和设置主机 ...
- Mybatis源码之Statement处理器RoutingStatementHandler(三)
RoutingStatementHandler类似路由器,在其构造函数中会根据Mapper文件中设置的StatementType来选择使用SimpleStatementHandler.Prepared ...
- C++ Primer 有感(标准库pair)
与关联容器相关的模板类型,包含两个数据成员,在utility头文件中定义. pair类型提供的操作: pair<T1,T2> p1; pair<T1,T2> p1(v1,v2) ...
- DB 查询分析器 方便地创建DB2自定义函数
DB 查询分析器 方便地创建DB2自定义函数 马根峰 (广东联合电子服务股份有限公司, 广州 510300) 摘要 ...
- xml之DOM方式解析,DOM4J工具解析原理
DOM解析原理: DOM解析原理:xml解析器一次性把整个xml文档加载进内存,然后在内存中构建一颗Document的对象树,通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到x ...
- 文件I/O实践(2) --文件stat
功能:获取文件元数据 #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int st ...
- 小强的HTML5移动开发之路(8)——坦克大战游戏2
来自:http://blog.csdn.net/cai_xingyun/article/details/48629015 在上一篇文章中我们已经画出了自己的坦克,并且可以控制自己的坦克移动,我们继续接 ...
- WebStorm开发工具设置React Native智能提示
最近在做React Native开发的时候,相信大家一般会使用WebStorm,Sublime,Atom等等开发工具.二之前搞前端的对WebStorm会很熟悉,WebStorm最新版是WebStorm ...