SDRAM初始化过程

项目名称

SDRAM初始化

具体要求

对sdram进行初始化设计,并仿真验证

设计说明

SDRAM即同步动态随机存储器,同步是指SDRAM时钟频率与控制器的时钟频率相同,动态是指存储阵列需要不断的刷新来保证数据不丢失,随机是指数据的读取和写入可以随机指定地址。

SDRAM存储数据是 利用电容能够保持电荷以及其充放电特性,对于一位数据的存取,首先需要打开行地址,然后打开列地址,电容的电平状态就可以呈现在数据线上。打开行地址需要一定的时间,经过tRCD时间才可以打开列地址,打开列地址同样需要经过列选通潜伏期CL之后才能进行读写。SDRAM所有信号在时钟上升沿被寄存。

本开发板上为128M的SDRAM,SDRAM拥有4个BANK,每个bank可以存储32M的数据,每个BANK有4096行512列,数据位宽为16位。

SDRAM的存储容量计算是       数据位宽X一个bank中的行数X一个bank中的列数Xbank数量

本项目主要是对SDRAM进行初始化,对SDRAM的操作命令,是通过CS_N,RAS_N,CAS_N,WE_N这四个控制信号组成来控制的。

        {CS_N,RAS_N,CAS_N,WE_N} 命令 命令说明
4‘b1xxx 禁止命令执行。  
4‘b0111 空命令。NOP 无需操作
4'b0000 加载模式寄存器。 只有在所有bank空闲状态才可以进行,执行此命令的响应周期为tMRD
4‘b0011

激活命令。

激活一个特定的bank和行,BA0和BA1用来选择特定的bank,地址线A0-A12选择指定的行,如果需   要关闭该行需要执行一次预充电命令,该行才会被关闭。
4'b0101 读命令。 对一个已经激活的行突发读操作,A10控制是否在突发读取完成之后立即执行预充电,为高电平则读取完当前行之后立即执行预充电,若为低电平则不关闭该行。
4‘b0100 写命令。 对一个已经激活的行突发写入操作,A10控制是否在突发读取完成之后立即执行预充电,为高电平则读取完当前行之后立即执行预充电,若为低电平则不关闭该行。
4'b0010 预充电命令。 其作用就是关闭指定bank或全部bank中已经打开的行,执行此命令的响应周期为tRP。A10为高电平的时候对所有bank进行预充电,为低电平时只对指定bank中的行进行预充电。
4'b0001 自动刷新。

在执行自动刷新之前所有bank必须被预充电(关闭),间隔至少为tRP时间,对于128M的SDRAM每64ms要执行4096次自动刷新命令。

 

 

 

 

 

 

 

 

 

 

 

 

 

 SDRAM上电必须被初始化,需要先延迟200us,在这期间只能赋值给禁止命令或空操作命令,然后对SDRAM执行一次预充电命令,使所有BANK(A10=1)都处于空闲状态,等待tRP之后(在这个过程中保持禁止命令或者空操作命令),执行两个周期的自动刷新命令,每个自动刷新命令执行之后需要等待tRFC才可执行下一个命令,最后发出装在模式寄存器命令设置模式寄存器,模式寄存器的值由A0-A11传输,等待tMRD之后就可以进行行激活等其他命令。

BA1 BA0 A11 A10              A9 A8 A7 A6 A5 A4          A3 A2 A1 A0
        写突发模式设置寄存器 运行模式设置寄存器 列选通潜伏期设置寄存器 突发类型寄存器 突发长度寄存器
        为0代表读写突发模式 0 0 011潜伏期为3,100M时钟 0连续型 011突发长度为8

 

根据以下流程图进行代码设计

 

 

SDRAM初始化过程_第1张图片

代码设计

将需要定义的参数在单独文件中进行定义

