3.SDRAM程序设计

1.SDRAM的模块划分

  SDRAM一共有四类操作:上电、刷新、读、写。
  模块分成五个:上电、刷新、读、写、仲裁。

2.SDRAM上电

在这里插入图片描述
结合 SDRAM 初始化时序图,列出 SDRAM 初始化参考流程如下:
  (1) 对 SDRAM 上电,加载稳定时钟信号,CKE 设置为高电平;
  (2) 等待 T=100us 的时间,此过程中操作命令保持为空操作命令;
  (3) 100us 等待结束后,写入预充电命令,A10 设置为高电平,对所有 L-Bank 进
行预充电;
  (4) 预充电指令写入后,等待 tRP时间,此过程中操作命令保持为空操作命令;
  (5) tRP等待时间结束后,写入自动刷新命令;
  (6) 自动刷新命令写入后,等待 tRC时间,此过程中操作命令保持为空操作命令;
  (7) tRC等待时间结束后,再次写入自动刷新命令;
  (8) 自动刷新命令写入后,等待 tRC时间,此过程中操作命令保持为空操作命令;
  (9) tRC 等待时间结束后,写入模式寄存器配置指令,地址总线 A0-A11 参数不同
辅助模式寄存器不同模式的设置;
  (10) 模式寄存器配置指令写入后,等待 tMRD 时间,此过程中操作命令保持为空操
作命令;
  (11) tMRD等待时间结束后,SDRAM 初始化完成。
在这里插入图片描述

/*----------------------------------------------------------------------------------------------------
sdram初始化
cmd真值表		cs_n	ras_n	cas_n	we_n	ba[1:0]	addr[11]	addr[10],addr[9:0]
	NOP			0		1		1		1		X		X			X		X
	PRLL		0		0		1		0		X		x			1		X
	REF			0		0		0		1		X		X			X		X

MR模式寄存器		{ba[1:0],addr[11:0]}	=	{00,00,000,011,0,010}
		
-----------------------------------------------------------------------------------------------------*/


module	sdram_init(
	input	wire		clk,	//50MHZ
	input	wire		rst,
	
	output	reg			init_end_flag,
	output	reg [17:0]	init_cmd
);
	
parameter	TRP		 		=	2,
		 	TRC		 		=	4,
		 	TMRD			=	2;

parameter	DEY_200US		=	9999, 					
		 	PALL_CNT	 	=	10000, 					
		 	REF_ST1		  	=	10001+TRP,
		 	REF_ST2		 	=	10002+TRP+TRC,
		 	MRD_CNT		 	=	10003+TRP+TRC+TRC,
			END_INIT_CNT	=	10003+TRP+TRC+TRC+TMRD;
		
parameter	NOP		=	18'h1c000,//18'b01_1100_0000_0000_0000
		 	PALL	=	18'h08400,//18'b00_1000_0100_0000_0000
		 	REF		=	18'h04000,//18'b00_0100_0000_0000_0000
		 	MR		=	18'h00032;//18'b00_0000_0000_0011_0010
			
	
reg[15:0]	init_cnt;

