FPGA之SDRAM控制器设计(二)

FPGA之SDRAM控制器设计(二):刷新

这次要来解决上次留下来的刷新问题,在100us后首先要经过两次刷新才进行模式寄存器设置。这颗SDRAM芯片需要每隔64ms对8192行(列地址10-位,行地址13位)的每一个存储电容进行一次刷新,因为不刷新电充会泄露电流导致存储信息丢失。那每一行的刷新时间为64/8192 ≈ 7810ns,注意刷新是以行为单位,器芯片内部有一个计数器,这个计数器不是时钟直接驱动的,而是AUTO PRECHARGE驱动,每发一次atuoprecharge命令这个计数器加1,我们是看不到的也无法对其直接置数,这个计数器一上电就进行初始化这是我们不需要关心的,我们要做的是在7810ns进行一次刷新操作就行了。所做的读和写就是在两次刷新间隔内进行的,这个会在下一节讲到。

刷新模块的设计思路是:刷新的命令状态机和一个刷新标志产生的计数器,在此基础上要加上一个主控状态机,也就是控制何时上电刷新读写的一个模块。

刷新状态转移图:

刷新状态机设计

`include	"head.v"
module ref_fsm(
		ref_done,ref_en,clk,ref_bus,soft_rst_n
);//刷新状态机
		input			clk;
		input			ref_en;
		input			soft_rst_n;
		output	reg		ref_done;
		output	[19:0]	ref_bus;
		
		reg		[12:0]	ref_a;
		reg		[1:0]	ref_ba;
		reg		[3:0]	ref_cmd;
		reg				ref_cke;
		
		assign	ref_bus = {ref_cmd,ref_a,ref_ba,ref_cke};
		
		reg		[14:0]	cnt;
		reg		[1:0]	state;
		localparam	s0 = 2'b00;
		localparam	s1 = 2'b01;
		localparam	s2 = 2'b10;
		
		
	always @(posedge clk)
		begin
			if(soft_rst_n == 1'b0)
				begin
					ref_done <= 1'b0;
					ref_ba <= 'd0;
					ref_cmd <= `NOP;
					ref_cke <= 1'b0;
					cnt <= 'd0;
					state <= s0;
				end
			else
				case(state)
					s0 : if(ref_en == 1'b0)
							begin
								ref_done <= 1'b0;
								state <= s0;
								
							end
						 else
						 	begin
						 		ref_cmd <= `PRE;
						 		ref_a[10] <= 1'b1;
						 		ref_done <= 1'b0;
						 		state <= s1;
						 		ref_cke <= 1'b1;//add
						 	end
					s1 : if(cnt < `tRP - 1)
							begin
								cnt	<= cnt + 1'b1;
								ref_cmd <= `NOP;
								state <= s1;
							end
						 else
						 	begin
						 		cnt	 <= 'd0;
						 		ref_cmd <= `REF;
						 		state <= s2;
						 	end
					s2 : if(cnt	< `tRFC - 1)
							begin
								cnt <= cnt + 1'b1;
								ref_cmd <= `NOP;
								state <= s2;	
							end
						 else
						 	begin
						 		cnt	<= 'd0;
						 		ref_done <= 1'b1;
						 		state <= s0;
						 	end
				endcase
		end
endmodule

定时模块设计

`include	"head.v"

module ref_time(
	clk,soft_rst_n,rt_en,rt_flag
);//刷新定时器
	input		clk;
	input		rt_en;
	input		soft_rst_n;
	output	reg	rt_flag;
	
	reg		[9:0]	cnt;

always @(posedge clk)begin
	if(soft_rst_n == 1'b0)
		begin
			cnt <= 'd0;
			rt_flag <= 1'b0;
		end
	else if(rt_en == 1'b1 )
			if(cnt < 780)
			begin
				cnt <= cnt + 1'b1;
				rt_flag <= 1'b0;
			end
			else begin
				cnt	 <= 'd0;
				rt_flag <= 1'b1;	
			end
		
end
endmodule

猜你喜欢

转载自blog.csdn.net/qq_41754003/article/details/107922956