时间:2024-07-28 来源:网络搜集 关于我们 0
小周 明德扬FPGA科教
本文为明德扬原创及录用文章,转载请注明出处!
1.1 SDRAM简介SDRAM即同步动态随机存储器,英文为Synchronous Dynamic Random Access Memory;具有容量大、读写速度快、价格相对便宜等优点,但同时控制逻辑比较复杂。
1.1.1 SDRAM示意图其管脚图如下所示:
SDRAM的命令与时钟上升沿是中心对齐的,本设计采用锁相环生成SDRAM工作时钟,SDRAM与初始化模块工作时钟相差180°。这样FPGA产生的信号到SDRAM正好中心对齐,如下图所示:
SDRAM初始化时序如上图所示,sdr_cmd命令由sdr_cs_n, sdr_ras_n, sdr_cas_n, sdr_we_n组合而成;复位后要延时最少100us后才能工作;当A10为高时可以对所有bank进行操作;当到达Tp+3时需要将init_done拉高。
其模式寄存器配置如上图所示,主要参数设置如下:
a. 模式寄存器的配置是确定SDRAM的工作模式
b. A2、A1、A0用作设置突发长度,本项目设置为4
c. A3用作设置突发类型,本项目设置为Sequential顺序类型
d. A6、A5、A4用作设置列选通潜伏期,本项目设置为3
e. A8、A7设置操作模式,一般为00
f. A9设置写突发模式,本项目为0
g. A12、A11、A10设置为0
1.2 顶层模块设计1.2.1 SDRAM顶层模块管脚图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
);
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;
wire phy_clk;
wire rst_n;
wire [19:0] init_bus;
assign {sdr_cke, sdr_cs_n, sdr_ras_n, sdr_cas_n, sdr_we_n, sdr_ba, sdr_a} = init_bus;
assign sdr_dqm = 2b00;
sdram_init sdram_init_inst(
.clk (phy_clk) ,
.rst_n (rst_n) ,
//其他信号,举例dout
.init_done (init_done) ,
.init_bus (init_bus)
);
my_pll PLL(
.areset (~sys_rst_n) ,
.inclk0 (clk) ,
.c0 (phy_clk) ,
.c1 (sdr_clk) ,
.locked (rst_n)
);
endmodule
1.3 初始化模块设计1.3.1 SDRAM出计划模块管脚图module sdram_init(
clk ,
rst_n ,
//其他信号,举例dout
init_done,
init_bus
);
//参数定义
parameter DATA_W = 20 ;
parameter T100us = 10_000 ;
parameter TRP = 2 ;
parameter TRFC = 7 ;
parameter TMRD = 2 ;
parameter NOP = 4b0111 ;
parameter PRE = 4b0010 ;
parameter REF = 4b0001 ;
parameter LMR = 4b0000 ;
parameter CODE = 13b000_000_011_0010 ;
parameter CNT_MAX = 10_021 ;
//输入信号定义
input clk ;
input rst_n ;
//输出信号定义
output init_done ;
output[DATA_W-1:0] init_bus ;
//输出信号reg定义
reg init_done ;
wire [DATA_W-1:0] init_bus ;
//中间信号定义
reg [20:0] cnt ;
reg sdr_cke ;
reg [3:0] sdr_cmd ;
reg [1:0] sdr_ba ;
reg [12:0] sdr_a ;
wire add_cnt ;
wire end_cnt ;
assign init_bus = {sdr_cke, sdr_cmd, sdr_ba, sdr_a};
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
assign add_cnt = init_done == 0;
assign end_cnt = add_cnt && cnt==CNT_MAX - 1 ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1b0)begin
sdr_cke <= 1b0;
end
else if(add_cnt&&cnt==10_000-1)begin
sdr_cke <= 1b1;
end
else
sdr_cke <= sdr_cke;
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1b0)begin
sdr_cmd <= NOP;
end
else if(add_cnt&&cnt==10_001-1)begin
sdr_cmd <= PRE;
end
else if(add_cnt&&cnt==10_003-1)begin
sdr_cmd <= REF;
end
else if(add_cnt&&cnt==10_012-1)begin
sdr_cmd <= REF;
end
else if(add_cnt&&cnt==10_019-1)begin
sdr_cmd <= LMR;
end
else if(add_cnt&&cnt==10_020-1)begin
sdr_cmd <= NOP;
end
else begin
sdr_cmd <= NOP;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1b0)begin
sdr_a <= 13d0;
end
else if(add_cnt&&cnt==10_001-1)begin
sdr_a[10] <= 1b1;
end
else if(add_cnt&&cnt==10_019-1)begin
sdr_a <= CODE;
end
else begin
sdr_a <= 13d0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1b0)begin
init_done <= 1b0;
end
else if(add_cnt&&cnt==10_021-1)begin
init_done <= 1b1;
end
else begin
init_done <= init_done;
end
end
endmodule
1.4 PLL设置最后对代码进行仿真,modelsim生成的报告如下所示,说明初始化设置成功。
以上就是SDRAM控制器初始化设计的思考步骤以及相关代码,更多FPGA资料可以进入明德扬论坛进行学习交流。