基于verilog的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

时间: 2024-11-03 21:21:20

基于verilog的SDRAM初始化的相关文章

基于Verilog HDL整数乘法器设计与仿真验证

基于Verilog HDL整数乘法器设计与仿真验证 1.预备知识 整数分为短整数,中整数,长整数,本文只涉及到短整数.短整数:占用一个字节空间,8位,其中最高位为符号位(最高位为1表示为负数,最高位为0表示为正数),取值范围为-127~127. 负数的表示方法为正值的求反又加1.例如: 8’b0000_0100; //表示值:4,正值求反为:8’b1111_1011:再加1表示为:8’b1111_1100,这样便得到了-4的表示方法为:8’b1111_1100. 同理,负值变成正值的方法为:负值

嵌入式Linux裸机开发(五)——SDRAM初始化

嵌入式Linux裸机开发(五)--SDRAM初始化 一.SDRAM初始化流程 S5PV210有两个独立的DRAM控制器,一个最大支持512MB,一个最大支持1024MB,但两个控制器必须支持相同类型的内存. 根据三星S5PV210文档可知,DDR2类型内存的初始化流程如下: 1.提供稳压电源给内存控制器和内存芯片,内存控制器必须保持CLE在低电平,此时就会提供稳压电源.注:当CKE引脚为低电平时,XDDR2SEL应该处于高电平 2.根据时钟频率正确配置PhyControl0.ctrl_start

基于Verilog的奇数偶数小数分频器设计

今天呢,由泡泡鱼工作室发布的微信公共号“硬件为王”(微信号:king_hardware)正式上线啦,关注有惊喜哦.在这个普天同庆的美好日子里,小编脑洞大开,决定写一首诗赞美一下我们背后伟大的团队,虽然连上我只有两个人,但丝毫不影响我们的工作热情和创业野心.合抱之木,生于毫末:九层之台,起于垒土:千里之行,始于足下! 首先小编在这里分享一个基于Verilog语言的分频器设计,该分频器实现了奇数.偶数.小数(0.5)分频,可综合,能跑700M左右的时钟,基本能够满足大部分应用需求. 一:背景 前天,

基于Verilog的带FIFO输出缓冲的串口接收接口封装

一.模块框图及基本思路 rx_module:串口接收的核心模块,详细介绍请见"基于Verilog的串口接收实验" rx2fifo_module:rx_module与rx_fifo之间的控制模块,其功能是不断接收并将数据写入rx_fifo rx_interface:串口接收接口封装,也就是前两个模块的组合 rx_interface_control:串口接收接口控制模块,每隔1s读取一次串口rx_fifo,并将数据的低四位用Led显示出来 rx_interface_top:串口接收接口顶层

基于Verilog的CRC-CCITT校验

由于笔者在自己设计CRC模块时遇到很多问题,在网上并未找到一篇具有实际指导意义的文章,在经过多次仿真修改再仿真之后得到了正确的结果,故愿意在本文中为大家提供整个设计流程供大家快速完成设计.本文章主要针对具体的实际应用给出一套亲测可行的实现办法,给出设计代码并提供仿真结果,供各位参考. 一.CRC概述 CRC(Cyclic Redundancy Check),循环冗余校验,是一种数字通信中的常用查错校验码.其特征是信息段和校验字段的长度可以任意选定. 校验方法为发送方对信息数据执行约定好除数的二进

基于Annotation的IOC 初始化

从Spring2.0 以后的版本中,Spring 也引入了基于注解(Annotation)方式的配置,注解(Annotation)是JDK1.5 中引入的一个新特性,用于简化Bean 的配置,可以取代XML 配置文件.开发人员对注解(Annotation)的态度也是萝卜青菜各有所爱,个人认为注解可以大大简化配置,提高开发速度,但也给后期维护增加了难度.目前来说XML 方式发展的相对成熟,方便于统一管理.随着Spring Boot 的兴起,基于注解的开发甚至实现了零配置.但作为个人的习惯而言,还是

SDRAM初始化

DDR配置过程比较复杂,基本上是按照DDR控制器的时序要求来做的,其中很多参数要结合DDR芯片本身的参数来定,还有些参数是时序参数,要去详细计算.所以DDR配置非常繁琐.细致.专业.所以我们对DDR初始化的态度就是:学会这种思路和方法,结合文档和代码能看懂,会算一些常见的参数即可. .global sdram_asm_init sdram_asm_init: ldr r0, =0xf1e00000 ldr r1, =0x0 str r1, [r0, #0x0] /* DMC0 Drive Str

一路艰辛调试特权同学Verilog读写SDRAM实验,终于通了。

今年过完年回到学校,大概二月19日,开始调SDRAM这个实验,目的是想做最后的那个数码相框的项目.特权使用的SDRAM是三星的K4S641632(64M),而我板子上是海力士的H57V1262GTR(128M),由于不知道二者时序是否兼容,于是乖乖的按照特权的建议,仔仔细细的把<SDRAM-高手进阶,终极内存技术指南——完整进阶版.pdf>一文读了个遍,结果感觉时序是一样的,又从网上查资料,得到的结论也是二者兼容.于是不打算动其中大的时序过程.检查程序,修改程序,进行了许多尝试,下到我的板子上

基于verilog的FPGA编程经验总结(XILINX ISE工具)

1.用ISE仿真的时候.所用变量一定要初始化. ISE默认初始量为"XXXXX", 而Quarters是默认为"00000"的, 其实实际上, 下到FPGA里后也是默认为0的,只是可以说ISE严谨得令人DT吧.比如说用一个累加器, result = A+B+result ,必须保证在某一刻A, B, result都为定值时, 之后的数据才不会一直为"XXXXX"; 2.所有的中间线(就是module间用来传递参数的信号)都要用wire定义一下.