3.SDRAM的自动刷新

SDRAM 内部存储体是利用电容能够保持电荷以及可充放电的特 性制成,而电容所存储的电荷会随时间不断流失,会造成存储数据的丢失。为保证 SDRAM 中数据的可靠性,需要对 SDRAM 进行不断刷新。

SDRAM 的刷新方式分为自刷新和自动刷新两种。自动刷新模式:作用是在 SDRAM 的正常操作过程中,保证数据不丢失,自动刷新过 程需要外部时钟的参与,但刷新行地址由内部刷新计数器控制,无需外部写入。 自刷新模式则主要用于休眠模式低功耗状态下的数据保存,自刷新过程无需外部时钟 参与,与自动刷新相同的是,刷新行地址由内部刷新计算器控制,无需外部写入。两者的操作命令相同,当 CKE 信号保持高电平时,写入刷新指令,进入自动刷新模 式;当 CKE 信号为低电平时,写入刷新指令,进入自刷新模式。 自刷新模式下,除 CKE 之外的其他外部信号均无效,当 CKE 再次拉高时,退出自刷 新模式,进入正常操作状态。

自动刷新大致流程如下:

(1) 写入预充电命令,A10 设置为高电平,对所有 L-Bank 进行预充电; (2) 预充电指令写入后,等待 tRP时间,此过程中操作命令保持为空操作命令; (3) tRP等待时间结束后,写入自动刷新命令; (4) 自动刷新命令写入后,等待 tRC时间,此过程中操作命令保持为空操作命令; (5) tRC等待时间结束后,再次写入自动刷新命令; (6) 自动刷新命令写入后,等待 tRC时间,此过程中操作命令保持为空操作命令; (7) tRC等待时间结束后,自动刷新操作完成。不同的等待时间与芯片有关。

本模块的输入信号:init_end 为初始化模块传入的初始化完成标志信号,表示初始化完成, SDRAM 进入正常模式,可进行其他操作;aref_en 为自动刷新使能信号,表示仲裁模块响 应自动刷新请求,自动刷新模块可以开始自动刷新操作。 输出信号:aref_cmd、aref_ba、aref_addr 分别为自动刷新阶段的指令信号、逻辑 Bank 地址和地址总线;aref_req 为自动刷新请求信号,向仲裁模块请求执行自动刷新操作; aref_end 为自动刷新结束标志信号,告知仲裁模块自动刷新操作完成,SDRAM 可进行其他 操作。

SDRAM 的自动刷新操作是周期性执行,这里的时钟为 100MHz,周期计数器的计数范围设置为 0-749,计数时间为 7.5us。

代码如下:

//SDRAM自动刷新模块sdram_aref
module	sdram_aref
(
	input	wire	sys_clk	,	//100MHz
	input	wire	sys_rst_n,
	input	wire	init_end,	//初始化结束标志
	input	wire	aref_en,	//自动刷新使能信号(由仲裁模块传入,只有为高时才能执行刷新)
	
	output	reg			aref_req,	//自动刷新请求
	output	reg [3:0]	aref_cmd,	//输出指令
	output	reg [1:0]	aref_ba,	//输出bank地址
	output	reg [12:0]	aref_addr,	//地址总线A12-A0
	output	wire 		aref_end	//自动刷新结束标志
);

parameter	P_CHARGE = 4'b0010;		//预充电指令
parameter	A_REF	 = 4'b0001;		//自动刷新指令
parameter	NOP		 = 4'b0111;		//空操作指令

parameter AREF_IDLE = 3'b000 ; //初始状态,等待自动刷新使能
parameter AREF_PCHA = 3'b001 ; //预充电状态
parameter AREF_TRP = 3'b011 ; //预充电等待状态
parameter AUTO_REF = 3'b010 ; //自动刷新状态
parameter AREF_TRF = 3'b100 ; //自动刷新等待状态
parameter AREF_END = 3'b101 ; //自动刷新结束状态
parameter  MAX_ref = 'd750    ;  //计数的最大值(每7.5us刷新一次)

reg [2:0]	STATE_NOW;	//现态
reg	[2:0]	STATE_NEXT;	//次态
reg [9:0] cnt_ref          ;  //计数器位宽
reg [3:0] cnt_state          ;  //计数器位宽
reg [3:0]  MAX_state;			 //等待状态时需要等待的周期
reg        cnt_AUTO_REF = 0;     //计数自动刷新状态经过了几次

wire	   add_cnt_ref      ;  //计数器开始条件
wire	   end_cnt_ref      ;  //计数器结束条件
wire	   add_cnt_state      ;  //计数器开始条件
wire	   end_cnt_state      ;  //计数器结束条件

//自动刷新计数器--cnt_ref
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		cnt_ref <= 0;
	end
	else if(add_cnt_ref)begin
		if(end_cnt_ref)
			cnt_ref <= 0;
		else
			cnt_ref <= cnt_ref + 1;
	end
	else
		cnt_ref <= cnt_ref;
