SDRAM读写一字(上)
SDRAM读写一字
系统设计

SDRAM指令
|
指令 |
常量名 |
CKE |
CSn |
RAS |
CASn |
WEn |
备注 |
|
空操作 |
NOP |
1 |
0 |
1 |
1 |
1 |
|
|
行激活 |
ACTIVE |
1 |
0 |
0 |
1 |
1 |
|
|
读操作 |
READ |
1 |
0 |
1 |
0 |
1 |
|
|
写操作 |
WRITE |
1 |
0 |
1 |
0 |
0 |
|
|
预充电 |
PR |
1 |
0 |
0 |
1 |
0 |
|
|
自刷新 |
AR |
1 |
0 |
0 |
0 |
1 |
|
|
设置寄存器 |
LMR |
1 |
0 |
0 |
0 |
0 |
|
|
突发停止 |
BURST_STOP |
1 |
0 |
1 |
1 |
0 |
1 |
SDRAM初始化
SDRAM控制模块发送初始化使能信号,使能SDRAM初始化模块,然后进行初始化操作,初始化操作完成后,发出初始化完成信号到SDRAM控制模块,SDRAM控制模块进入下一步操作。

Init_start用于启动SDRAM初始化模块进行初始化,done_init用于反馈SDRAM初始化模块初始化完成。在SDRAM初始化的过程中,根据初始化的每一个步骤,进行输出指令和SDRAM_address信号。
初始化时序

初始化操作流程图

