没有什么事都是一帆风顺的,学业。。。让人学会了很多但是又让人难以忘怀。。。人生路上起起伏伏,并不是真心的付出就可以得到相同的回报,有时候可能还会恰恰相反。。。

好了,负面情绪就不带给大家了,博主还是来讲sdram吧。其实博主搞了3,4天才搞明白sdram的大体流程,其实主要是被那么多的地址线啊,各种工作条件给懵逼了,其实学下来发现也就不过尔尔有一个规律可循,以及知道了看数据手册的必要。不过目前还是只会单字读写上。

sdram简单来说可以分为三个过程:1.初始化操作。2.写数据。3.读数据。但是由于我们的sdram并不是时时刻刻都需要读数据和写数据的,所以当我们不读数据或者不写数据的时候,需要每隔一段时间去自动刷新一下,防止数据丢失。(当然官方手册给出了的是先预充电,然后延时20ns,然后刷新)。间隔的刷新时间由数据手册决定。

1.初始化操作

官方给出的初始化过程如下:

各位不要慌,一开始博主就是慌了才搞了好几天,其实耐下性子来看还是很简单的,首先cke是使能时钟信号的,应该一直置高电平。

1.首先,需要对sdram延时200us,官方是100us,但是根据你的器件决定,多延迟也没事。在延时过程中,fpga发送nop无操作指令。

2.然后发送precharge预充电指令,同时对A10和BA0和BA1进行赋值,A10为1,则不用管BA0和BA1,所以的资源库都会释放。这些查手册即可。发送完延迟tRP时间,约20ns,同时指令设为无操作

3.接着发送自动刷新指令,然后延迟tRFC,根据器件决定,大约63ns,由于时钟是整数,所以一般要多一些延时。

4.重复第三步

5.设置模式寄存器

同样根据查表得到,然后延时tMRD。这个时间有CAS决定,一般是2个时钟单位。

这样初始化就完成了,感觉还是要学会看手册,要耐心。

然后就是写操作了,具体如下:

1.首先是发送active命令,同时需要设置bank信息来确定写哪块bank,还要设置行信息,代表要往哪一行写数据。然后延时tRCD,大约20ns

2.然后发送写命令,同时将dqm拉低,这样才能写入数据,然后将列信息,bank信息,要写入数据赋值,注意此时要拉高A10,代表自动释放资源库,然后延时tWR,大约2个时钟,再延时tRP,大约20ns。

然后就是读操作,具体如下:

可以发现它和写操作异曲同工

1.首先是发送active命令,同时需要设置bank信息来确定写哪块bank,还要设置行信息,代表要往哪一行写数据。然后延时tRCD,大约20ns

2.然后发送读命令,同时将dqm拉低,这样才能读到数据,同时将列信息,bank信息,注意此时要拉高A10,代表自动释放资源库,然后延时CAS时钟,大约2个,然后在延时tAC,大约6ns,然后读到数据,一般会考虑延时多一些,因为时钟信号50M的,单个周期就是20ns,读到数据后在延时大约tRP时间。需要注意的是,由于是读数据,所一开始需要将数据库设为高阻态来释放对它的控制。

这个就是sdram单个读写的基本操作了,可以看出如果按照数据手册来,其实不算难,看来以后还是要养成比较良好的阅读习惯啊

最后就是自动刷新了,这个操作是在不在读写的时候发出的,因为要保持数据不掉电。根据手册决定,我的是大约15us刷新一次。刷新过程如下

这是官方定义的刷新,按照它的要求来说如下

1.首先发出precharge命令,同时设置A10和bank信息,这个和初始化的第一步一样,然后延时tRP时刻

2.发送自动刷新命令,然后延时tRFC时刻,约63ns

3.重复第二步

好了,以上就是sdram简单的一个读写操作了,具体还是来看代码吧

