目录

1、SDRAM初始化的内容(结合英文数据手册)

2、SDRAM初始化的时序

3、代码的编写

4、modesim的仿真

 


 SDRAM初始化的内容

    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.

command.

Sdram 在工作前需要进行初始化
1、sdram 上电,时钟稳定,DQM高,CKE高,开始初始化
2、至少100us的等待时间,在这个等待时间之内不能有除了COMMAND INHIBIT 或 NOP 以外的任何命令,COMMAND INHIBIT 或 NOP命令需持续生效。
3、在100us等待时间结束之后,所有的 bank 需要预充电,(执行 PRECHARGE 需要 tRP 的时间)。
4、至少两个自动刷新命令(每个自动刷新都需要tRC的时间)
5、模式寄存器的配置(需要tMRD的时间)。
6、初始化完成以后处于idle的状态,每隔 64ms/2^12 =64_000_000 ns/4096=15625ns,因为工作时钟为100Mhz,所以需要每隔1562个时钟需要发一个自动刷新指令(这个64ms将所有行刷新一次是由SDRAM的内部结构决定的)
 注意:所需要的时间需要从数据手册中得到(datasheet一定要看英文原版)
SDRAM学习(二)之初始化

SDRAM学习(二)之初始化 

状态机
SDRAM学习(二)之初始化
 

SDRAM初始化的时序 

SDRAM学习(二)之初始化

这个时序图可以结合状态机的图理解,非常重要,因为每个状态需要的时间都不一样,所以需要设计计数器。

1、CKE 一直为高电平

2、command 由 cs,ras,cas,we 四个控制信号实现,具体如下图

例如 NOP命令 cs=0,ras=1,cas=1,we=1

SDRAM学习(二)之初始化

3、DQM在初始化的时候始终为1

4、A10为高,则忽略BA0,BA1,对所有bank 进行预刷新。

5、在配置模式寄存器时,根据自己的需求设置参数

例如当 mode_value=000_00_011_0_111 即全页模式,顺序,CL=3,突发读,突发写。

SDRAM学习(二)之初始化

 


代码的编写

初始化代码

/*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

 


modesim的仿真

SDRAM学习(二)之初始化

1、2、3、4、5就是初始化的5个状态,用红框框起来的数字就是各种时间的初始值 Trp=3 , Trc=7, Tmrd=2(倒数到0,因此需要减1)

SDRAM学习(二)之初始化

由图可知,自动刷新也正常。

如有问题欢迎指正交流。

 转载请注明出处:http://www.cnblogs.com/aslmer/p/5860382.html

相关文章: