zoukankan      html  css  js  c++  java
  • 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教程

  • 相关阅读:
    Mimikatz命令简单使用
    WPA加密数据包简单破解-aircrack-ng
    Pwn相关工具安装
    ubuntu火狐浏览器汉化
    Wireshark-sslkeylogfile
    有关RSA 命令总结
    二、volatile关键字
    一、Java JUC简介
    VUE之图表操作
    Drools+springboot
  • 原文地址:https://www.cnblogs.com/xianyufpga/p/12233187.html
Copyright © 2011-2022 走看看