`define ASIZE 13//地址位宽
`define DSIZE 16//数据位宽
`define BSIZE 2 //bank位宽

//操作命令
//空操作
parameter C_NOP =4'b0111;
//预充电
parameter C_PRE =4'b0010;
//自动刷新
parameter C_AREF=4'b0001;
//加载模式寄存器
parameter C_MSET=4'b0000;
//激活
parameter C_ACT =4'b0011;
//读
parameter C_RD  =4'b0101;
//写
parameter C_WR  =4'b0100;


//采用100M的时钟
parameter INIT_PRE=20000;//初始化等待200us,100M时钟下
parameter REF_PRE =3;	 //预充电等待tRP 30ns
parameter REF_REF =10;	 //自动刷新等待tRFC 60ns
parameter AUTO_REF=1560;	 //自动刷新周期<64ms/4096=15625ns
parameter LMR_ACT =2;	 //加载模式寄存器到可激活的延迟
parameter WR_PRE  =2;	 //写操作完成到预充电时间间隔
parameter SC_RCD  =3;	 //激活到读写命令延时

//模式寄存器参数化表示
parameter SC_CL  =3;//列选通潜伏期
parameter SC_BL  =8;//突发长度设置
parameter OP_CODE=0;//写突发模式设置
parameter SDR_BL =(SC_BL==8)?3'b011: 3'b111;

parameter SDR_BT=0;//突发类型设置
parameter SDR_CL=(SC_CL==2)? 3'b10 : 3'b11 ;//写突发模式设置

      


 SDRAM初始化设计,需要注意的是如果参数定义的不都是用define定义,包含的头文件必须写在模块内部,否则会报错,如果是用define定义的参数,包含头文件也可以写在模块外面,可查看笔者的lcd液晶显示项目。


module sdram_init(

	clk,
	rst_n,
	command,//命令信号
	saddr,//地址信号
	init_done
);
	
`include  "params.h"
	input						 clk;
	input						 rst_n;
	output reg[3:0]		 command;//命令信号
	output reg[`ASIZE-1:0]saddr;//地址信号
	output					 init_done;


localparam init_PRE_TIME	=INIT_PRE;//初始化等待200us,100M时钟下
localparam init_AREF1_TIME =INIT_PRE+REF_PRE;//初始化等待200us,然后预充电等待tRP预充电周期
localparam init_AREF2_TIME =INIT_PRE+REF_PRE+REF_REF;//等待第一个自动刷新周期
localparam init_LMR_TIME   =INIT_PRE+REF_PRE+REF_REF*2;//等待第2个自动刷新周期
localparam init_END_TIME   =INIT_PRE+REF_PRE+REF_REF*2+LMR_ACT;//初始化结束

//初始化过程计数器
reg [15:0] init_cnt;
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		init_cnt<=0;
	else if(init_cnt

仿真结果

在仿真之前,需要添加SDRAM的仿真模型,在镁光官网可以下载,需要用到sdr.v和sdr_parameter.h文件。

`timescale 1ns/1ns
`define clk_period 10

module sdram_init_tb;
`include "../dev/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;
	
assign command={cs_n,ras_n,cas_n,we_n};
assign sd_clk=~clk;//数据和时钟呈中心对齐
	
sdram_init sdram_init(
	.clk(clk),
	.rst_n(rst_n),
	.command(command),//命令信号
	.saddr(saddr),//地址信号
	.init_done(init_done)
);


//sdram模型例化
sdr sdr(
	.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=0;
always #(`clk_period/2) clk=~clk;

initial begin
	rst_n=0;
	#(`clk_period*200+1)
	rst_n=1;
	
	@(posedge init_done)
		#2000;
		$stop;
end

endmodule

加载模式寄存器后{OP_CODE,2'b00,SDR_CL,SDR_BT,SDR_BL}=0_00_011 _0_011,这个代码调试了两个两个小时,应该是软件的问题,代码对着就是波形出来的数据一直是错的,至今还没找到具体的原因,感觉这种跨文件传输数据应该用宏定义比较保险吧。

 

SDRAM初始化过程_第2张图片

你可能感兴趣的:(项目进阶)