原创 零基础学FPGA (二十五) 一路走来 :SDR SDRAM(架构篇)

2015-3-24 17:21 2530 14 18 分类: FPGA/CPLD 文集: FPGA/CPLD

         湖南最近终于也算是过了阴雨期,话说从开学到现在还没见过几个晴天。这几天还算好,阳光不错,学校里的樱花也开了,开得好是灿烂,但是面积不大,只有零零散散的几棵,每次到这樱花盛开的季节,总是有一个想法,就是去湖北武汉参加一下那里的樱花节。

360桌面截图20150324101215.jpg
 
       虽然作为男生,但是也对樱花情有独钟。尤其面对那“仙云昨夜坠庭柯,化作翩跹万玉娥”般的樱花雨没有丝毫抵抗力。牵着自己喜欢人的手,漫步在樱花飘落的樱花道,是不是一幅令人陶醉的场景?
 
       然而昨天还看新闻,说武汉大学的樱花节当日接待游客10W人,看樱花的人都在抱怨看得是人头,而不是樱花,这样说来,清明节假期去看樱花的人是不是更了不得了....本来打算清明节去一趟武汉,但是想起当时去杭州西湖的时候,瞬间就没了兴致,所谓西湖无断桥,只见人头啊...
 
      话说小墨在大学这2年多也去了不少地方,读万卷书,不如行万里路嘛,什么北京,上海,杭州啊,桂林,凤凰,南岳啊以及周围的一些城市,长沙,武汉的就不用说了,最近同学又在组织去张家界了,而我更倾向于厦门和黄山,至于张家界,九寨沟等毕业之后再好好去看一下吧,要知道我可是个旅游达人~
360桌面截图20150324103057.jpg
 
 
        旅游当然是要的,但是我们的专业知识也还是要好好学的,今天我们来讲的是SDRAM的架构以及设计,这也是小墨第一次接触架构,也谈不上给大家讲,就是把我理解的当做一个笔记分享给大家,我也试着做了一个SDRAM 的架构word文档,在文章的后面,喜欢的朋友可以下载下来看一下,有什么错误也请积极指正,毕竟我也是没有老师教,也是自己摸索的,难免有些不合理的地方。
 
一、SDRAM 工作部分
 
1、上电初始化
 
       360桌面截图20150324103638.jpg
             我们先来看第一部分,上电初始化。上电初始化我们知道,上电之后我们需要等待200us的稳定期,这段时间我们可以用一个定时器来计数,这没什么问题,然后进入的是预充电部分,这个时候,预充电的时候,sdram_cmd模块会检测此时的初始化状态机的状态,若处于预充电状态,那么sdram_cmd模块向SDRAM发命令,具体命令sdram的datasheet里面有,发的是一个precharge,即预充电,发完命令之后,需要等待一段时间,来确保这个命令被SDRAM捕获,这等待的时间,特权老师用的方式我觉得很好
360桌面截图20150324104540.jpg
 
         用一个宏定义,当计数器计数到相应的时间后,预充电完成参数置位 即end_trp 置位,下面的用法也是一样,即当初始化状态机进入预充电状态i_pre时,计数器开启,开始计数,计数完成,也就是预充电结束的时候,计数器复位,这个复位的控制,可以用case语句来检测初始化状态机的状态,在相应的状态给予相应的复位与置位
         接下来是8个自刷新,操作和预充电一样
         到了模式寄存器的配置阶段,我们需要选定L_bank,以及SDRAM工作模式的配置,当sdram_cmd模块检测到初始化状态机到达模式寄存器配置阶段时,我们的给SDRAM的sdram_bank端口赋相应的值,并且设置地址总线
360桌面截图20150324105615.jpg
 
 
 
当初始化结束的时候,标志位init_done置位,告诉工作状态机,初始化状态机已经结束,进入工作状态。下面是我用word做的上电初始化的状态转移图
360桌面截图20150324154251.jpg
360桌面截图20150324154421.jpg
 
 
 
2、自刷新
 
初始化结束之后,SDRAM为了防止数据丢失,要进行自刷新,上一篇文章已经讲过了,刷新2^12行需要64ms,也就是每15us刷新一行,也就是我们需要每15us发送一次自刷新请求给SDRAM工作状态机,状态机一旦检测到自刷新请求信号,就告诉sdram工作模块,然后工作模块就向SDRAM发送自刷新命令,即CMD_A_PEF
360桌面截图20150324154758.jpg
下面是自刷新的状态转移图
 
360桌面截图20150324155355.jpg
 