module sdram(
clk,
rst,
choose,
inaddress,
indata,
sdb,
sa,
dqm,
command,
inidone,
wdone,
rdone,
redone,
outdata
);input clk;
input rst;
input [3:0]choose;
input [23:0]inaddress;// 前两位bank,后13行地址,后9列地址
input [15:0]indata;
inout reg [15:0]sdb; //数据口
output reg [14:0]sa; //bank 和地址
output reg [1:0]dqm;
output reg [4:0]command; //[4]CKE , [3]CSn, [2]RAS, [1]CASn, [0]WEn
output reg inidone;
output reg wdone;
output reg rdone;
output reg redone;
output reg [15:0]outdata;reg [4:0]i;
reg [15:0]count;
always@(posedge clk or negedge rst)
if(!rst)
beginsdb<=16'd0;sa<=15'h7fff;dqm<=2'b11;command<=5'b10111; //无操作i<=5'b0;count<=16'd0;inidone<=1'b0;wdone<=1'b0;rdone<=1'b0;redone<=1'b0;outdata<=16'd0;
end
else if(choose[0])//初始化
case(i)0: if(count==16'd10000)begincount<=16'd0;i<=i+1'b1;endelsecount<=count+1'b1;1: begin command <= 5'b10010; sa<=15'h7fff; i <= i + 1'b1; end//预充电2,3: begin command<=5'b10111;i<=i+1'b1; end //延时40ns 20ns就够 无操作4: begin command<=5'b10001; i<=i+1'b1; end//自动刷新5,6,7,8: begin command<=5'b10111;i<=i+1'b1; end9: begin command<=5'b10001; i<=i+1'b1; end//自动刷新10,11,12,13: begin command<=5'b10111;i<=i+1'b1;end14: begin command<=5'b10000; sa<={4'b0,4'b0,3'b010,4'b0011};i<=i+1'b1; end15,16: begin command<=5'b10111;i<=i+1'b1; end //延时两个时钟17: begin inidone<=1'b1; i<=i+1'b1; end18: begin inidone<=1'b0; i<=5'b0; end
endcase
else if(choose[1]) //写1数据
case(i)0:begin command<=5'b10011; sa<=inaddress[23:9]; sdb<=indata;i<=1+1'b1; end//active 先把数据写入1,2: begin command<=5'b10111; i<=i+1'b1; end //3: begin command<=5'b10100; sa<={inaddress[23:22],4'b0010,inaddress[8:0]}; dqm<=2'b00;i<=i+1'b1; end //列地址,a10拉高自动充电4,5,6: begin command<=5'b10111; dqm<=2'b11; i<=i+1'b1; end7: begin wdone<=1'b1; i<=i+1'b1; end8: begin wdone<=1'b0; i<=5'b0; end
endcase
else if(choose[2]) //读数据
case(i)0:begin command<=5'b10011; sa<=inaddress[23:9]; i<=1+1'b1; sdb<=16'hzzzz;end//active且拉高数据总线做输出1,2: begin command<=5'b10111; i<=i+1'b1;end //先把数据写入3: begin command<=5'b10101; sa<={inaddress[23:22],4'b0010,inaddress[8:0]};dqm<=2'b00; i<=i+1'b1; end4,5,6: begin command<=5'b10111; dqm<=2'b11; i<=i+1'b1; end7: begin outdata<=sdb; i<=i+1'b1; end8: begin rdone<=1'b1; i<=i+1'b1; end9: begin rdone<=1'b0; i<=5'b0; end
endcase
else if(choose[3]) //刷新
case(i)0: begin command<=5'b10001; i<=i+1'b1; end //ar1: begin command<=5'b10111; i<=i+1'b1; end2: begin redone<=1'b1; i<=i+1'b1; end3: begin redone<=1'b0; i<=5'b0; end
endcase
endmodule
module sdram_test(
clk,
rst,
sdb,
sa,
dqm,
command,
slk,
led
);
input clk;
input rst;
inout wire [15:0]sdb; //数据口
output wire [14:0]sa; //bank 和地址
output wire [1:0]dqm;
output wire [4:0]command; //[4]CKE , [3]CSn, [2]RAS, [1]CASn, [0]WEn
output slk;
output reg [3:0]led;assign slk=clk;reg [3:0]choose;
reg [23:0]inaddress;
reg [15:0]indata;
wire inidone;
wire wdone;
wire rdone;
wire redone;
wire [15:0]outdata;
sdram sdram(
.clk(clk),
.rst(rst),
.choose(choose),
.inaddress(inadress),
.indata(indata),
.sdb(sdb),
.sa(sa),
.dqm(dqm),
.command(command),
.inidone(inidone),
.wdone(wdone),
.rdone(rdone),
.redone(redone),
.outdata(outdata)
);reg [3:0]i;
reg [15:0]count;
reg [27:0]ccount;
always@(posedge clk or negedge rst)
if(!rst)
beginchoose<=4'b0001;//inaddress<=24'b0;//indata<=16'h1234;i<=4'b0;count<=16'd390;
end
else
case(i)0: if(inidone) begin i<=i+1'b1; choose<=4'b0010; endelse begin choose<=4'b0001; end  1: if(wdone) begin i<=i+1'b1; choose<=4'b0100; endelse begin inaddress<=24'b0; indata<=16'h1234; end2: if(rdone) begin led<=outdata[3:0];count<=16'd390;ccount<=28'd0;i<=i+1'b1;end3: if(count==16'd390)beginchoose<=4'b1000;count<=16'b0;ccount<=ccount+1'b1;endelse if(redone)beginchoose<=4'b0000;endelse if(ccount==28'd128205)begini<=i+1'b1;ccount<=28'd0;choose<=4'b0100;count<=16'd0;endelsecount<=count+1'b1;4: if(rdone) begin led<=outdata[7:4];count<=16'd390;ccount<=28'd0;i<=i+1'b1;end5: if(count==16'd390)beginchoose<=4'b1000;count<=16'b0;ccount<=ccount+1'b1;endelse if(redone)beginchoose<=4'b0000;endelse if(ccount==28'd128205)begini<=i+1'b1;ccount<=28'd0;choose<=4'b0100;count<=16'd0;endelsecount<=count+1'b1;6: if(rdone) begin led<=outdata[11:8];count<=16'd390;ccount<=28'd0;i<=i+1'b1;end7: if(count==16'd390)beginchoose<=4'b1000;count<=16'b0;ccount<=ccount+1'b1;endelse if(redone)beginchoose<=4'b0000;endelse if(ccount==28'd128205)begini<=i+1'b1;ccount<=28'd0;choose<=4'b0100;count<=16'd0;endelsecount<=count+1'b1;8: if(rdone) begin    led<=outdata[15:12];count<=16'd390;ccount<=28'd0;end
endcaseendmodule

这是一个简单的测试,将数据写入后每隔一秒读数据的四位来检测其稳定性。好了简单的例子就完成了,要更多的操作可以看数据手册。还是很必要的。

好了,博主快不行了,更多的负面情绪就不继续传递了。写博客的时候感觉心里很失落,总感觉少了点什么,不知道还要持续多久。。。哎。。。人生总是这样,充满了戏剧,同样也没有永远的承诺。。。

利用FPGA实现简单的sdram的读写操作相关推荐

  1. 利用java poi对excel表的读写操作

    2019独角兽企业重金招聘Python工程师标准>>> 利用java poi对excel表的读写操作 POI简介: Apache POI是一种流行的API,它允许程序员使用Java程 ...

  2. php利用文件做数据储存,PHP_PHP文件读写操作之文件写入代码,在PHP网站开发中,存储数据通 - phpStudy...

    PHP文件读写操作之文件写入代码 在PHP网站开发中,存储数据通常有两种方式,一种以文本文件方式存储,比如txt文件,一种是以数据库方式存储,比如Mysql,相对于数据库存储,文件存储并没有什么优势, ...

  3. 利用FPGA实现简单的CPU

    微处理器结构简介 根据处理器体系结构的不同,可分为冯·诺依曼结构和哈佛结构两种.冯·诺依曼型的处理器以存器程序原理为基础,将程序和数据混合存放在单一存储器中,并使用单一处理部件按"取指-分析 ...

  4. 【FPGA】SPI协议详解及对flash读写操作

    FPGA基于SPI实现对flash读写操作 概括 一.SPI协议.flash讲解 1.SPI协议 2.flash (1)WREN (2)RDID (3)WRSR (4)READ (5)PP (6)SE ...

  5. FPGA学习日记(八)SDRAM的读写测试

    目的:对SDRAM进行读写测试,使用FIFO对SDRAM进行封装. SDRAM功能框图: SDRAM原理图: 初始化状态机: 工作状态机: 代码如下: SDRAM顶层模块:连接外部芯片与测试灯,并通过 ...

  6. FPGA中用verilog直接读写操作SDRAM

    1 简介 SDRAM 型号为MT48LC32M16A2.SDRAM,英文名是: Synchronous Dynamic Random Access Memory,相较于 SRAM(静态存储器), SD ...

  7. 利用FPGA实现外设通信接口之:利用FPGA实现USB 2.0通信接口

    10.3  利用FPGA实现USB 2.0通信接口 10.3.1  USB 2.0接口的实现方式 利用FPGA来实现USB 2.0接口的方式一般有两种,一是借助外围的USB接口芯片,二是FPGA内部实 ...

  8. matlab segy文件,利用matlab实现segy格式数据的读写研究和分析.ppt

    利用matlab实现segy格式数据的读写研究和分析 2.SEGY数据格式 地震数据一般以地震道为单位进行组织,采用SEG-Y文件格式存储.SEG-Y格式是由SEG (Society of Explo ...

  9. Android之利用SharedPreferences进行简单数据存储

    1.SharedPreferences是Android系统提供的轻量级的数据保存方式,是将数据以最简单的方式进行永久性保存,在应用程序的使用中,用户经常会根据自己的习惯和偏好等更改应用程序的设置,或设 ...

最新文章

  1. DP UVALive 6506 Padovan Sequence
  2. 在线CSS工具及相关资源收集
  3. Windows:让Windows XP中的IIS支持多站点的工具
  4. Python进阶4——元组与拆包
  5. UI- UIView控件知识点回顾
  6. php+nginx导入太大文件报http error错误的原因
  7. javascript闭包_JavaScript闭包教程–带有JS闭包示例代码
  8. Failed to install Tomcat7 service 解决
  9. python标准库之re
  10. java基础—TreeSet集合中储存自定义对象(java集合二)
  11. linux下MySQL使用方法
  12. 快速接入阿里云应用配置管理工具 轻松开启企业效率新时代
  13. 零基础带你学习计算机网络—(四)
  14. 阿里正式进军机器人赛道,首款物流机器人“小蛮驴”来了!
  15. Gallery和BaseAdapter容器
  16. java反射机制历史_java的反射机制浅谈
  17. Android native crash debug
  18. Kafka(zookeeper)环境配置超级详细
  19. vue-cli首页加载速度慢优化vender+vue预加载
  20. Hadoop生态圈:19个让大象飞起来的工具!

热门文章

  1. 聊聊 PC 端自动化最佳方案 - WinAppDriver
  2. 单片机控制继电器 使LED灯交替闪烁
  3. 语义分割数据增强python代码
  4. java前端的日期插件_几个前端时间插件总结
  5. C++实现的基于NSM的简易数据库
  6. oracle clob导入mysql_Oracle数据库中包含CLOB字段表的导出和导入
  7. 反序列化漏洞分析讲解
  8. AI芯片的分类及应用
  9. centos无网络BROADCAST,MULTICAST,UP,LOWER_UP
  10. 思考让人学有所得,学有所获