SDRAM(2):初始化


  查詢手上的 SDRAM 芯片對應數據手冊《 Winbond W9812G6KH - 6》,感覺它的初始化部分講得有些模糊,所以拿到另一款 SDRAM 芯片的數據手冊《IS42S116160》來分析,雖然 SDRAM 芯片不一樣,但初始化操作是類似的。

 

一、初始化過程

1、文字描述

  數據手冊原文:Prior to normal operation, the SDRAM must be initialized. 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 200us period and should continue 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.

  由此我們知道:在 SDRAM 正常工作前必須先進行初始化。在執行任何命令前(除了 COMMAND INHIBIT 或 NOP命令),必須先延時等待 100us,在 200us 周期內,可能會執行 COMMAND INHIBIT 或 NOP 命令,並一直到該 200us 的結束。執行完至少一次的 COMMAND INHIBIT 或 NOP 命令后,且滿足了上電后延時等待 100us 這個條件,就必須立刻給一個 PRECHAEGE 命令。所有的 Bank (A10為高電平)都必須被預充電,在至少兩個 AUTO REFRESH 周期后,所有 Bank 都處於空閑狀態,之后 SDRAM 准備加載模式寄存器。在執行任何其他的操作命令前,都應先加載模式寄存器,因為模式寄存器上電后處於未知的狀態。

2、初始化時序圖

  上面的文字描述還是說得不是很清楚,我們根據時序圖再來捋一捋初始化過程到底怎么回事:

① 上電后先延時 100us,此過程中命令為 INIHIBIT 或 NOP。但前文又說 200us 內都可能有命令,干脆這里取 T = 200us 吧。

② 200us 時間結束后,給出一個命令: PRECHARGRE,對所有 Bank 進行預充電。然后等待時間 tRP,這期間命令為 INIHIBIT 或 NOP。

③ tRP 時間結束后,給出一個命令:AUTO REFRESH,然后等待時間 tRP,這期間命令為 INIHIBIT 或 NOP。

④ tRP 時間結束后,給出一個命令:AUTO REFRESH,然后等待時間 tRC,這期間命令為 INIHIBIT 或 NOP。

⑤ tRC 時間結束后,給出一個命令:Load MODE REGISTER,然后等待時間 tMRD,之后 SDRAM 初始化完成。

注:tRP、tRC、tMRD等時間均可在數據手冊中查到,可大不可小。

 

二、加載模式寄存器

  前面所說有一個命令是 Load MODE REGISTER ,即加載模式寄存器,也就是將各個位設計成需要的方式。由數據手冊得到下表,從右往左分析一下。

1、Burst Length:突發長度,如果突發長度是4,那突發寫時,只需給出4個寫數據和需要寫入地址的首地址,那么剩下的數據會排隊寫進去,一次共寫入4個數據;突發讀時,只需要給出1個讀數據的地址,那么剩下的數據會排隊讀出來,一次共讀出4個數據。SDRAM 提供 1、2、4、8 和全頁(一行)共 5 種突發長度,但注意全頁突發必須與 BURST TERMINATE 命令一起使用,以生成任意突發長度。本次設計中我們采用的突發長度為4,即 { A2,A1,A0 } = { 0,1,0 }

2、Burst Type:突發類型,順序型或交錯型,一般都是選擇順序型,即 A3 = 0。

3、CAS Latency:列選通潛伏期,即給出讀命令和SDRAM 的讀取 DQ 之間的延遲關系,只有 2 和 3 可以選擇,我們選 3 吧,即 { A6,A5,A4 ) = {0,1,1}。其時序如下所示:

