标签:
目录
1、SDRAM初始化的内容(结合英文数据手册)
2、SDRAM初始化的时序
3、代码的编写
4、modesim的仿真
SDRAMs must be powered up and initialized in a predefined manner. The 64M SDRAM is initialized after the power is applied to Vdd and Vddq, and the clock is stable with DQM High and CKE High. A 100μs delay is required prior to issuing any command other than a COMMAND INHIBIT or a NOP.
The COMMAND INHIBIT or NOP may be applied during the 100μs period and continue should at least through the end of the period.With at least one COMMAND INHIBIT or NOP command having been applied, a PRECHARGE command should be applied once the 100μs delay has been satisfied. All banks must be precharged. This will leave all banks in an idle state, after which at least two AUTO REFRESH cycles must be performed. After the AUTO REFRESH cycles are complete, the SDRAM is then ready for mode register programming.The mode register should be loaded prior to applying any operational command because it will power up in an unknown state. After the Load Mode Register command, at least two NOP commands must be asserted prior to any command.
这个时序图可以结合状态机的图理解,非常重要,因为每个状态需要的时间都不一样,所以需要设计计数器。
1、CKE 一直为高电平
2、command 由 cs,ras,cas,we 四个控制信号实现,具体如下图
例如 NOP命令 cs=0,ras=1,cas=1,we=1
3、DQM在初始化的时候始终为1
4、A10为高,则忽略BA0,BA1,对所有bank 进行预刷新。
5、在配置模式寄存器时,根据自己的需求设置参数
例如当 mode_value=000_00_011_0_111 即全页模式,顺序,CL=3,突发读,突发写。
代码的编写
初始化代码
/*1、工作时钟定为100Mhz 2、 Sdram 初始化 3、Sdram 的自动刷新功能:每隔 64ms/2^12=15625 个时钟周期,给出刷新命令。*/ //------------------------------------------------------------------------------------ module Sdram_initial( clk , rst_n , cke , cs , ras , cas , we , dqm , addr , bank , dq ); input clk ; //100Mhz input rst_n ; output cke ; //clk enable output cs ; //片选信号 output ras ; //行 output cas ; //列 output we ; //读写控制端 output [11:0] dqm ; //byte controlled by LDQM and UDQM output [11:0] addr ; //12个位地址 output [ 1:0] bank ; //sdram有4个逻辑bank inout [15:0] dq ; //是三态门 wire cs ; wire ras ; wire cas ; wire we ; wire [15:0] dq ; reg [11:0] dqm ; reg [11:0] addr ; reg [ 1:0] bank ; reg [3:0] command ; reg [2:0] c_state ; reg [2:0] n_state ; reg [13:0] cnt_0 ; wire get_100us ; wire get_trp ; wire get_trc1 ; wire get_trc2 ; wire get_tmrd ; wire get_1562 ; wire get_trc3 ; //---------------------------------------------------------------------- parameter NOP = 3‘b000; parameter PRECHARG = 3‘b001; parameter AUTO_REF1 = 3‘b010; parameter AUTO_REF2 = 3‘b011; parameter MODE_REG = 3‘b100; parameter IDLE = 3‘b101; parameter AUTO_REF = 3‘b110; parameter TIME_100US = 10_000 ; parameter TRP = 3 ; //这些数据由数据手册可以获得 parameter TRC = 7 ; parameter TMRD = 2 ; parameter TIME_1562 = 1562 ; parameter MODE_VALUE = 12‘b000_00_011_0_111; //即全页模式,顺序,CL=3,突发读,突发写。 parameter NOP_CD = 4‘b0111; parameter PRECHARGE_CD = 4‘b0010; parameter AUTO_REF_CD = 4‘b0001; parameter MODE_REG_CD = 4‘b0000; //----------------------------------------------------------------------状态机的设计 always @(posedge clk or negedge rst_n)begin if(rst_n==1‘b0)begin c_state<=NOP; end else begin c_state<=n_state; end end always @(*)begin case(c_state) NOP :begin if(get_100us) //等待100us后跳转 n_state = PRECHARG; else n_state = c_state; end PRECHARG :begin if(get_trp) //trp时间后 n_state = AUTO_REF1; else n_state = c_state; end AUTO_REF1 :begin if(get_trc1) //trc n_state = AUTO_REF2; else n_state = c_state; end AUTO_REF2 :begin if(get_trc2) //trc n_state = MODE_REG; else n_state = c_state; end MODE_REG :begin if(get_tmrd) //tmrd n_state = IDLE; else n_state = c_state; end IDLE :begin if(get_1562) //等待1562个始终周期 n_state = AUTO_REF; else n_state = c_state; end AUTO_REF :begin if(get_trc3) //trc n_state = IDLE; else n_state = c_state; end default : n_state = NOP; //其他状态转移到NOP endcase end assign get_100us = (c_state == NOP && cnt_0 == 0)? 1‘b1 : 1‘b0; //cnt_0是一个递减计数器 assign get_trp = (c_state == PRECHARG && cnt_0 == 0)? 1‘b1 : 1‘b0; assign get_trc1 = (c_state == AUTO_REF1&& cnt_0 == 0)? 1‘b1 : 1‘b0 ; assign get_trc2 = (c_state == AUTO_REF2&& cnt_0 == 0)? 1‘b1 : 1‘b0 ; assign get_tmrd = (c_state == MODE_REG && cnt_0 == 0)? 1‘b1 : 1‘b0 ; assign get_1562 = (c_state == IDLE && cnt_0 == 0)? 1‘b1 : 1‘b0 ; assign get_trc3 = (c_state == AUTO_REF && cnt_0 == 0)? 1‘b1 : 1‘b0 ; always @(posedge clk or negedge rst_n)begin if(rst_n==1‘b0)begin cnt_0 <= TIME_100US-1; end else if(get_100us) begin cnt_0 <= TRP-1; end else if(get_trc1 || get_1562||get_trp) begin cnt_0 <= TRC-1; end else if(get_trc2)begin cnt_0 <= TMRD-1; end else if(get_tmrd||get_trc3) cnt_0 <= TIME_1562-1; else if(cnt_0 != 0) cnt_0 <= cnt_0 -1; end //---------------------------------------------------------------------- assign cke=1; //cke始终为1 always @(posedge clk or negedge rst_n)begin //dqm在初始化状态始终为1 if(rst_n==1‘b0)begin dqm<=2‘b11; end else if( c_state == NOP || c_state == PRECHARG || c_state == AUTO_REF1 || c_state == AUTO_REF2 || c_state ==AUTO_REF2 || c_state == MODE_REG ) begin dqm<=2‘b11; end else dqm<=2‘b00; end assign dq = 16‘hzzzz; //dq为高阻态 assign {cs,ras,cas,we} = command; //cs,ras,cas,we的设计 always @(posedge clk or negedge rst_n)begin if(rst_n==1‘b0)begin command <= NOP_CD ; end else if(get_100us) begin command <= PRECHARGE_CD ; end else if(get_trp || get_trc1 || get_1562 ) command <= AUTO_REF_CD ; else if(get_trc2) command <= MODE_REG_CD ; else command <= NOP_CD ; end always @(posedge clk or negedge rst_n)begin if(rst_n==1‘b0)begin addr <= 0; end else if(get_trc2) begin addr <= MODE_VALUE; end else if(get_100us) addr <= (12‘b1 << 10 ); //A10=1 else addr <= 0; end always @(posedge clk or negedge rst_n)begin //bank初始化用不到,取0; if(rst_n==1‘b0)begin bank <= 2‘b00; end else begin bank <= 2‘b00; end end endmodule
testbench
`timescale 1 ns/1 ns module Sdram_test(); //时钟和复位 reg clk ; reg rst_n; //uut的输入信号 wire cke ; wire cs ; //片选信号 wire ras ; //行 wire cas ; //列 wire we ; //读写控制端 wire [11:0] dqm ; //byte controlled by LDQM and UDQM wire [11:0] addr ; //12个位地址 wire [ 1:0] bank ; //sdram有4个逻辑bank wire [15:0] dq ; //是三态门 //时钟周期,单位为ns,可在此修改时钟周期。 parameter CYCLE = 10; //复位时间,此时表示复位3个时钟周期的时间。 parameter RST_TIME = 3 ; //待测试的模块例化 Sdram_initial uu1( .clk (clk ), .rst_n(rst_n), .cke (cke ), .cs (cs ), .ras (ras ), .cas (cas ), .we (we ), .dqm (dqm ), .addr (addr), .bank (bank), .dq (dq ) ); //生成本地时钟50M initial begin clk = 0; forever #(CYCLE/2) clk=~clk; end //产生复位信号 initial begin rst_n = 1; #2; rst_n = 0; #(CYCLE*RST_TIME); rst_n = 1; end endmodule
1、2、3、4、5就是初始化的5个状态,用红框框起来的数字就是各种时间的初始值 Trp=3 , Trc=7, Tmrd=2(倒数到0,因此需要减1)
由图可知,自动刷新也正常。
如有问题欢迎指正交流。
转载请注明出处:http://www.cnblogs.com/aslmer/p/5860382.html
标签:
原文地址:http://www.cnblogs.com/aslmer/p/5860382.html