SDRAM控制器设计(3)初始化操作
1.初始化操作
参考博客https://blog.csdn.net/fxltsbl007/article/details/79114640
在对 SDRAM 进行正常的操作之前, SDRAM 必须被初始化。
初始化流程
a、给SDRAM上电,并提供稳定的时钟,至少100us
b、发送“空操作”(NOP)命令
c、发送“预充电”命令,控制所有BANK进行预充电,并等待tRP的时间
tRP表示预充电和其他命令之间的延时
d、发送至少2个“自送刷新”命令,每个命令后需等待
tRC时tRC表示自送刷新时间
e、发送“加载模式寄存器”命令,配置SDRAM的工作参数,等待tMDR时间
tMDR表示加载模式寄存器命令与行有效或刷新命令之间的延时
f、初始化流程完毕,可以开始读写操作
SDRAM 具体的上电初始化时序图如图
具体操作步骤
- 加载电源( VDD 和 VDDQ);
- CKE 设置为低低电平( LVTTL 逻辑低电平);
- 加载稳定的时钟信号;
- 等待至少 100us 的时间,此过程中的命令保持为禁止命令或空操作命令;
- 在步骤 4 的 100us 中的某个时刻,将 CKE 设置为高;
- 步骤 4 的 100us 等待时间结束后,随即可发出一个全部 BANK 的预充电命令;
- 等待时间 tRP,此过程中命令保持为禁止命令或空操作命令;
- 步骤 7 钟的等待时间 tRP 结束时,发出一个自动刷新命令;
- 等待时间 tRFC( Auto refresh period),此过程中命令仅允许是禁止命令或空操作命令;
- 步骤 9 中的等待时间 tRFC 结束时,再发出一个自动刷新命令;
- 再等待时间 tRFC,此过程中命令仅允许是禁止命令或空操作命令;
- 步骤 11 中的等待时间 tRFC 结束时,发出装载模式寄存器命令设置模式寄存器,具体模式寄存器的值由 A0~A11 传输;
- 等待时间 tMRD( LOAD MODE REGISTER command to ACTIVE orREFRESH command),此过程中命令仅允许是禁止命令或空操作命令。
为什么要预充电呢?下面来看一下专业的解释:
SDRAM的寻址具有独占性,所以在进行完读写操作后,如果要对同一个Bank的另一行进行寻址,就要将原来有效(ACTIVE)的行关闭,重新发送行/列地址。Bank关闭当前工作行,准备打开新行的操作就是预充电。
预充电可以通过独立的命令控制,也可以在每次发送读写命令的同时使用“A10”线控制自动进行预充电。实际上,预充电是一种对工作中所有存储阵列进行数据重写,并对行地址进行复位,以准备新行的工作。
查阅手册,设置时间参数,假如本实验时钟为100Mhz,则单位均为一周期10ns。
parameter INIT_PRE = 20000; //初始化等待时间,不小于 100us,这里取 200us
parameter REF_PRE = 3; //等待时间 tRP,不小于 20ns,这里取 30ns
parameter REF_REF = 10; //等待时间 tRFC,不小于 66ns,这里取 100ns
localparam init_PRE_TIME = INIT_PRE, //预充电时刻
init_AREF1_TIME = INIT_PRE+REF_PRE, //自动刷新时刻
init_AREF2_TIME = INIT_PRE+REF_PRE+REF_REF, //自动刷新时刻
init_LMR_TIME = INIT_PRE+REF_PRE+REF_REF*2,//加载模式寄存器
init_END_TIME = INIT_PRE+REF_PRE+REF_REF*2+LMR_ACT; //结束时刻
其他参数设置
// 地址和数据位宽
`define ASIZE 13 //SDRAM 地址位宽
`define DSIZE 16 //SDRAM 数据位宽
`define BSIZE 2 //SDRAM 的 bank 地址位宽
//操作命令{CS_N,RAS_N,CAS_N,WE}
parameter C_NOP = 4'b0111, //空操作命令
C_PRE = 4'b0010, //预充电命令
C_AREF = 4'b0001, //自动刷新命令
C_MSET = 4'b0000, //加载模式寄存器命令
C_ACT = 4'b0011, //**命令
C_RD = 4'b0101, //读命令
C_WR = 4'b0100; //写命令
////////////100 MHz ///////////////
parameter INIT_PRE = 20000; //初始化等待时间>100us,取 200us
parameter REF_PRE = 3; //tRP >=18ns,取 30ns
parameter REF_REF = 10; //tRFC >=60ns,取 100ns
parameter AUTO_REF = 750; //自动刷新周期<64ms/8192=7812.5ns
parameter LMR_ACT = 2; //装在模式寄存器到可**延时
parameter WR_PRE = 2; //写操作写数据完成到预充电时间间隔
parameter SC_RCD = 3; //**到读命令或写命令延时 tRCD>18ns
// SDRAM 模式寄存器参数化表示
parameter SC_CL = 2; //列选通潜伏期
parameter SC_BL = 8; //突发长度设置, 1,2,4,8 可选
parameter OP_CODE = 1'b0; //写突发模式设置
parameter
SDR_BL = (SC_BL == 1)? 3'b000:(SC_BL == 2)? 3'b001:(SC_BL == 4)? 3'b010:(SC_BL == 8)? 3'b011:3'b111;
//用parameter达成了优先级式选通的功能
parameter SDR_BT = 1'b0; //突发类型设置
parameter SDR_CL = (SC_CL == 2)? 3'b10: 3'b11;
在其他模块文件中如果需要使用这些参数,只需在其模块内部包含文件夹中的这个文件即可,文件的路径读者根据自己的实际情况进行更改,具体表示如下:
`include "../src/Sdram_Params.h"
接下来就通过线性序列机的方法进行初始化过程的设计,首先,对初始化过程的时间进行计数
//SDRAM 初始化过程时间计数器
reg [15:0]init_cnt;
aaa@qq.com(posedge Clk or negedge Rst_n)
begin
if(!Rst_n)
init_cnt <= 16'd0;
else if(init_cnt < init_END_TIME)
init_cnt <= init_cnt + 16'd1;
else
init_cnt <= 16'd0;
end
//SDRAM 初始化过程,类似线性序列机
//相应时刻发出对应的命令和操作
aaa@qq.com(posedge Clk or negedge Rst_n)
begin
if(!Rst_n)
begin
Command <= C_NOP;
Saddr <= 0;
end
else
begin
case(init_cnt)
init_PRE_TIME:
begin
Command <= C_PRE;
Saddr[10] <= 1'b1;
end
init_AREF1_TIME:
begin
Command <= C_AREF;
end
init_AREF2_TIME:
begin
Command <= C_AREF;
end
init_LMR_TIME:
begin
Command <= C_MSET;
Saddr <= {OP_CODE,2'b00,SDR_CL,SDR_BT,SDR_BL};
end
default:
begin
Command <= C_NOP;
Saddr <= 0;
end
endcase
end
end
//SDRAM 初始化完成结束标志位
assign Init_done = (init_cnt == init_END_TIME);
仿真
选用了镁光官网下载的 SDRAM 模型sdr,是包含多个文件的压缩包,仿真需要用到是压缩包里的sdr.v 和 sdr_parameters.vh 两个文件,具体改动详见小梅哥教程P636
`timescale 1ns/1ns
`define CLK100_PERIOD 10
module sdram_init_tb;
`include "../src/Sdram_Params.h"
reg Clk;
reg Rst_n;
wire [3:0] Command;
wire [`ASIZE-1:0]Saddr;
wire Init_done;
wire sd_clk;
wire Cs_n;
wire Ras_n;
wire Cas_n;
wire We_n;
//SDRAM 初始化模块例化
sdram_init sdram_init(
.Clk(Clk),
.Rst_n(Rst_n),
.Command(Command),
.Saddr(Saddr),
.Init_done(Init_done)
);
assign {Cs_n,Ras_n,Cas_n,We_n} = Command;
assign sd_clk = ~Clk;
//SDRAM 模型例化
sdr sdram_model(
.Dq(),
.Addr(Saddr),
.Ba(),
.Clk(sd_clk),
.Cke(Rst_n),
.Cs_n(Cs_n),
.Ras_n(Ras_n),
.Cas_n(Cas_n),
.We_n(We_n),
.Dqm()
);
//系统时钟产生
initial Clk = 1'b1;
always #(`CLK100_PERIOD/2) Clk = ~Clk;
initial
begin
Rst_n = 1'b0;
#(`CLK100_PERIOD*200+1);
Rst_n = 1'b1;
@(posedge Init_done)
#2000;
$stop;
end
endmodule
上一篇: Spring MVC 开发环境搭建
推荐阅读
-
【java框架】SpringMVC(3)--SpringMVC控制器常用业务操作
-
Scratch3.0 页面初始化同时加载sb3文件的操作代码
-
s3c2440 sdram初始化
-
【java框架】SpringMVC(3)--SpringMVC控制器常用业务操作
-
JavaScript高级程序设计(第3版)学习笔记4 js运算符和操作符_基础知识
-
SDRAM控制器设计(4)自动刷新&自刷新操作
-
【至简设计案例系列】基于FPGA的SDRAM控制器设计(三)读写
-
SDRAM控制器设计(5)不带自动预充电的写操作时序
-
SDRAM之初始化(波形设计、代码设计、仿真调试)
-
SDRAM控制器设计(6)不带自动预充电的读操作时序