SDRAM小项目——刷新模块

2024-01-08 18:51:29

记录了SDRAM控制器进行初始化配置后的刷新模块。

SDRAM要进行不停地刷新保证数据的存在,因为SDRAM类似于电容,每次放电结束后数据都会丢失,所以要进行不断地刷新,刷新间隔为15us。

控制器状态从开始的idle状态到仲裁状态,在仲裁状态下进行刷新,读,写状态的跳转。

在仲裁状态下接收到刷新请求,发送刷新使能,状态转到刷新状态,当刷新结束后发送刷新结束标志,状态跳转到仲裁状态。

文档信息:

首先进行precharge命令,trp时间后进行auto refresh命令(20ns,1个周期),文档中要进行两次刷新才能进行act命令,但是实际上只用一次就行了。

在何种情况下进行刷新:

1.每个15us以后自动进行刷新

刷新状态会输出哪些信息:

1.输出刷新请求,仲裁阶段接收到刷新请求,仲裁同意刷新才可以刷新。

2.输出刷新结束,状态跳转回到仲裁

3.刷新命令command(cs,cas,ras,we)

4.addr(a0-a11),文档中显示A0-A9,A11,A12不关心。

根据文档编写代码:

输出:

ref_req:只有在每个15us拉高(每隔15us刷新一次)

flag_ref_end:刷新结束,当命令寄存器发送aref命令结束后拉高

cmd_reg:发送命令(precharge—cmd_cnt计数1和auto refcmd_cnt计数2)

ref_addr:A0-A11

内部变量:

falg_ref:在刷新阶段为高电平

ref_cnt_15us:计数15us,初始化结束后自动开始计数

cmd_cnt:首先是precharge,一个周期后aref,在刷新阶段内部开始计数(flag_ref为高)

module sdram_aref(
		input			sclk,
		input			srst,
		//commmunicate with arbit
		input			ref_en,
		output wire 		ref_req,
		output wire		flag_ref_end,
		//others
		input						flag_init_end,
		output	reg		[3:0]		cmd_reg,
		output	wire	[11:0]		ref_addr
);

//==========================================================
//=======	define parameter and internal signal	========
//==========================================================

localparam			delay_15us = 749;
localparam 			cmd_aref	=	4'b0001;
localparam			cmd_nop		=	4'b0111;
localparam			cmd_pre		=	4'b0010;

reg					flag_ref;
reg 	[9:0]		ref_cnt_15us;
reg		[3:0]		cmd_cnt;	


//==========================================================
//====================	main	code	====================
//==========================================================

