• 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

  • 相关阅读:
    POJ 2184 Cow Exhibition (01背包变形)(或者搜索)
    ACM-ICPC如何起步[转]
    查看centos中的用户和用户组和修改密码
    CentOS7安装并配置PostgreSQL
    在Win10下,python3和python2同时安装并解决pip共存问题
    Django-用户-组-权限
    linux系统磁盘满了,怎么解决?
    DRF (Django REST framework) 中的路由Routers
    DRF (Django REST framework) 中的视图扩展类
    DRF (Django REST framework) 中的视图类
  • 原文地址:https://www.cnblogs.com/aslmer/p/5860382.html
Copyright © 2020-2023  润新知