SDRAM學習(二)之初始化


目錄

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.

    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.

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初始化的時序 

這個時序圖可以結合狀態機的圖理解,非常重要,因為每個狀態需要的時間都不一樣,所以需要設計計數器。

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

 


 modesim的仿真

1、2、3、4、5就是初始化的5個狀態,用紅框框起來的數字就是各種時間的初始值 Trp=3 , Trc=7, Tmrd=2(倒數到0,因此需要減1)

由圖可知,自動刷新也正常。

如有問題歡迎指正交流。

 轉載請注明出處:http://www.cnblogs.com/aslmer/p/5860382.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM