论坛风格切换切换到宽版
发帖 回复
返回列表  提醒:不能用迅雷等P2P下载,否则下载失败标(二级)的板块,需二级才能下载,没二级不要购买,下载不了
  • 1120阅读
  • 6回复

[技术讨论]基于FPGA的SDRAM控制器设计—自动刷新设计 [复制链接]

上一主题 下一主题
 

性别:
人妖
发帖
44
金币
171
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看楼主 倒序阅读 使用道具 0楼 发表于: 2020-05-04
SDRAM控制器设计的主要功能是能对SDRAM进行读写操作,本工程实现了SDRAM的初始化和自动刷新两个功能。
*G* k6.9W!  
初始化功能在前一章的分享中已经进行了比较详细的描述,感兴趣的同学可以搜索学习下,文后历史文章里有链接。今天我们主要讨论SDRAM的自动刷新的功能以及实现。
<HbcNE~  
一、原理功能1、为什么刷新
我们都知道SDRAM是使用电容保存信息的,随着使用时间的增长,电容的电量会有损失,因此在操作SDRAM时要进行刷新。SDRAM的刷新分为两种,分别是Auto Refresh和Self Refresh。本次实验采用的是Auto Refresh。
BNL;Biy t7  
2、刷新间隔
查询器件手册得到(64ms, 8192-cycle (commercial and industrial)),对8192行全部进行一次刷新时间是64ms。一次刷新操作是对4个bank的同一行进行刷新,所以一次刷新间隔是64ms/8192=7.813us。但是当刷新时间到来时,SDRAM可能正在进行读写,那么需要本次读突发或者写突发完成之后才能进行刷新操作;那么一次读突发为7拍,写突发为6拍,时间是60ns或者70ns (SDRAM工作时钟是100MHz,1拍是10ns),同时考虑到读写命令都是仲裁模块发出,会有一定的延时,所以本次实验刷新间隔设为7.5us,留出足够的时间。
v`M3eh@$A  
3、刷新时序
刷新时序如上图所示。这里需要注意,此时序图发了两次Auto Refresh命令,这种被称为背靠背技术;但其实背靠背技术并不是必须的,可以只发一次命令。
dqN5]Sb2B  
二、FPGA实现
1、模块架构
Djg,Lvhm  
2、信号说明
293M\5:  
信号
说明
clk
刷新模块工作时钟(100MHz)
rst_n
复位信号
ref_en
刷新使能信号,由仲裁模块发出
ref_done
刷新完成信号
ref_bus
刷新数据总线,由SDRAM信号组成
rt_flag
计数到最大值信号
rt_clear
rt_flag清除信号
rt_en
计数器使能信号
init_done
初始化完成信号
sel_sm
选择SDRAM输出信号
ref_en
刷新使能信号
sdr_bus
顶层模块数据总线
sdr_clk
SDRAM工作时钟
sdr_cke
时钟使能
sdr_cs_n
片选信号
sdr_cas_n
行选通
sdr_ras_n
列选通
sdr_we_n
写使能
sdr_ba
bank地址
sdr_a
SDRAM地址总线
^]TVo\,N  
6i1LjLB  
3、顶层模块参考代码 r-:Uz\gM  
vM5k_D  
module sdram_top(
clk    ,
sys_rst_n  ,
//其它信号,举例dout
local_addr,
local_data,
local_q,
local_rdreq,
local_wrreq,
local_reday,
local_rdata_vaild,
init_done,
sdr_cke,
sdr_cs_n,
sdr_ras_n,
sdr_cas_n,
sdr_we_n,
sdr_ba,
sdr_a,
sdr_dq,
sdr_dqm,
sdr_clk
);
B)0i:"q  
input clk;
input sys_rst_n;
input [24:0] local_addr;
input [63:0] local_data;
output [63:0] local_q;
input local_rdreq;
input local_wrreq;
output local_reday;
output local_rdata_vaild;
output init_done;
output sdr_cke;
output sdr_cs_n;
output sdr_ras_n;
output sdr_cas_n;
output sdr_we_n;
output [1:0] sdr_ba;
output [12:0] sdr_a;
output [15:0] sdr_dq;
output [1:0] sdr_dqm;
output sdr_clk;
nDHTV !]<  
wire phy_clk;
wire rst_n;
wire rt_flag;
wire rt_clear;
wire rt_en;
wire ref_en;
wire ref_done;
wire sel_sm;
wire [19:0] sdr_bus;
wire [19:0] init_bus;
wire [19:0] ref_bus;
j KoG7HH  
assign {sdr_cke, sdr_cs_n, sdr_ras_n, sdr_cas_n, sdr_we_n, sdr_ba, sdr_a} = sdr_bus;
assign sdr_dqm = 2'b00;
6oGYnu;UZ  
sdram_init sdram_init_inst(
.clk            (phy_clk)       ,
.rst_n          (rst_n)       ,
//其它信号,举例dout
.init_done      (init_done)       ,
.init_bus       (init_bus)
);
<yd{tD$A*  
arbitrate arbitrate_inst(
.clk(phy_clk),
.rst_n(rst_n),
.rt_en(rt_en),
.rt_flag(rt_flag),
.init_done(init_done),
.ref_done(ref_done),
.ref_en(ref_en),
.sel_sm(sel_sm),
.rt_clear(rt_clear)
);
V,%=AR5  
ref_timer ref_timer_inst(
.clk(phy_clk),
.rst_n(rst_n),
.rt_en(rt_en),
.rt_clear(rt_clear),
.rt_flag(rt_flag)
);
K*~0"F>"0  
sdram_ref sdram_ref_inst(
.clk(phy_clk),
.rst_n(rst_n),
.ref_en(ref_en),
.ref_done(ref_done),
.ref_bus(ref_bus)
);
ZzSz%z_sE  
sdram_mux sdram_mux_inst(
.clk(phy_clk),
.rst_n(rst_n),
.init_bus(init_bus),
.ref_bus(ref_bus),
.sdr_bus(sdr_bus),
.sel_sm(sel_sm)
);
ljb7oA3cP4  
my_pll PLL(
.areset        (~sys_rst_n)        ,
.inclk0        (clk)        ,
.c0        (phy_clk)        ,
.c1        (sdr_clk)        ,
.locked        (rst_n)
);
Ymg|4 %O@  
endmodule
<ZNzVnVA  
1,% R;7J=g  
4、模块功能 +mn ,F};  
N<XNTf  
(1)PLL模块
my_pll模块产生SDRAM和控制器工作时钟。
输入的50M时钟,经过PLL模块后,会产生两个100M、相位相差180度的时钟。其中一个用于输出给外部SDRAM,另一个用于其它模块的工作时钟。关于此模块的原理,可以参考《基于FPGA的SDRAM控制器设计—初始化设计》中的“SDRAM中心对齐原则”部分进行学习。
另外,本模块锁定输入时钟后,将产生LOCK指示信号,此信号用于其它模块的复位信号。我们可以理解为,在时钟稳定之前,其它模块都处于复位状态。
iv4H#rJ  
(2)仲裁模块 L U={")TdQ  
arbitrate即仲裁模块,因为SDRAM控制时可能进行刷新或者读写操作(后续介绍),但是刷新时不能进行读写操作,因此需要一个仲裁模块,对这些控制命令进行管理,使刷新命令优先级最高。
    Ru>MFG  
    FY#C.mL  
当初始化完成之后仲裁模块发出rt_en信号,当仲裁模块收刷新定时器计时到最大值时的标志信号rt_flag后,发出刷新使能信号ref_en,并发出rt_clear信号。
R=QZgpR  
其代码如下所示:
'h,VR=e<  
module arbitrate(clk, rst_n, rt_en, rt_flag, init_done, ref_done, ref_en, sel_sm, rt_clear);
EwvoQ$#jv  
input clk;
input rst_n;
input rt_flag;
input init_done;
input ref_done;
output reg rt_en;
output reg ref_en;
output reg sel_sm;
output reg rt_clear;
xCc[#0R{  
localparam SM_INIT = 1'b0;
localparam SM_REF  = 1'b1;
. QBF`Rz  
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rt_en <= 1'b0;
end
else if(init_done)begin
rt_en <= 1'b1;
end
else begin
rt_en <= rt_en;
end
end
5fd]v<  
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
ref_en <= 1'b0;
end
else if(rt_flag)begin
ref_en <= 1'b1;
end
else if(ref_done)begin
ref_en <= 1'b0;
end
else begin
ref_en <= ref_en;
end
end
Jcrw#l8|C  
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sel_sm <= SM_INIT;
end
else if(init_done)begin
sel_sm <= SM_REF;
end
else begin
sel_sm <= sel_sm;
end
end
gcl5jB5)>  
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rt_clear <= 1'b0;
end
else if(rt_flag)begin
rt_clear <= 1'b1;
end
else begin
rt_clear <= 1'b0;
end
end
1pgU}sRk  
endmodule
<nT +$  
}khV'6"'|  
(3)刷新定时器模块
{#@W)4)cA  
ref_timer即刷新定时器模块,主要是计数刷新间隔时间,当计数到最大值时拉高rt_flag信号。当收到rt_clear信号时将rt_flag信号拉低。
oYm[V<nIl  
代码如下所示:
    #Up86(Z  
    V<T9&8l+:  
hYG6 pTCb  
module ref_timer(clk, rst_n, rt_en, rt_clear, rt_flag);
`T5W}p[6  
input clk;
input rst_n;
input rt_en;
input rt_clear;
output reg rt_flag;
Ezd_`_@R  
parameter CNT_MAX = 750;
woGAf)vV#  
reg [9:0] cnt;
@~"h62=] -  
wire add_cnt;
wire end_cnt;
).`1+b  
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
end
qKr8)}h  
assign add_cnt = rt_en;
assign end_cnt = add_cnt && cnt==CNT_MAX - 1 ;
rrik,qyv6  
always @(posedge clk or negedge rst_n)begin
if (!rst_n)
rt_flag <= 0;
else if (add_cnt && cnt == CNT_MAX - 1)
rt_flag <= 1;
else if (rt_clear)
rt_flag <= 0;
else
rt_flag <= rt_flag;
end
pL/DZ|S3  
endmodule
#_^Lb]jkM  
 Ac2n  
(4)初始化模块sdr_init初始化模块,在《基于FPGA的SDRAM控制器设计—初始化设计》中我们有比较详细的介绍,可以认真学习一下。
    l 3ko?k  
    (ROY?5 @c  
(5)刷新模块sdr_ref刷新模块,收到刷新使能信号后进行刷新操作,在前文中“刷新时序”一节有讲述原因。本代码通过一个计数器cnt对时序进行计数,并产生了两个刷新命令;刷新完成后,让ref_done信号置1个时钟的高电平,表示刷新完成。 C26>BU<  
代码如下: svcK?^ HTe  
L.*M&Ry  
module sdram_ref(clk, rst_n, ref_en, ref_done, ref_bus);
R6;=n"Ueb  
input clk;
input rst_n;
input ref_en;
output reg ref_done;
output [19:0] ref_bus;
gd`!tRcNY  
parameter CNT_MAX = 9;
// parameter TRP = 2;
// parameter TRFC = 7;
parameter NOP = 4'b0111;
parameter PRE = 4'b0010;
parameter REF = 4'b0001;
ux vqMgR  
reg [3:0] cnt;
reg [3:0] sdr_cmd;
reg [1:0] sdr_ba;
reg [12:0] sdr_a;
uKUiV%p!  
wire add_cnt;
wire end_cnt;
vqDu(6!2  
assign sdr_cke = 1'b1;
assign ref_bus = {sdr_cke, sdr_cmd, sdr_ba, sdr_a};
A$Hfr8w1u  
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
end
}v}P .P  
assign add_cnt = ref_en;
assign end_cnt = add_cnt && cnt==CNT_MAX - 1 ;
hKL4cpK4  
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sdr_cmd <= NOP;
end
else if(ref_en && add_cnt && cnt == 0)begin
sdr_cmd <= PRE;
end
else if(add_cnt && cnt == 2 - 1)begin
sdr_cmd <= REF;
end
else begin
sdr_cmd <= NOP;
end
end
{?}E^5Z*g  
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sdr_a <= 13'd0;
end
else if(ref_en && add_cnt && cnt == 0)begin
sdr_a[10] <= 1'b1;
end
else begin
sdr_a <= 13'd0;
end
end
r!_-"~`7E  
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
ref_done <= 1'b0;
end
else if(add_cnt && cnt == CNT_MAX - 1)begin
ref_done <= 1'b1;
end
else begin
ref_done <= 1'b0;
end
end
x[ ~b2o  
endmodule
S9]'?|  
E7j(QO f  
6、选择模块
[9evz}X  
sdr_mux模块,由于初始化模块和刷新模块都会发出SDRAM的信号,所以需要一个多路器来进行选择。由仲裁模块的sel_sm来控制输出init_bus信号还是ref_bus;当初始化没完成时输出init_bus,初始化完成时输出ref_bus。
@E7DyU|  
代码如下所示:
EE&K0<?T|:  
module sdram_mux(clk, rst_n, init_bus, ref_bus, sdr_bus, sel_sm);
n' n/Tu   
input clk;
input rst_n;
input [19:0] init_bus;
input [19:0] ref_bus;
output reg [19:0] sdr_bus;
input sel_sm;
%*A0# F  
localparam SM_INIT = 1'b0;
localparam SM_REF  = 1'b1;
A5c%SCq;  
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sdr_bus <= init_bus;
end
else if(sel_sm == SM_INIT)begin
sdr_bus <= init_bus;
end
else if(sel_sm == SM_REF)begin
sdr_bus <= ref_bus;
end
else begin
sdr_bus <= sdr_bus;
end
end
ype$ c  
endmodule
LDgrR[  
三、仿真测试
X( \ AB  
最后对代码进行仿真,仿真文件参考:sdram_top_tb.v。
modelsim生成的报告如下所示,出现如下LOG信息,说明成功。
LM~[@_j  
qeVfE_<  
以上就是SDRAM控制器的完整设计,明德扬专注FPGA设计研究,更多FPGA资料可以进入论坛进行学习交流。


评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

一般

差劲
离线bidezhi7777

性别:
帅哥
发帖
13314
金币
240
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 1楼 发表于: 2020-05-04
        


离线ldd1840

性别:
人妖
发帖
303
金币
41
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 2楼 发表于: 2020-05-04
收藏收藏


离线william_d_87

性别:
人妖
发帖
1058
金币
734
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 3楼 发表于: 2020-05-04


离线地沟油

性别:
人妖
发帖
7241
金币
4361
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 4楼 发表于: 2020-05-04
        


离线nj20044

性别:
帅哥
发帖
6781
金币
7542
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 5楼 发表于: 2020-05-12



性别:
人妖
发帖
365
金币
0
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 6楼 发表于: 2020-05-13
            


快速回复
限150 字节
 
上一个 下一个