SDRAM--Verilog及仿真(1)

(1)初始化

器件原理:

SDRAM(Synchronous Dynamic Random Access Memory)同步动态随机存储器。

SDRAM的存储方式可以看成是几张表格,其中每张表格如图所示,向SDRAM写入数据就是存放在当中的格子,通过行地址和列地址可以准备找到存储单元。

SDRAM的总存储容量是:表格的张数 x 行地址数 x 列地址数 x 每个格子的容量。其中这里所使用的sdram型号的总存储容量是:4张 x 2M x 16bits

 所使用的sdram器件型号的结构:

引脚介绍:

sdram_clk

SDRAM 芯片时钟

上升沿

sdram_cke

SDRAM 时钟有效

高电平有效

sdram_cs_n

SDRAM 片选

低电平有效

sdram_ras_n

SDRAM 行有效

低电平有效

sdram_cas_n

SDRAM 列有效

低电平有效

sdram_we_n

SDRAM 写有效

低电平有效

[1:0]sdram_ba

SDRAM Bank地址

四张不同的表格:00、01、10、11

[11:0]sdram_addr

SDRAM 地址总线

 

[15:0]sdram_data

SDRAM 数据

双向inout

[1:0]sdram_dqm

SDRAM 数据掩码

 

bank+地址总线:

从这个时序图可以知道,初始化用到的命令有NOP、PRE、REF、MSET。

①输入稳定期200μs

②所用L-Bank预充电

③8个刷新周期

④模式寄存器设置(MRS:Mode Register Set)

 其中A9、A6、A5、A4、A3、A2、A1、A0是根据这里的SDRAM设置的。

操作模式A9:选择突发读/突发写方式,因此0。

潜伏期A6、A5、A4:潜伏期是3,因此011。

突发长度A3、A2、A1、A0:选择顺序突发方式,并且突发长度是4,因此0010。

综上所述,地址总线已经确定是00000_011_0010。

综合代码设计:

sdram_init.v模块:

module sdram_init(
input sys_clk,
input sys_rst_n,

output reg [3:0]cmd,
output [11:0]sdram_addr,
output init_end_flag
);

localparam NOP=4'b0111;
localparam PRE=4'b0010;
localparam REF=4'b0001;
localparam MSET=4'b0000;

reg [13:0]cnt_200us;
reg [3:0]cmd_cnt;

always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
cnt_200us<=14'd0;
else if(cnt_200us < 14'd10000)
cnt_200us<=cnt_200us+1'b1;
end

always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
cmd_cnt<=4'd0;
else if(cnt_200us == 14'd10000 && init_end_flag == 1'b0)
cmd_cnt<=cmd_cnt+1'b1;
end

always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
cmd<=NOP;
else if(cnt_200us == 14'd10000)
case(cmd_cnt)
0:cmd<=PRE;
1:cmd<=REF;
5:cmd<=REF;
9:cmd<=MSET;
default:cmd<=NOP;
endcase
end

assign init_end_flag=(cmd_cnt>=4'd10)?1'b1:1'b0;
assign sdram_addr=(cmd == MSET)?12'b00000_011_0010:12'b0100_0000_0000;
endmodule 

top.v模块:

module top(
input sys_clk,
input sys_rst_n,

output sdram_clk,
output sdram_cke,
output sdram_cs_n,
output sdram_ras_n,
output sdram_cas_n,
output sdram_we_n,
output [1:0]sdram_ba,
output [11:0]sdram_addr,
output [1:0]sdram_dqm,
output [15:0]sdram_data
);
wire [11:0]init_addr;
wire init_end_flag;
wire [3:0]init_cmd;

assign {sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n}=init_cmd;
assign sdram_clk=~sys_clk;
assign sdram_cke=1'b1;
assign sdram_ba=2'b00;
assign sdram_addr=init_addr;
assign sdram_dqm=2'b00;

sdram_init u_sdram_init(
.sys_clk        (sys_clk),
.sys_rst_n      (sys_rst_n),
.cmd            (init_cmd),
.sdram_addr     (init_addr),
.init_end_flag  (init_end_flag)
);
endmodule 

仿真代码设计:

由于SDRAM器件复杂,所以借用了别人已经设计好的SDRAM模型sdram_model_plus.v,并且改动其中内容如下:

激励文件sdram_init_tb.v:

`timescale 1ns/1ns
module sdram_init_tb;
reg sys_clk;
reg sys_rst_n;
wire sdram_clk;
wire sdram_cke;
wire sdram_cs_n;
wire sdram_ras_n;
wire sdram_cas_n;
wire sdram_we_n;
wire [1:0]sdram_ba;
wire [11:0]sdram_addr;
wire [1:0]sdram_dqm;
wire [15:0]sdram_data;

top u_top(
.sys_clk     (sys_clk),
.sys_rst_n   (sys_rst_n),
.sdram_clk   (sdram_clk),
.sdram_cke   (sdram_cke),
.sdram_cs_n  (sdram_cs_n),
.sdram_ras_n (sdram_ras_n),
.sdram_cas_n (sdram_cas_n),
.sdram_we_n  (sdram_we_n),
.sdram_ba    (sdram_ba),
.sdram_addr  (sdram_addr),
.sdram_dqm   (sdram_dqm),
.sdram_data  (sdram_data)
);

sdram_model_plus u_model_plus(
.Dq      (sdram_data),
.Addr    (sdram_addr),
.Ba      (sdram_ba),
.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)
);

initial begin
sys_clk=1;
sys_rst_n=0;
#30 sys_rst_n=1;
end
always #10 sys_clk=~sys_clk;

endmodule 

结果:Modelsim打印信息,表明sdram初始化的设计实现了。

run 201us,之后Modelsim的打印信息:

# at time 200050 ns PRE : Bank = ALL
# at time 200070 ns AREF : Auto Refresh
# at time 200150 ns AREF : Auto Refresh
# at time 200230 ns LMR : Load Mode Register
# CAS Latency = 3
# Burst Length = 4
# Burst Type = Sequential
# Write Burst Mode = Programmed Burst Length

观看波形:因为命令只有在sdram_init.v模块中,因此点击这个观看波形:

tb文件中30ns之后,复位信号才拉高,因此等下一个上升沿就是200us+40ns了,此时稳定期200us过去,命令4'b0111跳转到命令4'b0010。

assign sdram_addr=(cmd == MSET)?12'b00000_011_0010:12'b0100_0000_0000;

命令和地址都符合设计。

原文地址:https://www.cnblogs.com/FPGAer/p/13997916.html