//时间计数器     
always @(posedge clk) begin
	if(rst == 1'b1) begin
		init_cnt <= 'd0;
	end
	else if(init_cnt == END_INIT_CNT) begin
		init_cnt <= 'd0;
	end
	else if(init_end_flag == 1'b0)begin
		init_cnt <= init_cnt + 1'b1;
	end
end

//初始化结束标志
always @(posedge clk) begin
	if(rst == 1'b1) begin
		init_end_flag <= 1'b0;
	end
	else if(init_cnt >= END_INIT_CNT) begin
		init_end_flag <= 1'b1;
	end
end

//线性序列机控制命令发送
always @(posedge clk) begin
	if(rst == 1'b1) begin
		init_cmd <= NOP;
	end
	else if(init_cnt <=DEY_200US) begin 	//等待100us  保持空操作
		init_cmd <= NOP;
	end
	else if(init_cnt ==  PALL_CNT) begin 	//100us时写入预充电指令
		init_cmd <= PALL;
	end
	else if (init_cnt >PALL_CNT && init_cnt < REF_ST1) begin 	//预充电后等待tRP时间
		init_cmd <= NOP;
	end
	else if (init_cnt == REF_ST1) begin 	//等待完成后写入自动刷新命令
		init_cmd <= REF;
	end
	else if (init_cnt >REF_ST1 && init_cnt <REF_ST2) begin 	//等待tRC
		init_cmd <= NOP;
	end
	else if (init_cnt == REF_ST2) begin 	//等待完成后再次写入自动刷新命令
		init_cmd <= REF;
	end
	else if (init_cnt >REF_ST2 && init_cnt < MRD_CNT) begin 	//等待tRC
		init_cmd <= NOP;
	end
	else if (init_cnt == MRD_CNT) begin 	//写入寄存器配置命令
		init_cmd <= MR;
	end
	else if (init_cnt >MRD_CNT ) begin 	//等待tMRD
		init_cmd <= NOP;
	end
end
endmodule		

3.SDRAM自刷新

  SDRAM属于动态存储器,需要不断的刷新来保证内部数据不丢失。自刷新时无需芯片内部会提供地址,无需手动提供。
  刷新周期为64ms,一般需要刷新4096或者8192次。及每次刷新间隔应为15.625μs(64ms/4096),8192行时为7.8125μs(64ms/8192)。
在这里插入图片描述

由 SDRAM 自动刷新时序图可知,SDRAM 的自动刷新类似于简化版的初始化操作,只是缺少了上电后的等待时间和模式寄存器配置部分,只包含一次预充电操作和两次自动刷新操作,自动刷新操作参考流程如下。
  (1) 写入预充电命令,A10 设置为高电平,对所有 L-Bank 进行预充电;
  (2) tRC等待时间结束后,自动刷新操作完成。
图中的预充电已经在其他模块完成
图中的一个刷新指令就能完成一次刷新,所以多个刷新指令实际上完成了多个刷新操作。

/*
	初始化结束后,刷新计数器开始计数
	计数到规定时间后拉高刷新请求并保持
	主控制模块接受到刷新请求后在空闲时向该模块发出刷新允许
	刷新请求和刷新允许同时拉高后发出刷新指令,并拉低刷新请求
	等待数个时钟周期后刷新结束
*/
/*----------------------------------------------------------------------------------------------------
sdram 命令
cmd真值表		cs_n	ras_n	cas_n	we_n	ba[1:0]	addr[11]	addr[10],addr[9:0]
	NOP			0		1		1		1		X		X			X		X
	PRLL		0		0		1		0		X		x			1		X
	REF			0		0		0		1		X		X			X		X

MR模式寄存器		{ba[1:0],addr[11:0]}	=	{00,00,000,011,0,010}
		
-----------------------------------------------------------------------------------------------------*/
module sdram_ref(
	input	wire 		clk,
	input	wire 		rst,
	output	reg	[17:0]	ref_cmd,	//命令信号
	input	wire 		ini_end, 	//初始化结束,即可开始刷新计时
	output	reg			ref_req, 	//向外发出刷新请求
	input	wire 		ref_en, 	//控制模块给刷新允许
	output	reg			ref_end 	//刷新结束
);

parameter   REF		=	18'h04000;//18'b00_0100_0000_0000_0000
parameter	NOP		=	18'h1c000;//18'b01_1100_0000_0000_0000
parameter   REF_CNT_END = 780;

reg	[15:0]	ref_cnt; 		//刷新间隔计数器
reg 		ref_dly_flag; 	//刷新指令后等待标志位
reg [3:0] 	ref_dly_cnt; 	//刷新等待计数器

//自动刷新计数器
always @(posedge clk) begin
	if(rst == 1'b1 ) begin
		ref_cnt <='d0;
	end
	else if (ref_cnt == REF_CNT_END) begin
		ref_cnt <= 'd0;
	end
	else if (ini_end == 1'b1) begin
		ref_cnt <= ref_cnt + 1'b1;
	end
end

//刷新时间到了就拉高刷新请求信号,控制器发出刷新允许就拉低
always @(posedge clk) begin
	if(rst == 1'b1 ) begin
		ref_req <= 1'b0;
	end
	else if (ref_en == 1'b1 ) begin
		ref_req <= 1'b0;
	end
	else if(ref_cnt == REF_CNT_END) begin
		ref_req <= 1'b1;
	end
end

//刷新请求和刷新允许同时为高时给出刷新指令   
always @(posedge clk) begin
	if(rst == 1'b1) begin
		ref_cmd <= NOP;
	end
	else if (ref_req == 1'b1 && ref_en == 1'b1 ) begin
		ref_cmd <= REF;
	end
	else begin
		ref_cmd <= NOP;
	end
end

//刷新请求发出后刷新等待标志位拉高
always @(posedge clk ) begin
	if (rst == 1'b1) begin
		ref_dly_flag <= 1'b0;
	end
	else if (ref_dly_cnt == 'd9) begin
		ref_dly_flag <= 1'b0;
	end
	else if (ref_req == 1'b1 && ref_en == 1'b1) begin
		ref_dly_flag <= 1'b1;
	end
end

//刷新等待计数器
always @(posedge clk ) begin
	if (rst == 1'b1) begin
		ref_dly_cnt <='d0;
	end
	else if (ref_dly_flag == 1'b1) begin
		ref_dly_cnt <= ref_dly_cnt + 1'b1;
	end
	else begin
		ref_dly_cnt <= 'd0;
	end
end

//刷新等待计数器记满后刷新结束
always @(posedge clk ) begin
	if (rst == 1'b1) begin
		ref_end <= 1'b0;
	end
	else if (ref_dly_cnt == 'd9) begin
		ref_end <= 1'b1;
	end
	else begin
		ref_end <= 1'b0;
	end
end
endmodule

3.SDRAM写模块

  由于SDRAM是一个半双工的存储器,且内部还有刷新操作,为了防止数据丢失,读写模块都需要借用FIFO来作为数据的中转与缓存。
  由于突发长度、突发类型等参数可设置,以及可选取是否进行自动预充电操作等诸多原因,SDRAM 数据写操作包含多种操作方式。本次编写采用的
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值