大家好,又见面了,我是你们的朋友全栈君。
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
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/129213.html原文链接:https://javaforall.cn