SDRAM初始化代码
该工程的时钟频率为20MHz
module sdram_init(
clk,
reset_n,
init_start,
init_done,
sdram_command,
sdram_address
);
//参数定义
parameter T200US = 12'd3999; //上电延迟200us
//端口定义
input clk; //时钟信号20MHz
input reset_n; //复位信号
input init_start; //初始化开始信号,高电平有效
output init_done; //初始化完成信号,输出,高电平有效
output [4:0] sdram_command; //cke、cs_n、ras、cas_n、we_n,SDRAM指令信号
output [13:0] sdram_address; //[13:12]BA , [11:0]Addr,SDRAM地址信号
//常量定义
parameter NOP = 5'b10111, //空操作
ACTIVE = 5'b10011, //行激活
READ = 5'b10101, //读操作
WRITE = 5'b10100, //写操作
PR = 5'b10010, //预充电
AR = 5'b10001, //自刷新
LMR = 5'b10000; //设置寄存器
parameter SET_MODE_REG = {4'd0, 1'b0, 2'd0, 3'b010, 1'b0, 3'b011};
,顺序操作,突发长度为8
//寄存器定义
reg [11:0] time_cnt; //上电延迟计数寄存器
reg [4:0] sdram_command_reg; //SDRAM指令寄存器
reg [13:0] sdram_address_reg; //SDRAM地址信号寄存器,{bank,address}
reg init_done_reg; //初始化完成信号寄存器
reg [3:0] state_cnt; //状态机计数器,用于控制状态跳转
//*****************************************************************************
// 模块名称:SDRAM初始化模块
// 功能描述:在初始化开始控制信号的控制下进行初始化操作,操作完成后发出初始化完成信号
//*****************************************************************************
always @(posedge clk or negedge reset_n)
begin
if(reset_n == 1'b0)
begin
time_cnt <= #1 12'd0; //上电延迟计数寄存器清零
state_cnt <= #1 4'd0; //状态计数器初始化
init_done_reg <= #1 1'b0; //初始化完成寄存器清零
sdram_command_reg <= #1 NOP; //SDRAM指令寄存器初始化
sdram_address_reg <= #1 14'h3fff; //SDRAM地址信号寄存器进行置高
end
else
begin
if(init_start == 1'b1)
case (state_cnt)
4'd0://上电延迟200us
begin
if(time_cnt == T200US) //判断200us延迟是否结束
begin
state_cnt <= #1 state_cnt + 1'b1;
time_cnt <= #1 12'd0;
end
else
time_cnt <= #1 time_cnt + 1'b1;
end
4'd1://预充电操作
begin
sdram_command_reg <= #1 PR;
sdram_address_reg <= #1 14'h3fff;
state_cnt <= #1 state_cnt + 1'b1;
end
4'd2://空操作
begin
sdram_command_reg <= #1 NOP;
state_cnt <= #1 state_cnt + 1'b1;
end
4'd3://自动刷新
begin
sdram_command_reg <= #1 AR;
state_cnt <= #1 state_cnt + 1'b1;
end
4'd4,4'd5://空操作
begin
sdram_command_reg <= #1 NOP;
state_cnt <= #1 state_cnt + 1'b1;
end
4'd6://自动刷新
begin
sdram_command_reg <= #1 AR;
state_cnt <= #1 state_cnt + 1'b1;
end
4'd7,4'd8://空操作
begin
sdram_command_reg <= #1 NOP;
state_cnt <= #1 state_cnt + 1'b1;
end
4'd9://设置寄存器
begin
sdram_command_reg <= #1 LMR;
state_cnt <= #1 state_cnt + 1'b1;
sdram_address_reg <= #1 SET_MODE_REG;
end
4'd10,4'd11://空操作
begin
sdram_command_reg <= #1 NOP;
state_cnt <= #1 state_cnt + 1'b1;
end
4'd12://设置初始化完成信号
begin
init_done_reg <= #1 1'b1;
state_cnt <= #1 state_cnt + 1'b1;
end
4'd14://恢复初始化完成信号
begin
state_cnt <= #1 4'd0;
end
default://其他状态,恢复到初始状态
begin
state_cnt <= #1 4'd0;
sdram_command_reg <= #1 NOP;
end
endcase
end
end
//*****************************************************************************
assign init_done = init_done_reg;
assign sdram_command = sdram_command_reg;
assign sdram_address = sdram_address_reg;
endmodule
SDRAM读写模块

state_signal: 状态信号,用于控制对SDRAM进行读写和自刷新;
sdram_bank_addr:SDRAM最小单元地址,[21:20]块地址+[19:8]行地址Row+[7:0]列地址Column;
write_data: 写入SDRAM的数据;
rw_done_signal: 读写完成信号;
ar_done_signal: 自动刷新完成信号;
read_data: 从SDRAM读出的数据;
sdram_command:SDRAM指令,cke、cs_n、ras、cas_n、we_n,SDRAM指令信号;
sdram_address: SDRAM读写地址;
sdram_dqm: SDRAM数据掩码;
sdram_data: SDRAM读写数据;
state_signal有四种状态,分别为自刷新、读、写、空操作。Sdram读写控制模块根据state_signal的信号对SDRAM发出控制信息,同时接收数据和发送数据、地址。
当处于自刷新状态时,向SDRAM发送自刷新命令,自刷新完成后ar_done_signal信号有效,表明自刷新操作完成。
当处于读状态时,向SDRAM发送读数据命令、读取数据的地址sdram_bank_addr,读操作完成后rw_done_signal信号有效,表明读操作完成,这时可以从read_data读取从sdram读取的数据。
当处于写状态时,向SDRAM发送写数据命令,同时将写入的数据送往write_data,写入的地址送往sdram_bank_addr,写操作完成后rw_done_signal信号有效,表明写操作完成。
当处于空操作时向sdram发送NOP指令。
sdram_dqm为sdram的数据掩码信号,在对sdram进行读写操作时,其电平状态要与指令sdram_command相配合操作。
自刷新操作
存储体中电容的数据有效保存期上限是64ms,也就是说每一行刷新的循环周期是64ms。这样刷新速度就是:行数量/64ms 。我们在看内存规格时,经常会看到4096 Refresh Cycles/64ms 或8192 Refresh Cycles/64ms的标识,这里的4096与8192就代表这个芯片中每个L-Bank的行数。刷新命令一次对一行有效,发送间隔也是随总行数而变化,4096行时为15.625 μs。
由此每隔15us需要自刷新一次。
刷新操作采样简单的操作:
- 发送AutoRefresh命令,命SDRAM刷新内部逻辑的内容
- 相关操作需要消耗时间tRFC-63ns
自刷新时序:

自刷新代码:

读操作

读操作过程
- 发送Active命令、行(Row)和库(Bank)地址。
- 满足时间要求tRCD-20ns。
- 发送Read命令、列(Column)和库(Bank)地址,DQM拉低,拉高A10一个时钟,表示读操作后自动释放资源库(With Auto Precharge)。
- 满足CAS Latency时间要求
- CAS Latency满足之后,接下来满足时间要求tAC-6ns、tRP-20ns,然后读取数据。
读操作代码


写操作
操作过程
- 发送Active命令,发送库(Bank)和行(Row)地址信息。
- 满足tRCD时间要求,至少20ns。
- 发送Write命令、库(Bank)和列(Column)地址;A10拉高代表With Auto Precharge;
- 同时写入的一字数据。这时候DQM必须拉低。
- 满足tWR(tDPL)时间要求,至少2个时钟。
- 满足tRP时间要求,至少20ns。
- 经过时间tWR(tDPL)以后,一字数据就成功被写入。随后SDRAM开始执行Auto Precharge的操作,释放当前相关的资源库。最后经过tRP以后(Auto Precharge的操作完成)
时序图

写操作代码

每日推送不同科技解读,原创深耕解读当下科技,敬请关注微信公众号“科乎”。

SDRAM读写一字(上)的更多相关文章
- SDRAM读写一字(下)
SDRAM读写一字 SDRAM控制模块 上电后进行初始化状态,初始化完成后进入空闲状态,在此进行判断如下判断: 如果自刷新时间到,则进行自刷新操作,操作完成后重新进入空闲状态: 如果读使能有效则进行读 ...
- 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十九:SDRAM模块② — 多字读写
实验十九:SDRAM模块② — 多字读写 表示19.1 Mode Register的内容. Mode Register A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A ...
- SDRAM读写状态解析
SDRAM的写状态流程 IDLE状态到WRITE状态 (1)在IDLE状态需要先给ACT命令激活某一行,此时处于Row Active状态. (2)在Row Active状态之后,给Write命令则会进 ...
- SDRAM读写操作
SDRAM读写操作 1.读操作 2.写操作 SDRAM所有时序参数都可以在芯片手册上查到.
- Apache错误:[error] (OS 10038)在一个非套接字上尝试了一个操作
Apache错误:[error] (OS 10038)在一个非套接字上尝试了一个操作 博客分类: vb2005xu软件学习 OSApache防火墙PHPWindows 日志如下:[ ...
- android学习笔记47——读写SD卡上的文件
读写SD卡上的文件 通过Context的openFileInput.openFileOutput来打开文件输入流.输出流时,程序打开的都是应用程序的数据文件夹里的文件,其存储的文件大小可能都比较有限- ...
- Error is 10055 由于系统缓冲区空间不足或队列已满,不能执行套接字上的操作
今天上午,一个同事反映:某系统的某个通过socket来进行通信的服务无法连接上数据库里,在操作系统上用数据库的客户端测试数据库连接也出现这样的错误信息:Error is 10055 由于系统缓冲区空间 ...
- 关于OSError: [WinError 10038] 在一个非套接字上尝试了一个操作。
在使用socket的时候,写了一个while循环,就报错了.结果如下: OSError: [WinError 10038] 在一个非套接字上尝试了一个操作. 代码 import socket impo ...
- Windows服务器【由于系统缓冲区空间不足或队列已满,不能执行套接字上的操作】问题调查
今天测试反应了一个问题,说接口返回的速度变慢了,并且返回的数据也不对.然后就找到了我o(╥﹏╥)o. 第一个反应就是查日志,不查不要紧,一查吓一跳,整个服务器上所有的站点都报错了.异常信息如下: Sy ...
随机推荐
- VIM使用技巧总结
一.vim使用的基本配置 1: set nu //设置行号 2: set ts=4 //设置tab为4个空格大小 3: set expandtab //设置用空格代替tab 4: set ai //设 ...
- parted在2T以上硬盘上分区操作
parted分区生产环境如何使用? 1)pertend一般用于当硬盘(raid后)大于2t的时候分区操作,2t以下还是用fdisk分区 2)使用parted一般操作系统都已经安装好了 3)大于2t的因 ...
- 必须知道的八大种排序算法【java实现】(一) 冒泡排序、快速排序
冒泡排序 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个 ...
- MAC中设置java环境变量和MAVEN
借助于/usr/libexec/java_home进行配置 在~/.bash_profile 或者/.bash中添加(这里添加1.7版本) #JAVA_HOME export JAVA_HOME=$( ...
- monkeyrunner之安卓开发环境搭建(一)
在学习monkeyrunner之前,让我们先搭建好eclipse安卓开发环境. 对于程序开发人员而言,eclipse并不陌生,它提供了一个非常广阔的平台来开发程序.同样也可以用它来开发android程 ...
- WinCE下GPRS自动拨号软件(GPRS AutoDial)
之前在WinCE下调试USB的3G Modem时,写过一个拨号助手RASManager,基本能用.后来车机卖到俄罗斯去,客户老M提供了一个更好的GPRS自动拨号软件GPRS AutoDial,功能完善 ...
- BZOJ1085: [SCOI2005]骑士精神 [迭代加深搜索 IDA*]
1085: [SCOI2005]骑士精神 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1800 Solved: 984[Submit][Statu ...
- Noip2000 T3 单词接龙
题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...
- Android中分页滑动实现总结
手机的屏幕相对较小,因此会出现当有多项内容需要展示而不得不进行分页的情况.例如手机桌面的应用图标的展示.一般一屏可以显示4*4=16个小方块形的应用程序,可以通过左右滑动进行屏幕的选择.而Androi ...
- HTML 学习笔记 CSS3 (背景)
CSS3对于background做了一些修改,最明显的一个就是采用设置多背景,不但添加了4个新属性,并且还对目前的属性进行了调整增强. 1.多个背景图片 在CSS3里面 你可以在一个标签元素里应用多个 ...