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之后就可以进行行激活等其他命令。

BA1BA0A11A10             A9A8A7A6A5A4         A3A2A1A0
    写突发模式设置寄存器运行模式设置寄存器列选通潜伏期设置寄存器突发类型寄存器突发长度寄存器
    为0代表读写突发模式00011潜伏期为3,100M时钟0连续型011突发长度为8

 

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

 

 

代码设计

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

`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<init_END_TIME)
		init_cnt<=init_cnt+1;
	else	
		init_cnt<=0;
		
//初始化完成标志
assign init_done=(init_cnt==init_END_TIME);

//初始化过程
always@(posedge clk or negedge rst_n)
	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;//所有bank预充电
								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

	endmodule

仿真结果

在仿真之前,需要添加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,这个代码调试了两个两个小时,应该是软件的问题,代码对着就是波形出来的数据一直是错的,至今还没找到具体的原因,感觉这种跨文件传输数据应该用宏定义比较保险吧。

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值