end
assign add_cnt_ref = init_end;//初始化结束后开始计数
assign end_cnt_ref = (add_cnt_ref && (cnt_ref>=MAX_ref-1));

//等待状态计数器--cnt_state
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		cnt_state <= 0;
	end
	else if(add_cnt_state)begin
		if(end_cnt_state)
			cnt_state <= 0;
		else
			cnt_state <= cnt_state + 1;
	end
	else
		cnt_state <= cnt_state;
end
assign add_cnt_state = (STATE_NOW==3'b011 || STATE_NOW==3'b100)?1:0;//只有在等待状态才计数
assign end_cnt_state = (add_cnt_state && (cnt_state>=MAX_state-1));


//三段式状态机
//(1)状态切换
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		STATE_NOW  <= 3'b000;					//初始状态,等待自动刷新使能
		//STATE_NEXT <= 'd0;
	end
	else
		STATE_NOW <= STATE_NEXT;
end
//(2)状态转移
always@(*)begin 
	case(STATE_NOW)
		3'b000:							 //初始状态,等待自动刷新使能		
			begin
				if(aref_en)
					STATE_NEXT<=3'b001;
				else
					STATE_NEXT<=STATE_NOW;
			end
		3'b001:							 //预充电状态
			begin 
					STATE_NEXT<=3'b011;		 //直接跳转
			end
		3'b011:							 //预充电等待状态
			begin 
				if(end_cnt_state)			 //等待两个时钟周期
					STATE_NEXT<=3'b010;
				else
					STATE_NEXT<=STATE_NOW;
			end
		3'b010:							 //自动刷新状态(需要刷新2次)
			begin
					STATE_NEXT<=3'b100;		 //直接跳转
					
			end
		3'b100:							 //自动刷新等待状态
			begin 
				if(end_cnt_state && cnt_AUTO_REF<'d1)begin
					STATE_NEXT<=3'b010;          //跳回自动刷新状态
					//cnt_AUTO_REF<=cnt_AUTO_REF+1;
				end
				else if(end_cnt_state)			 //等待7个时钟周期
					STATE_NEXT<=3'b101;
				else
					STATE_NEXT<=STATE_NOW;
			end
		3'b101:							 //自动刷新结束状态
			begin
					STATE_NEXT<=3'b000;		//直接跳转
			end	
		default:
					STATE_NEXT<=3'b000;		//回到空闲态
	endcase
end
//(3)输出控制
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		MAX_state <= 'd0;
		aref_cmd  <= NOP;			 //空操作指令
		aref_ba <= 2'b11;
		aref_addr <= 13'h1fff;	//本阶段无需操作bank和地址,输出全1
	end
	else 
		case(STATE_NOW)
			3'b000:							 //初始状态,等待自动刷新使能
				begin
					MAX_state <= 'd0;
					aref_cmd  <= NOP;			 //空操作指令
					aref_ba <= 2'b11;
					aref_addr <= 13'h1fff;
				end
			3'b001:							 //预充电状态
				begin 
					MAX_state <= 'd0;
					aref_cmd  <= P_CHARGE;		 //预充电指令
					aref_ba <= 2'b11;
					aref_addr <= 13'h1fff;
				end
			3'b011:							 //预充电等待状态
				begin
					MAX_state <= 'd2;			 //等待两个时钟周期
					aref_cmd  <= NOP;			 //空操作指令
					aref_ba <= 2'b11;
					aref_addr <= 13'h1fff;
				end
			3'b010:							 //自动刷新状态(需要刷新2次)
				begin
					MAX_state <= 'd0;
					aref_cmd  <= A_REF;		     //自动刷新指令
					aref_ba <= 2'b11;
					aref_addr <= 13'h1fff;
				end
			3'b100:							 //自动刷新等待状态(同样有2次)
				begin
					MAX_state <= 'd7;			 //等待7个时钟周期
					aref_cmd  <= NOP;			 //空操作指令
					aref_ba <= 2'b11;
					aref_addr <= 13'h1fff;
					cnt_AUTO_REF<=cnt_AUTO_REF+1;
				end
			3'b101:							 //自动刷新结束状态
				begin
					MAX_state <= 'd0;
					aref_cmd  <= NOP;			 //空操作指令
					aref_ba <= 2'b11;
					aref_addr <= 13'h1fff;
				end
			default:
				begin
					MAX_state <= 'd0;
					aref_cmd  <= NOP;			 //空操作指令
					aref_ba <= 2'b11;
					aref_addr <= 13'h1fff;
				end
		endcase
end

always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)
		aref_req <= 0;			
	else if(STATE_NOW!=3'b000) 	//当不在空闲态时,说明正处于自动刷新的过程中,因此将自动刷新请求拉低
		aref_req <= 0;			//自动刷新请求信号拉低	
	else if(end_cnt_ref)		//自动刷新周期到了
		aref_req <= 1;
	else
		aref_req <= aref_req;
end

assign	aref_end=(STATE_NOW==3'b101)?1:0; 		//在自动刷新结束状态产生一个周期的脉冲

endmodule

仿真结果如下:可以看到,执行了两次刷新指令。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值