(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;
命令和地址都符合设计。