3、读写状态
 
      初始化结束以后,SDRAM就处于工作状态,每15us进行一次自刷新,这个时候,如果想要读或写数据的话,即向工作状态机sdram_work_FSM发送读写请求,如果是读请求,那么工作状态机进入行有效状态,也即激活状态w_active,此时,sdram_cmd模块会发送行有效命令,即CMD_ACTIVEA
 
      同时,我们需要将我们的12位行地址送给我们的sdram地址总线sdram_addr,然后便是一个等待时间段,TRCD,这个时间段里我们是不需要做什么工作的,只需等待TRCD结束
 
      TRCD结束的时候,工作状态机进入读状态,此时,我们需要发送列地址选中我们的存储单元,并告诉sdram_cmd模块发送读命令,这个过程是读命令和列地址同时发送的。我们知道,读命令发出之后,会进入潜伏期TCL。
 
       这个状态我们也不需要做什么,因为我们在模式寄存器配置阶段已经将各种参数配置好了,包括什么潜伏期长,突发读写长度之类的,等到潜伏期结束之后,SDRAM会自动进行读数据,而且读的数据长度会跟我们之前设置的一样长,这个读数据的状态需要时间,即我们的工作状态机工作在w_rd状态,等待8个时钟周期之后,所有的数据都已经被送到数据总线。
 
       这个时候我们需要等一会,因为我们在发送读命令的时候,A10是置1的,也就是说,每次读写完之后要自动进行预充电,从而才可以打开新的工作行,这时,我们的工作状态机即进入了w_rwait状态,等到预充电结束,才完成一次读操作,返回初始状态,等待下一个请求的到来
 
360桌面截图20150324161430.jpg
 
 
       下面是读写状态转移图,由于写状态只是没有潜伏期,写完之后有一个写回延时,其他地方与读状态相同,我就不再介绍了
360桌面截图20150324161640.jpg
360桌面截图20150324161743.jpg
 
 
二、模拟信号产生部分 
 
        我们先来想一下我们的要想测试我们的SDRAM控制器是否正确,都需要什么测试参数吧
 
       1、 首先我们需要发送读写地址对吧,但是我们需要有一个间隔,即每隔一段时间发送一次写地址,为什么呢?因为我们之前在模式寄存器配置的时候,定义了突发读写的长度为8,也就是我们发送一个地址,那么sdram会在连续的8个地址中连续写8次数,我们如果要再发送地址,需要等到这8次地址写完之后再发送下一个地址这个延时大概为640ns,也就是计数器为什么要计到3f的原因,下一个地址的发送就需要比之前的地址大8了,比如第一次我发送的是0地址,那,隔一段时间之后,我就需要发送8地址了。
 
        读地址也一样,当写地址写满了之后,让地址清零,从零地址读起即可
360桌面截图20150324164022.jpg
 
        还有再解释一下,特权老师为什么定义22位的模拟地址,22位的模拟地址包括2位的L_BANK的地址,12位行地址和8位列地址。有人会问,为什么是行地址和列地址分开呢,不是行列地址共用吗?注意这里只是模拟地址,到时候我们给地址总线赋值的时候是分开赋值的
 
       
     2、然后我们需要产生递增数据,每640ns产生8个数即可
360桌面截图20150324164409.jpg
       
      3、在发送递增数据之前,我们需要发送写请求信号,这个写请求信号是要发送到我们接下来要讲的FIFO里面,发送写请求之后,数据进入FIFO,注意,这里的写请求是发送给FIFO的,不是发送到SDRAM的,SDRAM的写请求是由FIFO发出去的
360桌面截图20150324165411.jpg
 
         有人会问,写请求有了,是不是还该有读请求,要知道,我们的数据是先写到FIFO里面,再有SDRAM对FIFO进行读操作,将写进FIFO的数据再送到SDRAM,而我们从SDRAM中读回的数据,同样要写到FIFO里面,然后我们再从FIFO里面读。是不是有人会问,这不是多此一举吗?其实不然,要知道我们的SDRAM是工作在100M的时钟频率下,而且是有相位偏移的,对我们FPGA来说是一个异步时钟,如果我们不采用FIFO的形式,那很容易发生亚稳态问题,导致系统不稳定
 
三、数据缓存部分
 
   1、写FIFO
360桌面截图20150324170343.jpg
 
         我来解释一下,写入时钟,也就是我们FPGA的时钟,50MHZ,在这个时钟频率下,我们需要给FIFO发送写请求和递增数据,wrusedw反映了我写入FIFO的占用量,当sdram工作状态机检测到写请求之后(FIFO发出的写请求),会产生一个响应,告诉FIFO要读数据了,这个响应作为FIFO的读信号,在100MHZ的时钟频率下,将我们写入的数据读走,送到SDRAM数据总线上
 
        2、读FIFO