4、OP code:寫模式,讀和寫都選擇成突發,即 A9 = 0。

  因此,再結合上篇博客的操作命令,那總的的模式寄存器的配置方式如下所示:CMD_LMR  = { CS_n,RAS_n,CAS_n,WE_n,BA[1:0],A[11:0] =  18'b0000_00_0000_0011_0010;

 

三、時序設計

  根據上文,我們可以設計出 SDRAM 初始化模塊的時序圖,如下所示:

  此模塊我們命名為 SDRAM_init,具體代碼就不貼了,初始化模塊還是比較簡單的。

  此外還需要建立一個頂層 top 模塊,將 SDRAM 相關接口寫好,同時有些信號還沒有設計,可以先采用賦值的方式。

 1 module top
 2 //========================< 端口 >==========================================
 3 (
 4 //system --------------------------------------------
 5 input   wire                clk                     , //clock,50Mhz
 6 input   wire                rst_n                   , //reset
 7 //sdram ---------------------------------------------
 8 output  wire                sdram_clk               , //sdram clk
 9 output  wire                sdram_cke               , //sdram cke
10 output  wire                sdram_cs_n              , //sdram cs_n
11 output  wire                sdram_ras_n             , //sdram ras_n
12 output  wire                sdram_cas_n             , //sdram cas_n
13 output  wire                sdram_we_n              , //sdram we_n
14 output  wire    [ 1:0]      sdram_bank              , //sdram bank
15 output  wire    [11:0]      sdram_addr              , //sdram addr
16 output  wire    [ 1:0]      sdram_dqm               , //sdram dqm
17 inout   wire    [15:0]      sdram_dq                  //tri_single
18 );
19 //========================< 連線 >==========================================
20 //init ----------------------------------------------
21 wire                        init_end                ;
22 wire    [ 3:0]              init_cmd                ;
23 wire    [11:0]              init_addr               ;
24 
25 
26 //==========================================================================
27 //==    信號設置
28 //==========================================================================
29 assign sdram_clk  = ~clk; //SDRAM命令在系統時鍾下書寫產生,取反即可保證SDRAM內部時鍾能采到這些命令
30 assign sdram_cke  = 1'b1;
31 assign sdram_dqm  = 2'b00;
32 assign sdram_bank = 2'b00;
33 assign {sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n} = init_cmd;
34 assign sdram_addr = init_addr;
35 
36 //==========================================================================
37 //==    例化
38 //==========================================================================
39 SDRAM_init u_SDRAM_init
40 (
41     .clk                    (clk                    ),              
42     .rst_n                  (rst_n                  ),
43     .init_end               (init_end               ),
44     .init_cmd               (init_cmd               ),
45     .init_addr              (init_addr              )
46 );
47 
48 
49 
50 
51 endmodule 

 

四、SDRAM 仿真模型

   SDRAM 這個器件還是比較復雜的,靠我們自己手寫仿真非常困難,但我們可以利用 SDRAM 仿真模型 sdram_model_plus.v ,我們再設計一個 testbench,將此仿真模型例化進去即可。

 1 `timescale 1ns/1ps  //時間精度
 2 `define    Clock 20 //時鍾周期
 3 
 4 module top_tb;
 5 
 6 //========================< 端口 >==========================================
 7 //system ------------------------------------
 8 reg                     clk                 ; //時鍾,50Mhz
 9 reg                     rst_n               ; //復位,低電平有效
10 //sdram -------------------------------------
11 wire                    sdram_clk           ;
12 wire                    sdram_cke           ;
13 wire                    sdram_cs_n          ;
14 wire                    sdram_ras_n         ;
15 wire                    sdram_cas_n         ;
16 wire                    sdram_we_n          ;
17 wire [ 1:0]             sdram_bank          ;
18 wire [11:0]             sdram_addr          ;
19 wire [ 1:0]             sdram_dqm           ;
20 wire [15:0]             sdram_dq            ;
21 
22 //==========================================================================
23 //==    模塊例化
24 //==========================================================================
25 top u_top                                       //top層連線
26 (
27     .clk                (clk                ),
28     .rst_n              (rst_n              ),
29     .sdram_clk          (sdram_clk          ),
30     .sdram_cke          (sdram_cke          ),
31     .sdram_cs_n         (sdram_cs_n         ),
32     .sdram_ras_n        (sdram_ras_n        ),
33     .sdram_cas_n        (sdram_cas_n        ),
34     .sdram_we_n         (sdram_we_n         ),
35     .sdram_bank         (sdram_bank         ),
36     .sdram_addr         (sdram_addr         ),
37     .sdram_dqm          (sdram_dqm          ),
38     .sdram_dq           (sdram_dq           )
39 );
40 
41 sdram_model_plus u_sdram_model_plus             //sdram仿真模型
42 (
43     .Dq                 (sdram_dq           ),
44     .Addr               (sdram_addr         ),
45     .Ba                 (sdram_bank         ),
46     .Clk                (sdram_clk          ),
47     .Cke                (sdram_cke          ),
48     .Cs_n               (sdram_cs_n         ),
49     .Ras_n              (sdram_ras_n        ),
50     .Cas_n              (sdram_cas_n        ),
51     .We_n               (sdram_we_n         ),
52     .Dqm                (sdram_dqm          ),
53     .Debug              (1'b1               )  //為0則不會打印信息
54 );
55 
56 //==========================================================================
57 //==    修改SDRAM仿真模型的部分參數,以符合本次設計
58 //==========================================================================
59 defparam u_sdram_model_plus.addr_bits = 12;             //地址位寬
60 defparam u_sdram_model_plus.data_bits = 16;             //數據位寬
61 defparam u_sdram_model_plus.col_bits  = 9;              //col地址位寬A0-A8
62 defparam u_sdram_model_plus.mem_sizes = 2*1024*1024-1;  //2M
63 
64 //==========================================================================
65 //==    時鍾信號和復位信號
66 //==========================================================================
67 initial begin
68     clk = 1;
69     forever
70         #(`Clock/2) clk = ~clk;
71 end
72 
73 initial begin
74     rst_n = 0; #(`Clock*1+1);
75     rst_n = 1;
76 end
77 
78 
79 
80 
81 endmodule

  此外,該仿真模型  sdram_model_plus.v 需要修改一個地方, 第72行代碼為 input [3 : 0] Dqm;  ,我們這次設計的 Dqm信號是2位的,所以[3:0]改為[1:0],此外再注釋掉第835行和836行。最后打開 Modelsim 軟件進行仿真,仿真結果如下所示:

  可以看到下方打印出了信息,指出我們這次設計的情況。波形上 init_end 信號拉高了,表明初始化結束,同時仔細對比這些信號,沒發現什么問題,表明此次設計成功。

 

參考資料:[1]威三學院FPGA教程

       [2]開源騷客FPGA教程

 


免責聲明!

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



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