always@(posedge sclk or negedge srst)begin
		if(srst  ==  1'b0)
			ref_cnt_15us <= 'd0;
		else if(ref_cnt_15us  >=  delay_15us)
			ref_cnt_15us	<=	'd0;
		else if(flag_init_end  ==	'b1)
			ref_cnt_15us <= ref_cnt_15us +1'b1;
end

always@(posedge sclk or negedge srst)begin
		if(srst == 1'b0)
			flag_ref <= 1'b0;
		else if(flag_ref_end == 1'b1)    
			flag_ref <= 1'b0;
		else if(ref_en == 1'b1)
			flag_ref <= 1'b1;
end

always@(posedge sclk or negedge srst)begin
		if(srst == 1'b0)
			cmd_cnt <= 'd0;
		else if(flag_ref == 1'b1)
			cmd_cnt <= cmd_cnt +1'b1;
		else
			cmd_cnt <= 'd0;
end

always@(posedge sclk or negedge srst) begin
		if(srst == 1'b0)
			cmd_reg <= cmd_nop;
		else case(cmd_cnt)
			1:	cmd_reg <= cmd_pre;
			2:	cmd_reg <= cmd_aref;
			default:
				cmd_reg <= cmd_nop;
			endcase	
end

assign	flag_ref_end = (cmd_cnt == 'd3)? 1'b1:1'b0;
assign	ref_addr = 12'b0100_0000_0000;
assign 		ref_req = (ref_cnt_15us >= delay_15us)?1'b1:1'b0;

endmodule

顶层模块:

module	sdram_top(
		input			sclk,
		input			srst,
		//sdram		interface
		output	wire	sdram_clk,
		output	wire	sdram_cke,
		output	wire	sdram_cs_n,
		output	wire	sdram_cas_n,
		output	wire	sdram_ras_n,
		output	wire	sdram_we_n,
		output	wire	[1:0]	sdram_bank,
		output	wire	[11:0]	sdram_addr,
		output	wire	[1:0]	sdram_dqm,
		inout			[15:0]	sdram_dq
);

//==========================================================
//=======	define parameter and internal signal	========
//==========================================================

//define state machine
reg		[4:0]	state;
localparam		idle		=		5'b00001;
localparam		arbit		= 		5'b00010;
localparam		aref		= 		5'b00100;

//init module
wire 			flag_init_end;
wire	[3:0]	init_cmd;
wire	[11:0]	init_addr;

//refresh module
reg				ref_en;
wire			ref_req;
wire			flag_ref_end;
wire 	[3:0]	cmd_reg;
wire	[11:0]	ref_addr;

//==========================================================
//====================	main	code	====================
//==========================================================
always@(posedge sclk or negedge srst) begin
	if(srst 	==		1'b0)
		state	<=		idle;
	else
	case(state)
		idle:
				if(flag_init_end	==	1'b1)
					state	<=	arbit;
				else
					state	<=	idle;
		arbit:
				if(ref_en	==		1'b1)
					state	<=	aref;
				else
					state	<=	arbit;
		aref:
				if(flag_ref_end	==	1'b1)
					state	<=	idle;
				else
					state	<=	aref;
		default:	
					state	<=	idle;
	endcase
end


//ref_en
always@(posedge sclk or  negedge srst)begin
		if(srst == 1'b0)
			ref_en <= 1'b0;
		else if(state == arbit	&& ref_req == 1'b1)
			ref_en <= 1'b1;
		else	
			ref_en <= 1'b0;
end



assign	sdram_cke	=	1'b1;
assign	sdram_addr	=	(state == idle) ?init_addr:ref_addr;
assign	{sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n} = (state == idle) ?init_cmd:cmd_reg;
assign 	sdram_dqm	=	2'b00;
assign	sdram_clk	=	~sclk;	//内部时钟上升沿采集命令,命令又是由系统时钟上升沿产生的??(为了保证采样时刻处在数据中间时刻)


sdram_init	sdram_init_inst(
	.sclk				(sclk)	,
	.srst				(srst)	,
	.cmd_reg			(init_cmd)	,	
	.sdram_addr			(init_addr)	,	
	.flag_init_end	    		(flag_init_end)
);	


sdram_aref		sdram_aref(
		.sclk						(sclk),
		.srst						(srst),
		//commmunicate with arbit
		.ref_en							(ref_en),
		.ref_req						(ref_req),
		.flag_ref_end					(flag_ref_end),
		//others                       
		.flag_init_end					(flag_init_end),
		.cmd_reg						(cmd_reg),
		.ref_addr						(ref_addr)
);


endmodule

测试代码:

`timescale	1ns/1ns

module	tb_sdram_top;

	reg			sclk;
	reg			srst;
//----------------------------------------
	wire	sdram_clk;
	wire	sdram_cke;
	wire	sdram_cs_n;
	wire	sdram_cas_n;
	wire	sdram_ras_n;
	wire	sdram_we_n;
	wire	[1:0]	sdram_bank;
	wire	[11:0]	sdram_addr;
	wire	[1:0]	sdram_dqm;
    wire	[15:0]	sdram_dq;
//----------------------------------------

initial begin
			sclk = 1;
			srst <= 0;
			#100
			srst <=1;
end

always	#10		sclk = ~sclk;

defparam sdram_model_plus_inst.addr_bits =    12;
defparam sdram_model_plus_inst.data_bits =    16;
defparam sdram_model_plus_inst.col_bits  =    9;
defparam sdram_model_plus_inst.mem_sizes =    2*1024*1024;//1 M 


sdram_top		sdram_top_inst(
			.sclk							(sclk		),
			.srst							(srst		),
			.sdram_clk						(sdram_clk	),
			.sdram_cke						(sdram_cke	),
			.sdram_cs_n						(sdram_cs_n	),
			.sdram_cas_n						(sdram_cas_n),
			.sdram_ras_n						(sdram_ras_n),
			.sdram_we_n						(sdram_we_n	),
			.sdram_bank						(sdram_bank	),
			.sdram_addr						(sdram_addr	),
			.sdram_dqm						(sdram_dqm	),
			.sdram_dq						(sdram_dq	)
);


sdram_model_plus sdram_model_plus_inst(
 .Dq				(sdram_dq)	,
 .Addr				(sdram_addr), 
 .Ba				(sdram_bank), 
 .Clk				(sdram_clk), 
 .Cke				(sdram_cke), 
 .Cs_n				(sdram_cs_n), 
 .Ras_n				(sdram_ras_n), 
 .Cas_n				(sdram_cas_n), 
 .We_n				(sdram_we_n), 
 .Dqm				(sdram_dqm),
 .Debug				(1'b1)
 );
 
 
 
endmodule

文章来源:https://blog.csdn.net/weixin_49574391/article/details/135462315
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。