目录
1、SDRAM初始化的内容(结合英文数据手册)
2、SDRAM初始化的时序
3、代码的编写
4、modesim的仿真
SDRAM初始化的内容
SDRAMs must be powered up and initialized in a predefined manner. The 64M SDRAM is initialized after the power is applied to Vdd and Vddq, and the clock is stable with DQM High and CKE High. A 100μs delay is required prior to issuing any command other than a COMMAND INHIBIT or a NOP.
The COMMAND INHIBIT or NOP may be applied during the 100μs period and continue should at least through the end of the period.With at least one COMMAND INHIBIT or NOP command having been applied, a PRECHARGE command should be applied once the 100μs delay has been satisfied. All banks must be precharged. This will leave all banks in an idle state, after which at least two AUTO REFRESH cycles must be performed. After the AUTO REFRESH cycles are complete, the SDRAM is then ready for mode register programming.The mode register should be loaded prior to applying any operational command because it will power up in an unknown state. After the Load Mode Register command, at least two NOP commands must be asserted prior to any command.
Sdram 在工作前需要进行初始化
1、sdram 上电,时钟稳定,DQM高,CKE高,开始初始化
2、至少100us的等待时间,在这个等待时间之内不能有除了COMMAND INHIBIT 或 NOP 以外的任何命令,COMMAND INHIBIT 或 NOP命令需持续生效。
3、在100us等待时间结束之后,所有的 bank 需要预充电,(执行 PRECHARGE 需要 tRP 的时间)。
4、至少两个自动刷新命令(每个自动刷新都需要tRC的时间)
5、模式寄存器的配置(需要tMRD的时间)。
6、初始化完成以后处于idle的状态,每隔 64ms/2^12 =64_000_000 ns/4096=15625ns,因为工作时钟为100Mhz,所以需要每隔1562个时钟需要发一个自动刷新指令(这个64ms将所有行刷新一次是由SDRAM的内部结构决定的)
注意:所需要的时间需要从数据手册中得到(datasheet一定要看英文原版)
状态机
SDRAM初始化的时序
这个时序图可以结合状态机的图理解,非常重要,因为每个状态需要的时间都不一样,所以需要设计计数器。
1、CKE 一直为高电平
2、command 由 cs,ras,cas,we 四个控制信号实现,具体如下图
例如 NOP命令 cs=0,ras=1,cas=1,we=1
3、DQM在初始化的时候始终为1
4、A10为高,则忽略BA0,BA1,对所有bank 进行预刷新。
5、在配置模式寄存器时,根据自己的需求设置参数
例如当 mode_value=000_00_011_0_111 即全页模式,顺序,CL=3,突发读,突发写。
代码的编写
初始化代码
/1、工作时钟定为100Mhz
2、 Sdram 初始化
3、Sdram 的自动刷新功能:每隔 64ms/2^12=15625 个时钟周期,给出刷新命令。/
//------------------------------------------------------------------------------------
module Sdram_initial(
clk ,
rst_n ,
cke ,
cs ,
ras ,
cas ,
we ,
dqm ,
addr ,
bank ,
dq
);
input clk ; //100Mhz
input rst_n ;
output cke ; //clk enable
output cs ; //片选信号
output ras ; //行
output cas ; //列
output we ; //读写控制端
output 【11:0】 dqm ; //byte controlled by LDQM and UDQM
output 【11:0】 addr ; //12个位地址
output 【 1:0】 bank ; //sdram有4个逻辑bank
inout 【15:0】 dq ; //是三态门
wire cs ;
wire ras ;
wire cas ;
wire we ;
wire 【15:0】 dq ;
reg 【11:0】 dqm ;
reg 【11:0】 addr ;
reg 【 1:0】 bank ;
reg 【3:0】 command ;
reg 【2:0】 c_state ;
reg 【2:0】 n_state ;
reg 【13:0】 cnt_0 ;
wire get_100us ;
wire get_trp ;
wire get_trc1 ;
wire get_trc2 ;
wire get_tmrd ;
wire get_1562 ;
wire get_trc3 ;
//----------------------------------------------------------------------
parameter NOP = 3'b000;
parameter PRECHARG = 3'b001;
parameter AUTO_REF1 = 3'b010;
parameter AUTO_REF2 = 3'b011;
parameter MODE_REG = 3'b100;
parameter IDLE = 3'b101;
parameter AUTO_REF = 3'b110;
parameter TIME_100US = 10_000 ;
parameter TRP = 3 ; //这些数据由数据手册可以获得
parameter TRC = 7 ;
parameter TMRD = 2 ;
parameter TIME_1562 = 1562 ;
parameter MODE_VALUE = 12'b000_00_011_0_111; //即全页模式,顺序,CL=3,突发读,突发写。
parameter NOP_CD = 4'b0111;
parameter PRECHARGE_CD = 4'b0010;
parameter AUTO_REF_CD = 4'b0001;
parameter MODE_REG_CD = 4'b0000;
//----------------------------------------------------------------------状态机的设计
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
c_state<=NOP;
end
else begin
c_state<=n_state;
end
end
always @(*)begin
case(c_state)
NOP :begin
if(get_100us) //等待100us后跳转
n_state = PRECHARG;
else
n_state = c_state;
end
PRECHARG :begin
if(get_trp) //trp时间后
n_state = AUTO_REF1;
else
n_state = c_state;
end
AUTO_REF1 :begin
if(get_trc1) //trc
n_state = AUTO_REF2;
else
n_state = c_state;
end
AUTO_REF2 :begin
if(get_trc2) //trc
n_state = MODE_REG;
else
n_state = c_state;
end
MODE_REG :begin
if(get_tmrd) //tmrd
n_state = IDLE;
else
n_state = c_state;
end
IDLE :begin
if(get_1562) //等待1562个始终周期
n_state = AUTO_REF;
else
n_state = c_state;
end
AUTO_REF :begin if(get_trc3) //trc
n_state = IDLE;
else
n_state = c_state;
end
default : n_state = NOP; //其他状态转移到NOP
endcase
end
assign get_100us = (c_state == NOP && cnt_0 == 0)? 1'b1 : 1'b0; //cnt_0是一个递减计数器
assign get_trp = (c_state == PRECHARG && cnt_0 == 0)? 1'b1 : 1'b0;
assign get_trc1 = (c_state == AUTO_REF1&& cnt_0 == 0)? 1'b1 : 1'b0 ;
assign get_trc2 = (c_state == AUTO_REF2&& cnt_0 == 0)? 1'b1 : 1'b0 ;
assign get_tmrd = (c_state == MODE_REG && cnt_0 == 0)? 1'b1 : 1'b0 ;
assign get_1562 = (c_state == IDLE && cnt_0 == 0)? 1'b1 : 1'b0 ;
assign get_trc3 = (c_state == AUTO_REF && cnt_0 == 0)? 1'b1 : 1'b0 ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt_0 <= TIME_100US-1;
end
else if(get_100us) begin
cnt_0 <= TRP-1;
end
else if(get_trc1 || get_1562||get_trp) begin
cnt_0 <= TRC-1;
end
else if(get_trc2)begin
cnt_0 <= TMRD-1;
end
else if(get_tmrd||get_trc3)
cnt_0 <= TIME_1562-1;
else if(cnt_0 != 0)
cnt_0 <= cnt_0 -1;
end
//----------------------------------------------------------------------
assign cke=1; //cke始终为1
always @(posedge clk or negedge rst_n)begin //dqm在初始化状态始终为1
if(rst_n==1'b0)begin
dqm<=2'b11;
end
else if( c_state == NOP || c_state == PRECHARG || c_state == AUTO_REF1 ||
c_state == AUTO_REF2 || c_state ==AUTO_REF2 || c_state == MODE_REG ) begin
dqm<=2'b11;
end
else
dqm<=2'b00;
end
assign dq = 16'hzzzz; //dq为高阻态
assign {cs,ras,cas,we} = command; //cs,ras,cas,we的设计
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
command <= NOP_CD ;
//代码效果参考:http://www.jhylw.com.cn/194135451.html
endelse if(get_100us) begin
command <= PRECHARGE_CD ;
end
else if(get_trp || get_trc1 || get_1562 )
command <= AUTO_REF_CD ;
else if(get_trc2)
command <= MODE_REG_CD ;
else
command <= NOP_CD ;
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
addr <= 0;
end
else if(get_trc2) begin
addr <= MODE_VALUE;
end
else if(get_100us)
addr <= (12'b1 [ 10 ); //A10=1
else
addr <= 0;
end
always @(posedge clk or negedge rst_n)begin //bank初始化用不到,取0;
if(rst_n==1'b0)begin
bank <= 2'b00;
end
else begin
bank <= 2'b00;
end
end
endmodule
testbench
<div class="cnblogs_code_toolb