360桌面截图20150324170909.jpg
 
      读FIFO跟写FIFO相反,写FIFO时钟为100MHZ,在这个时钟频率下,我们将从SDRAM中读回的数据写到FIFO里面,注意这里我们还用了wrusedw,来反应写FIFO的占用量,也就是我们从SDRAM里读了多少数据,然后在50MHZ的时钟下,将从SDRAM读回的数据采集下来,送到显示模块来验证是否是递增数据,这个显示模块我们用数码管来显示,比较方便,为了观察清楚,我们可以在数码管显示模块,每隔1S种发送一次读FIFO请求,这样在数码管上,会每隔1秒钟显示一个递增的数据了
 
       大体上就是这么多了,整个SDRAM的工作过程就介绍完了,还有些细节没讲到的,大家可以自行消化,有不懂的可以给我留言,或者加我QQ微信,欢迎交流
 
      下一篇文章我们讲时序,真正在板子上让它跑起来才是王道,下面附上我做的一个word,还请各位大神指正~
 
以后小墨同学的文章将在EDNchina和北京至芯科技官方技术论坛同时更新,至芯科技的官方技术论坛也有很多的资料供大家下载,里面也有小墨的专题板块,希望广大网友和爱好者的大力支持~
小墨同学《零基础学FPGA》学习专版  一个大三学生学习之路的真实记录
下面是至芯科技官方网站,夏宇闻教授和那里的老师都超好的~有意愿接受FPGA培训的可以找工作人员咨询
       以后小墨同学的教程会跟这款开发板配套,想跟小墨同学一起学习,一起进步的的可以考虑一下购买一块开发板,毕竟学习要舍得投资嘛,下面是开发板淘宝链接
 

文章评论4条评论)

登录后参与讨论

用户1810846 2015-4-21 17:46

第一点:6'h3f对应的是63,不知道你这里的计数时钟是100M还是25M?如果是100M的时钟的话,那么是640ns,但是我看你的程序这里不像是100M的时钟; 第二点:这里的640ns如果对应到SDRAM的100M工作频率,那么是64个时钟周期,但是对应SDRAM的写时序觉得不需要这么多的时钟周期。 所以不是很明白

584642877_350004634 2015-4-20 10:27

这个值不一定是具体算出来的,可以是经验值或者是仿真值,就是说大概640ns,8个数据就会保证写完

用户1810846 2015-4-19 21:11

不知道小墨同学的那个640ns是怎么计算出来的?

用户465116 2015-3-25 13:24

看来小墨同学的FPGA工程已经调好了,能共享出来学习一下吧?
相关推荐阅读
小墨同学 2015-09-10 10:28
零基础学FPGA( 三十二) 写在京城,多级FIR半带滤波器的FPGA实现
        每次到京城来总不能忘了出去逛逛吧,偌大的北京城去哪呢?炙热的大太阳烤的哪都不想去了,幸好这次有亲戚来北京旅游,搭个顺风车便出去转了一下。这次的闲逛可没有上次那么感叹,上次主要是去的...
小墨同学 2015-08-29 15:19
零基础学FPGA(三十三)多相结构抽取滤波器笔记
        前两篇文章已经介绍过了,在多速率信号处理中,CIC滤波器和FIR半带滤波器应用的非常广泛,由于CIC滤波器的特殊结构,使得它非常适合采样速率远远大于信号速率的情况时的抽取跟内插滤波...
小墨同学 2015-08-29 15:18
零基础学FPGA(三十一)写在京城,Hogenauer CIC抽取滤波器的FPGA实现笔记
         实习完还没几天,突然接到北京至芯雷总的电话,让我赶往北京来做一些事情,就这样,我的又一趟北京之旅开始了。         上次来北京还是今年1月份,冬天嘛,京城光秃秃的一片,...
小墨同学 2015-08-05 20:50
【博客大赛】零基础学FPGA (二十六)必会! 从静态时序分析到SDRAM时序收敛(上篇)
    好像小墨有这么一个习惯啊,就是每篇文章的开头总喜欢叨叨几句啊~既然这样,那我们今天也聊几句好了,总感觉直接就开始学习专业知识有点让人看不进去~     今天我们就说说生活吧~时间很快啊,...
小墨同学 2015-07-26 21:57
[博客大赛]零基础学FPGA(三十) IIR数字滤波器的FPGA实现笔记
      然而暑假已经过了快一半,想想也是挺快的,前一段时间学校安排实习,在长沙待了一段时间,说是实习,感觉却是像是度假,住着酒店,100多号人,想想都觉的热闹。实习搞得是Java安卓,当然我也...
小墨同学 2015-06-17 09:50
[博客大赛] 零基础学FPGA (二十九)滤波器开篇,线性相位FIR滤波器的FPGA实现
        也是有一段时间不写博客了啊,主要是这学期的实验课太多,每天都是在写预习报告,实验报告中度过,也快到考试月了啊,感觉又要忙起来了,今天就抽点时间来开个头,开什么头呢?对!就如标题所示...
我要评论
4
14
关闭 站长推荐上一条 /2 下一条