2018/7/26

受教于邓堪文老师,开始真真学习控制sdram

由于自己买的sdram模块是256的,原来老师的是128,所以边学边改,不知道最后好不好使,但是我有信心

一.sdram的初始化

sdram介绍啥的就不用了,上来就是干,简单粗暴。

1.下面是引脚说明,看不懂自己可以用百度翻译,需要注意的是红框内的地址引脚和行列地址是复用的,A0~A12是行地址,A0~8是列地址

简单说一下SDRAM的容量计算:数据位宽 *行地址*列地址*bank数,我们用的256有4个bank,就是:16*8192*512*4

2.我的fpga是50m时钟,20ns一个周期,下图是初始化的时序图

sdram上电要延时至少100us,我们是延时200us,然后precharge(预充电)命令,隔tRP时间也就是一个时钟周期20ns进行第一次auto_refresh(自刷新),再隔tRC时间也就是四个时钟周期进行第二次auto_refresh命令,

又tRC时间进行mode_register(模式寄存器配置)。期间的NOP是空操作命令。还有就是这几个时间要看自己使用sdram的datasheet

3.上面说的命令也是要去datasheet手册去找,对应CS,RAS,CAS,WE的操作

4.模式配置对应datasheet ,根据红框addr:0_0000_0010_0010

5.再来一张时序图

6.该上源码了,应该没啥看不懂的吧

 1 `timescale     1ns/1ns
 2
 3 module        tb_sdram_top;
 4
 5 reg                sclk                ;
 6 reg                s_rst_n                ;
 7
 8 //----------------------------------------------------------
 9 wire            sdram_clk            ;
10 wire            sdram_cke            ;
11 wire            sdram_cs_n            ;
12 wire            sdram_cas_n            ;
13 wire            sdram_ras_n            ;
14 wire            sdram_we_n            ;
15 wire    [1:0]    sdram_bank            ;
16 wire    [12:0]    sdram_addr            ;
17 wire    [1:0]    sdram_dqm            ;
18 wire    [15:0]    sdram_dq            ;
19
20
21
22
23
24 initial    begin
25         sclk    =    1;
26         s_rst_n    <=    0;
27         #100
28         s_rst_n    <=    1;
29 end
30
31 always    #10        sclk    =    ~sclk;
32
33
34
35 sdram_top        sdram_top_inst(
36         //system signals
37         .sclk                    (sclk                ),
38         .s_rst_n                (s_rst_n            ),
39         //SDRAM Interfaces
40         .sdram_clk                (sdram_clk            ),
41         .sdram_cke                (sdram_cke            ),
42         .sdram_cs_n                (sdram_cs_n            ),
43         .sdram_cas_n            (sdram_cas_n        ),
44         .sdram_ras_n            (sdram_ras_n        ),
45         .sdram_we_n                (sdram_we_n            ),
46         .sdram_bank                (sdram_bank            ),
47         .sdram_addr                (sdram_addr            ),
48         .sdram_dqm                (sdram_dqm            ),
49         .sdram_dq                (sdram_dq            )
50 );
51
52
53 sdram_model_plus     sdram_model_plus_inst(
54         .Dq                      (sdram_dq            ),
55         .Addr                    (sdram_addr        ),
56         .Ba                      (sdram_bank        ),
57         .Clk                     (sdram_clk            ),
58         .Cke                     (sdram_cke            ),
59         .Cs_n                    (sdram_cs_n        ),
60         .Ras_n                   (sdram_ras_n        ),
61         .Cas_n                   (sdram_cas_n        ),
62         .We_n                    (sdram_we_n        ),
63         .Dqm                     (sdram_dqm            ),
64         .Debug                   (1'b1                )
65 );
66
67 endmodule

tb_sdram_top

 1 module sdram_ini(
 2             //systejm signal
 3             input                sclk            ,
 4             input                s_rst_n            ,
 5             //others
 6             output reg    [3:0]    cmd_reg            ,
 7             output wire  [12:0]    sdram_addr        ,
 8             output                flag_ini_end
 9 );
10
11 //==============================================================================\
12 //*********************Define Parameter and Internal Signal ********************
13 //==============================================================================/
14
15 localparam            DELAY_200US        =    10000    ;
16 //SDRAM Command
17 localparam            NOP                =    4'b0111    ;
18 localparam            PRE                =    4'b0010    ;
19 localparam            AREF            =    4'b0001    ;
20 localparam            MSET            =    4'b0000    ;
21
22 reg            [13:0]    cnt_200us                    ;
23 wire                flag_200us                    ;
24 reg            [3:0]    cnt_cmd                        ;
25
26 //=============================================================================\
27 //********************** Main Code    ***************************************
28 //=============================================================================/
29
30 always @(posedge sclk or negedge s_rst_n) begin
31         if(s_rst_n == 1'b0)
32                 cnt_200us <= 14'd0;
33         else if (flag_200us == 1'b0)
34                 cnt_200us <= cnt_200us + 1'b1;
35 end
36
37 always @(posedge sclk or negedge s_rst_n) begin
38         if(s_rst_n == 1'b0)
39                 cnt_cmd        <=        4'd0;
40         else if(flag_200us == 1'b1 && flag_ini_end == 1'b0)
41                 cnt_cmd        <=         cnt_cmd    +    1'b1;
42 end
43
44 //cmd_reg
45 always @(posedge sclk or negedge s_rst_n ) begin
46         if(s_rst_n == 1'b0)
47                 cmd_reg <= NOP;
48         else if(flag_200us == 1'b1)
49                 case(cnt_cmd)
50                         0:    cmd_reg    <=    PRE        ;
51                         1:    cmd_reg <=  AREF    ;
52                         4:    cmd_reg <=    AREF    ;
53                         9:    cmd_reg    <=    MSET    ;
54                         default    :    cmd_reg <= NOP ;
55                 endcase
56 end
57 assign        flag_ini_end    =    (cnt_cmd >= 4'd10)    ?    1'b1    :    1'b0;
58 assign        sdram_addr        =    (cmd_reg == MSET)    ?    13'b0_0000_0011_0010 : 13'b0_0100_0000_0000;
59 assign        flag_200us        =    (cnt_200us >= DELAY_200US)     ?     1'b1    :    1'b0;
60
61 endmodule

sdram_init

 1 module sdram_top(
 2         //system signals
 3         input                    sclk            ,
 4         input                    s_rst_n            ,
 5         //SDRAM Interfaces
 6         output    wire            sdram_clk        ,
 7         output    wire            sdram_cke        ,
 8         output    wire            sdram_cs_n        ,
 9         output    wire            sdram_cas_n        ,
10         output    wire            sdram_ras_n        ,
11         output    wire            sdram_we_n        ,
12         output    wire    [1:0]    sdram_bank        ,
13         output    wire    [12:0]    sdram_addr        ,
14         output    wire    [1:0]    sdram_dqm        ,
15         inout            [15:0]    sdram_dq
16 );
17
18 //==============================================================================\
19 //*********************Define Parameter and Internal Signal ********************
20 //==============================================================================/
21 //init module
22 wire                    flag_ini_end            ;
23 wire    [3:0]            init_cmd                ;
24 wire    [12:0]            init_addr                ;
25
26
27 //=============================================================================\
28 //********************** Main Code    ***************************************
29 //=============================================================================/
30 assign    sdram_cke        =    1'b1;
31 assign    sdram_addr        =   init_addr;
32 assign    {sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n}    =    init_cmd ;
33 assign    sdram_dqm        =    2'd0;
34 assign    sdram_clk         =     ~sclk;
35
36
37 sdram_ini        sdram_ini_inst(
38             //systejm signal
39             .sclk                (sclk            ),
40             .s_rst_n            (s_rst_n        ),
41             //others
42             .cmd_reg            (init_cmd        ),
43             .sdram_addr            (init_addr        ),
44             .flag_ini_end       (flag_ini_end    )
45 );
46
47
48 endmodule

sdram_top

这用了一个sdram仿真模型,堪文老师是128的,我的256的不能用,但是我改好了

   1 /***************************************************************************************
   2 作者:    李晟
   3 2003-08-27    V0.1    李晟
   4
   5  添加内存模块倒空功能,在外部需要创建事件:sdram_r ,本SDRAM的内容将会按Bank 顺序damp out 至文件
   6  sdram_data.txt 中
   7 ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××*/
   8 //2004-03-04    陈乃奎    修改原程序中将BANK的数据转存入TXT文件的格式
   9 //2004-03-16    陈乃奎    修改SDRAM 的初始化数据
  10 //2004/04/06    陈乃奎    将SDRAM的操作命令以字符形式表示,以便用MODELSIM监视
  11 //2004/04/19    陈乃奎    修改参数 parameter tAC  =   8;
  12 //2010/09/17    罗瑶    修改sdram的大小,数据位宽,dqm宽度;
  13 /****************************************************************************************
  14 *
  15 *    File Name:  sdram_model.V
  16 *      Version:  0.0f
  17 *         Date:  July 8th, 1999
  18 *        Model:  BUS Functional
  19 *    Simulator:  Model Technology (PC version 5.2e PE)
  20 *
  21 * Dependencies:  None
  22 *
  23 *       Author:  Son P. Huynh
  24 *        Email:  sphuynh@micron.com
  25 *        Phone:  (208) 368-3825
  26 *      Company:  Micron Technology, Inc.
  27 *        Model:  sdram_model (1Meg x 16 x 4 Banks)
  28 *
  29 *  Description:  64Mb SDRAM Verilog model
  30 *
  31 *   Limitation:  - Doesn't check for 4096 cycle refresh
  32 *
  33 *         Note:  - Set simulator resolution to "ps" accuracy
  34 *                - Set Debug = 0 to disable $display messages
  35 *
  36 *   Disclaimer:  THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
  37 *                WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
  38 *                IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
  39 *                A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
  40 *
  41 *                Copyright ?1998 Micron Semiconductor Products, Inc.
  42 *                All rights researved
  43 *
  44 * Rev   Author          Phone         Date        Changes
  45 * ----  ----------------------------  ----------  ---------------------------------------
  46 * 0.0f  Son Huynh       208-368-3825  07/08/1999  - Fix tWR = 1 Clk + 7.5 ns (Auto)
  47 *       Micron Technology Inc.                    - Fix tWR = 15 ns (Manual)
  48 *                                                 - Fix tRP (Autoprecharge to AutoRefresh)
  49 *
  50 * 0.0a  Son Huynh       208-368-3825  05/13/1998  - First Release (from 64Mb rev 0.0e)
  51 *       Micron Technology Inc.
  52 ****************************************************************************************/
  53
  54 `timescale 1ns / 100ps
  55
  56 module sdram_model_plus (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm,Debug);
  57
  58     parameter addr_bits =    13;
  59     parameter data_bits =     16;
  60     parameter col_bits  =    9;
  61     parameter mem_sizes =    4*1024*1024 -1;//1 Meg
  62
  63     inout     [data_bits - 1 : 0] Dq;
  64     input     [addr_bits - 1 : 0] Addr;
  65     input                 [1 : 0] Ba;
  66     input                         Clk;
  67     input                         Cke;
  68     input                         Cs_n;
  69     input                         Ras_n;
  70     input                         Cas_n;
  71     input                         We_n;
  72     input                 [1 : 0] Dqm;          //高低各8bit
  73     //added by xzli
  74     input              Debug;
  75
  76     reg       [data_bits - 1 : 0] Bank0 [0 : mem_sizes];//存储器类型数据
  77     reg       [data_bits - 1 : 0] Bank1 [0 : mem_sizes];
  78     reg       [data_bits - 1 : 0] Bank2 [0 : mem_sizes];
  79     reg       [data_bits - 1 : 0] Bank3 [0 : mem_sizes];
  80
  81     reg                   [1 : 0] Bank_addr [0 : 3];                // Bank Address Pipeline
  82     reg        [col_bits - 1 : 0] Col_addr [0 : 3];                 // Column Address Pipeline
  83     reg                   [3 : 0] Command [0 : 3];                  // Command Operation Pipeline
  84     reg                   [3 : 0] Dqm_reg0, Dqm_reg1;               // DQM Operation Pipeline
  85     reg       [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
  86
  87     reg       [addr_bits - 1 : 0] Mode_reg;
  88     reg       [data_bits - 1 : 0] Dq_reg, Dq_dqm;
  89     reg       [col_bits - 1 : 0] Col_temp, Burst_counter;
  90
  91     reg                           Act_b0, Act_b1, Act_b2, Act_b3;   // Bank Activate
  92     reg                           Pc_b0, Pc_b1, Pc_b2, Pc_b3;       // Bank Precharge
  93
  94     reg                   [1 : 0] Bank_precharge     [0 : 3];       // Precharge Command
  95     reg                           A10_precharge      [0 : 3];       // Addr[10] = 1 (All banks)
  96     reg                           Auto_precharge     [0 : 3];       // RW AutoPrecharge (Bank)
  97     reg                           Read_precharge     [0 : 3];       // R  AutoPrecharge
  98     reg                           Write_precharge    [0 : 3];       //  W AutoPrecharge
  99     integer                       Count_precharge    [0 : 3];       // RW AutoPrecharge (Counter)
 100     reg                           RW_interrupt_read  [0 : 3];       // RW Interrupt Read with Auto Precharge
 101     reg                           RW_interrupt_write [0 : 3];       // RW Interrupt Write with Auto Precharge
 102
 103     reg                           Data_in_enable;
 104     reg                           Data_out_enable;
 105
 106     reg                   [1 : 0] Bank, Previous_bank;
 107     reg       [addr_bits - 1 : 0] Row;
 108     reg        [col_bits - 1 : 0] Col, Col_brst;
 109
 110     // Internal system clock
 111     reg                           CkeZ, Sys_clk;
 112
 113     reg    [24:0]    dd;
 114
 115     // Commands Decode
 116     wire      Active_enable    = ~Cs_n & ~Ras_n &  Cas_n &  We_n;
 117     wire      Aref_enable      = ~Cs_n & ~Ras_n & ~Cas_n &  We_n;
 118     wire      Burst_term       = ~Cs_n &  Ras_n &  Cas_n & ~We_n;
 119     wire      Mode_reg_enable  = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
 120     wire      Prech_enable     = ~Cs_n & ~Ras_n &  Cas_n & ~We_n;
 121     wire      Read_enable      = ~Cs_n &  Ras_n & ~Cas_n &  We_n;
 122     wire      Write_enable     = ~Cs_n &  Ras_n & ~Cas_n & ~We_n;
 123
 124     // Burst Length Decode
 125     wire      Burst_length_1   = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
 126     wire      Burst_length_2   = ~Mode_reg[2] & ~Mode_reg[1] &  Mode_reg[0];
 127     wire      Burst_length_4   = ~Mode_reg[2] &  Mode_reg[1] & ~Mode_reg[0];
 128     wire      Burst_length_8   = ~Mode_reg[2] &  Mode_reg[1] &  Mode_reg[0];
 129
 130     // CAS Latency Decode
 131     wire      Cas_latency_2    = ~Mode_reg[6] &  Mode_reg[5] & ~Mode_reg[4];
 132     wire      Cas_latency_3    = ~Mode_reg[6] &  Mode_reg[5] &  Mode_reg[4];
 133
 134     // Write Burst Mode
 135     wire      Write_burst_mode = Mode_reg[9];
 136
 137     wire      Debug;        // Debug messages : 1 = On; 0 = Off
 138     wire      Dq_chk           = Sys_clk & Data_in_enable;      // Check setup/hold time for DQ
 139
 140     reg        [31:0]    mem_d;
 141
 142     event    sdram_r,sdram_w,compare;
 143
 144
 145
 146
 147     assign    Dq               = Dq_reg;                        // DQ buffer
 148
 149     // Commands Operation
 150     `define   ACT       0
 151     `define   NOP       1
 152     `define   READ      2
 153     `define   READ_A    3
 154     `define   WRITE     4
 155     `define   WRITE_A   5
 156     `define   PRECH     6
 157     `define   A_REF     7
 158     `define   BST       8
 159     `define   LMR       9
 160
 161 //    // Timing Parameters for -75 (PC133) and CAS Latency = 2
 162 //    parameter tAC  =   8;    //test 6.5
 163 //    parameter tHZ  =   7.0;
 164 //    parameter tOH  =   2.7;
 165 //    parameter tMRD =   2.0;     // 2 Clk Cycles
 166 //    parameter tRAS =  44.0;
 167 //    parameter tRC  =  66.0;
 168 //    parameter tRCD =  20.0;
 169 //    parameter tRP  =  20.0;
 170 //    parameter tRRD =  15.0;
 171 //    parameter tWRa =   7.5;     // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns)
 172 //    parameter tWRp =  0.0;     // A2 Version - Precharge mode only (15 ns)
 173
 174     // Timing Parameters for -7 (PC143) and CAS Latency = 3
 175     parameter tAC  =   6.5;    //test 6.5
 176     parameter tHZ  =   5.5;
 177     parameter tOH  =   2;
 178     parameter tMRD =   2.0;     // 2 Clk Cycles
 179     parameter tRAS =  48.0;
 180     parameter tRC  =  70.0;
 181     parameter tRCD =  20.0;
 182     parameter tRP  =  20.0;
 183     parameter tRRD =  14.0;
 184     parameter tWRa =   7.5;     // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns)
 185     parameter tWRp =  0.0;     // A2 Version - Precharge mode only (15 ns)
 186
 187     // Timing Check variable
 188     integer   MRD_chk;
 189     integer   WR_counter [0 : 3];
 190     time      WR_chk [0 : 3];
 191     time      RC_chk, RRD_chk;
 192     time      RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
 193     time      RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
 194     time      RP_chk0, RP_chk1, RP_chk2, RP_chk3;
 195
 196     integer    test_file;
 197
 198     //*****display the command of the sdram**************************************
 199
 200     parameter    Mode_Reg_Set    =4'b0000;
 201     parameter    Auto_Refresh    =4'b0001;
 202     parameter    Row_Active    =4'b0011;
 203     parameter    Pre_Charge    =4'b0010;
 204     parameter    PreCharge_All    =4'b0010;
 205     parameter    Write        =4'b0100;
 206     parameter    Write_Pre    =4'b0100;
 207     parameter    Read        =4'b0101;
 208     parameter    Read_Pre    =4'b0101;
 209     parameter    Burst_Stop    =4'b0110;
 210     parameter    Nop        =4'b0111;
 211     parameter    Dsel        =4'b1111;
 212
 213     wire    [3:0]    sdram_control;
 214     reg            cke_temp;
 215     reg        [8*13:1]    sdram_command;
 216
 217     always@(posedge Clk)
 218     cke_temp<=Cke;
 219
 220     assign    sdram_control={Cs_n,Ras_n,Cas_n,We_n};
 221
 222     always@(sdram_control or cke_temp)
 223     begin
 224         case(sdram_control)
 225             Mode_Reg_Set:    sdram_command<="Mode_Reg_Set";
 226             Auto_Refresh:    sdram_command<="Auto_Refresh";
 227             Row_Active:    sdram_command<="Row_Active";
 228             Pre_Charge:    sdram_command<="Pre_Charge";
 229             Burst_Stop:    sdram_command<="Burst_Stop";
 230             Dsel:        sdram_command<="Dsel";
 231
 232             Write:        if(cke_temp==1)
 233                         sdram_command<="Write";
 234                     else
 235                         sdram_command<="Write_suspend";
 236
 237             Read:        if(cke_temp==1)
 238                         sdram_command<="Read";
 239                     else
 240                         sdram_command<="Read_suspend";
 241
 242             Nop:        if(cke_temp==1)
 243                         sdram_command<="Nop";
 244                     else
 245                         sdram_command<="Self_refresh";
 246
 247             default:    sdram_command<="Power_down";
 248         endcase
 249     end
 250
 251     //*****************************************************
 252
 253     initial
 254         begin
 255         //test_file=$fopen("test_file.txt");
 256     end
 257
 258     initial
 259         begin
 260         Dq_reg = {data_bits{1'bz}};
 261         {Data_in_enable, Data_out_enable} = 0;
 262         {Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
 263         {Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
 264         {WR_chk[0], WR_chk[1], WR_chk[2], WR_chk[3]} = 0;
 265         {WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
 266         {RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
 267         {RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
 268         {MRD_chk, RC_chk, RRD_chk} = 0;
 269         {RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
 270         {RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
 271         {RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
 272         $timeformat (-9, 0, " ns", 12);
 273         //$readmemh("bank0.txt", Bank0);
 274         //$readmemh("bank1.txt", Bank1);
 275         //$readmemh("bank2.txt", Bank2);
 276         //$readmemh("bank3.txt", Bank3);
 277 /*
 278        for(dd=0;dd<=mem_sizes;dd=dd+1)
 279             begin
 280                 Bank0[dd]=dd[data_bits - 1 : 0];
 281                 Bank1[dd]=dd[data_bits - 1 : 0]+1;
 282                 Bank2[dd]=dd[data_bits - 1 : 0]+2;
 283                 Bank3[dd]=dd[data_bits - 1 : 0]+3;
 284             end
 285 */
 286       initial_sdram(0);
 287       end
 288
 289         task    initial_sdram;
 290
 291          input        data_sign;
 292          reg    [3:0]    data_sign;
 293
 294                for(dd=0;dd<=mem_sizes;dd=dd+1)
 295             begin
 296                 mem_d = {data_sign,data_sign,data_sign,data_sign,data_sign,data_sign,data_sign,data_sign};
 297                 if(data_bits==16)
 298                     begin
 299                         Bank0[dd]=mem_d[15:0];
 300                         Bank1[dd]=mem_d[15:0];
 301                         Bank2[dd]=mem_d[15:0];
 302                         Bank3[dd]=mem_d[15:0];
 303                     end
 304                 else if(data_bits==32)
 305                     begin
 306                         Bank0[dd]=mem_d[31:0];
 307                         Bank1[dd]=mem_d[31:0];
 308                         Bank2[dd]=mem_d[31:0];
 309                         Bank3[dd]=mem_d[31:0];
 310                     end
 311             end
 312
 313                endtask
 314
 315     // System clock generator
 316     always
 317         begin
 318                @(posedge Clk)
 319                    begin
 320                         Sys_clk = CkeZ;
 321                         CkeZ = Cke;
 322                 end
 323             @(negedge Clk)
 324                 begin
 325                         Sys_clk = 1'b0;
 326                 end
 327         end
 328
 329     always @ (posedge Sys_clk) begin
 330         // Internal Commamd Pipelined
 331         Command[0] = Command[1];
 332         Command[1] = Command[2];
 333         Command[2] = Command[3];
 334         Command[3] = `NOP;
 335
 336         Col_addr[0] = Col_addr[1];
 337         Col_addr[1] = Col_addr[2];
 338         Col_addr[2] = Col_addr[3];
 339         Col_addr[3] = {col_bits{1'b0}};
 340
 341         Bank_addr[0] = Bank_addr[1];
 342         Bank_addr[1] = Bank_addr[2];
 343         Bank_addr[2] = Bank_addr[3];
 344         Bank_addr[3] = 2'b0;
 345
 346         Bank_precharge[0] = Bank_precharge[1];
 347         Bank_precharge[1] = Bank_precharge[2];
 348         Bank_precharge[2] = Bank_precharge[3];
 349         Bank_precharge[3] = 2'b0;
 350
 351         A10_precharge[0] = A10_precharge[1];
 352         A10_precharge[1] = A10_precharge[2];
 353         A10_precharge[2] = A10_precharge[3];
 354         A10_precharge[3] = 1'b0;
 355
 356         // Dqm pipeline for Read
 357         Dqm_reg0 = Dqm_reg1;
 358         Dqm_reg1 = Dqm;
 359
 360         // Read or Write with Auto Precharge Counter
 361         if (Auto_precharge[0] == 1'b1) begin
 362             Count_precharge[0] = Count_precharge[0] + 1;
 363         end
 364         if (Auto_precharge[1] == 1'b1) begin
 365             Count_precharge[1] = Count_precharge[1] + 1;
 366         end
 367         if (Auto_precharge[2] == 1'b1) begin
 368             Count_precharge[2] = Count_precharge[2] + 1;
 369         end
 370         if (Auto_precharge[3] == 1'b1) begin
 371             Count_precharge[3] = Count_precharge[3] + 1;
 372         end
 373
 374         // tMRD Counter
 375         MRD_chk = MRD_chk + 1;
 376
 377         // tWR Counter for Write
 378         WR_counter[0] = WR_counter[0] + 1;
 379         WR_counter[1] = WR_counter[1] + 1;
 380         WR_counter[2] = WR_counter[2] + 1;
 381         WR_counter[3] = WR_counter[3] + 1;
 382
 383         // Auto Refresh
 384         if (Aref_enable == 1'b1) begin
 385             if (Debug) $display ("at time %t AREF : Auto Refresh", $time);
 386             // Auto Refresh to Auto Refresh
 387             if (($time - RC_chk < tRC)&&Debug) begin
 388                 $display ("at time %t ERROR: tRC violation during Auto Refresh", $time);
 389             end
 390             // Precharge to Auto Refresh
 391             if (($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP)&&Debug) begin
 392                 $display ("at time %t ERROR: tRP violation during Auto Refresh", $time);
 393             end
 394             // Precharge to Refresh
 395             if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
 396                 $display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
 397             end
 398             // Record Current tRC time
 399             RC_chk = $time;
 400         end
 401
 402         // Load Mode Register
 403         if (Mode_reg_enable == 1'b1) begin
 404             // Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
 405             if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
 406                 Mode_reg = Addr;
 407                 if (Debug) begin
 408                     $display ("at time %t LMR  : Load Mode Register", $time);
 409                     // CAS Latency
 410                     if (Addr[6 : 4] == 3'b010)
 411                         $display ("                            CAS Latency      = 2");
 412                     else if (Addr[6 : 4] == 3'b011)
 413                         $display ("                            CAS Latency      = 3");
 414                     else
 415                         $display ("                            CAS Latency      = Reserved");
 416                     // Burst Length
 417                     if (Addr[2 : 0] == 3'b000)
 418                         $display ("                            Burst Length     = 1");
 419                     else if (Addr[2 : 0] == 3'b001)
 420                         $display ("                            Burst Length     = 2");
 421                     else if (Addr[2 : 0] == 3'b010)
 422                         $display ("                            Burst Length     = 4");
 423                     else if (Addr[2 : 0] == 3'b011)
 424                         $display ("                            Burst Length     = 8");
 425                     else if (Addr[3 : 0] == 4'b0111)
 426                         $display ("                            Burst Length     = Full");
 427                     else
 428                         $display ("                            Burst Length     = Reserved");
 429                     // Burst Type
 430                     if (Addr[3] == 1'b0)
 431                         $display ("                            Burst Type       = Sequential");
 432                     else if (Addr[3] == 1'b1)
 433                         $display ("                            Burst Type       = Interleaved");
 434                     else
 435                         $display ("                            Burst Type       = Reserved");
 436                     // Write Burst Mode
 437                     if (Addr[9] == 1'b0)
 438                         $display ("                            Write Burst Mode = Programmed Burst Length");
 439                     else if (Addr[9] == 1'b1)
 440                         $display ("                            Write Burst Mode = Single Location Access");
 441                     else
 442                         $display ("                            Write Burst Mode = Reserved");
 443                 end
 444             end else begin
 445                 $display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
 446             end
 447             // REF to LMR
 448             if ($time - RC_chk < tRC) begin
 449                 $display ("at time %t ERROR: tRC violation during Load Mode Register", $time);
 450             end
 451             // LMR to LMR
 452             if (MRD_chk < tMRD) begin
 453                 $display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);
 454             end
 455             MRD_chk = 0;
 456         end
 457
 458         // Active Block (Latch Bank Address and Row Address)
 459         if (Active_enable == 1'b1) begin
 460             if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
 461                 {Act_b0, Pc_b0} = 2'b10;
 462                 B0_row_addr = Addr [addr_bits - 1 : 0];
 463                 RCD_chk0 = $time;
 464                 RAS_chk0 = $time;
 465                 if (Debug) $display ("at time %t ACT  : Bank = 0 Row = %d", $time, Addr);
 466                 // Precharge to Activate Bank 0
 467                 if ($time - RP_chk0 < tRP) begin
 468                     $display ("at time %t ERROR: tRP violation during Activate bank 0", $time);
 469                 end
 470             end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
 471                 {Act_b1, Pc_b1} = 2'b10;
 472                 B1_row_addr = Addr [addr_bits - 1 : 0];
 473                 RCD_chk1 = $time;
 474                 RAS_chk1 = $time;
 475                 if (Debug) $display ("at time %t ACT  : Bank = 1 Row = %d", $time, Addr);
 476                 // Precharge to Activate Bank 1
 477                 if ($time - RP_chk1 < tRP) begin
 478                     $display ("at time %t ERROR: tRP violation during Activate bank 1", $time);
 479                 end
 480             end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
 481                 {Act_b2, Pc_b2} = 2'b10;
 482                 B2_row_addr = Addr [addr_bits - 1 : 0];
 483                 RCD_chk2 = $time;
 484                 RAS_chk2 = $time;
 485                 if (Debug) $display ("at time %t ACT  : Bank = 2 Row = %d", $time, Addr);
 486                 // Precharge to Activate Bank 2
 487                 if ($time - RP_chk2 < tRP) begin
 488                     $display ("at time %t ERROR: tRP violation during Activate bank 2", $time);
 489                 end
 490             end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
 491                 {Act_b3, Pc_b3} = 2'b10;
 492                 B3_row_addr = Addr [addr_bits - 1 : 0];
 493                 RCD_chk3 = $time;
 494                 RAS_chk3 = $time;
 495                 if (Debug) $display ("at time %t ACT  : Bank = 3 Row = %d", $time, Addr);
 496                 // Precharge to Activate Bank 3
 497                 if ($time - RP_chk3 < tRP) begin
 498                     $display ("at time %t ERROR: tRP violation during Activate bank 3", $time);
 499                 end
 500             end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
 501                 $display ("at time %t ERROR: Bank 0 is not Precharged.", $time);
 502             end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
 503                 $display ("at time %t ERROR: Bank 1 is not Precharged.", $time);
 504             end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
 505                 $display ("at time %t ERROR: Bank 2 is not Precharged.", $time);
 506             end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
 507                 $display ("at time %t ERROR: Bank 3 is not Precharged.", $time);
 508             end
 509             // Active Bank A to Active Bank B
 510             if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
 511                 $display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
 512             end
 513             // Load Mode Register to Active
 514             if (MRD_chk < tMRD ) begin
 515                 $display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
 516             end
 517             // Auto Refresh to Activate
 518             if (($time - RC_chk < tRC)&&Debug) begin
 519                 $display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
 520             end
 521             // Record variables for checking violation
 522             RRD_chk = $time;
 523             Previous_bank = Ba;
 524         end
 525
 526         // Precharge Block
 527         if (Prech_enable == 1'b1) begin
 528             if (Addr[10] == 1'b1) begin
 529                 {Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
 530                 {Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
 531                 RP_chk0 = $time;
 532                 RP_chk1 = $time;
 533                 RP_chk2 = $time;
 534                 RP_chk3 = $time;
 535                 if (Debug) $display ("at time %t PRE  : Bank = ALL",$time);
 536                 // Activate to Precharge all banks
 537                 if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
 538                     ($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
 539                     $display ("at time %t ERROR: tRAS violation during Precharge all bank", $time);
 540                 end
 541                 // tWR violation check for write
 542                 if (($time - WR_chk[0] < tWRp) || ($time - WR_chk[1] < tWRp) ||
 543                     ($time - WR_chk[2] < tWRp) || ($time - WR_chk[3] < tWRp)) begin
 544                     $display ("at time %t ERROR: tWR violation during Precharge all bank", $time);
 545                 end
 546             end else if (Addr[10] == 1'b0) begin
 547                 if (Ba == 2'b00) begin
 548                     {Pc_b0, Act_b0} = 2'b10;
 549                     RP_chk0 = $time;
 550                     if (Debug) $display ("at time %t PRE  : Bank = 0",$time);
 551                     // Activate to Precharge Bank 0
 552                     if ($time - RAS_chk0 < tRAS) begin
 553                         $display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time);
 554                     end
 555                 end else if (Ba == 2'b01) begin
 556                     {Pc_b1, Act_b1} = 2'b10;
 557                     RP_chk1 = $time;
 558                     if (Debug) $display ("at time %t PRE  : Bank = 1",$time);
 559                     // Activate to Precharge Bank 1
 560                     if ($time - RAS_chk1 < tRAS) begin
 561                         $display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time);
 562                     end
 563                 end else if (Ba == 2'b10) begin
 564                     {Pc_b2, Act_b2} = 2'b10;
 565                     RP_chk2 = $time;
 566                     if (Debug) $display ("at time %t PRE  : Bank = 2",$time);
 567                     // Activate to Precharge Bank 2
 568                     if ($time - RAS_chk2 < tRAS) begin
 569                         $display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time);
 570                     end
 571                 end else if (Ba == 2'b11) begin
 572                     {Pc_b3, Act_b3} = 2'b10;
 573                     RP_chk3 = $time;
 574                     if (Debug) $display ("at time %t PRE  : Bank = 3",$time);
 575                     // Activate to Precharge Bank 3
 576                     if ($time - RAS_chk3 < tRAS) begin
 577                         $display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);
 578                     end
 579                 end
 580                 // tWR violation check for write
 581                 if ($time - WR_chk[Ba] < tWRp) begin
 582                     $display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
 583                 end
 584             end
 585             // Terminate a Write Immediately (if same bank or all banks)
 586             if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
 587                 Data_in_enable = 1'b0;
 588             end
 589             // Precharge Command Pipeline for Read
 590             if (Cas_latency_3 == 1'b1) begin
 591                 Command[2] = `PRECH;
 592                 Bank_precharge[2] = Ba;
 593                 A10_precharge[2] = Addr[10];
 594             end else if (Cas_latency_2 == 1'b1) begin
 595                 Command[1] = `PRECH;
 596                 Bank_precharge[1] = Ba;
 597                 A10_precharge[1] = Addr[10];
 598             end
 599         end
 600
 601         // Burst terminate
 602         if (Burst_term == 1'b1) begin
 603             // Terminate a Write Immediately
 604             if (Data_in_enable == 1'b1) begin
 605                 Data_in_enable = 1'b0;
 606             end
 607             // Terminate a Read Depend on CAS Latency
 608             if (Cas_latency_3 == 1'b1) begin
 609                 Command[2] = `BST;
 610             end else if (Cas_latency_2 == 1'b1) begin
 611                 Command[1] = `BST;
 612             end
 613             if (Debug) $display ("at time %t BST  : Burst Terminate",$time);
 614         end
 615
 616         // Read, Write, Column Latch
 617         if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
 618             // Check to see if bank is open (ACT)
 619             if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
 620                 (Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
 621                 $display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
 622             end
 623             // Activate to Read or Write
 624             if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
 625                 $display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
 626             if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
 627                 $display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
 628             if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
 629                 $display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
 630             if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
 631                 $display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
 632             // Read Command
 633             if (Read_enable == 1'b1) begin
 634                 // CAS Latency pipeline
 635                 if (Cas_latency_3 == 1'b1) begin
 636                     if (Addr[10] == 1'b1) begin
 637                         Command[2] = `READ_A;
 638                     end else begin
 639                         Command[2] = `READ;
 640                     end
 641                     Col_addr[2] = Addr;
 642                     Bank_addr[2] = Ba;
 643                 end else if (Cas_latency_2 == 1'b1) begin
 644                     if (Addr[10] == 1'b1) begin
 645                         Command[1] = `READ_A;
 646                     end else begin
 647                         Command[1] = `READ;
 648                     end
 649                     Col_addr[1] = Addr;
 650                     Bank_addr[1] = Ba;
 651                 end
 652
 653                 // Read interrupt Write (terminate Write immediately)
 654                 if (Data_in_enable == 1'b1) begin
 655                     Data_in_enable = 1'b0;
 656                 end
 657
 658             // Write Command
 659             end else if (Write_enable == 1'b1) begin
 660                 if (Addr[10] == 1'b1) begin
 661                     Command[0] = `WRITE_A;
 662                 end else begin
 663                     Command[0] = `WRITE;
 664                 end
 665                 Col_addr[0] = Addr;
 666                 Bank_addr[0] = Ba;
 667
 668                 // Write interrupt Write (terminate Write immediately)
 669                 if (Data_in_enable == 1'b1) begin
 670                     Data_in_enable = 1'b0;
 671                 end
 672
 673                 // Write interrupt Read (terminate Read immediately)
 674                 if (Data_out_enable == 1'b1) begin
 675                     Data_out_enable = 1'b0;
 676                 end
 677             end
 678
 679             // Interrupting a Write with Autoprecharge
 680             if (Auto_precharge[Bank] == 1'b1 && Write_precharge[Bank] == 1'b1) begin
 681                 RW_interrupt_write[Bank] = 1'b1;
 682                 if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, Bank);
 683             end
 684
 685             // Interrupting a Read with Autoprecharge
 686             if (Auto_precharge[Bank] == 1'b1 && Read_precharge[Bank] == 1'b1) begin
 687                 RW_interrupt_read[Bank] = 1'b1;
 688                 if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, Bank);
 689             end
 690
 691             // Read or Write with Auto Precharge
 692             if (Addr[10] == 1'b1) begin
 693                 Auto_precharge[Ba] = 1'b1;
 694                 Count_precharge[Ba] = 0;
 695                 if (Read_enable == 1'b1) begin
 696                     Read_precharge[Ba] = 1'b1;
 697                 end else if (Write_enable == 1'b1) begin
 698                     Write_precharge[Ba] = 1'b1;
 699                 end
 700             end
 701         end
 702
 703         //  Read with Auto Precharge Calculation
 704         //      The device start internal precharge:
 705         //          1.  CAS Latency - 1 cycles before last burst
 706         //      and 2.  Meet minimum tRAS requirement
 707         //       or 3.  Interrupt by a Read or Write (with or without AutoPrecharge)
 708         if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
 709             if ((($time - RAS_chk0 >= tRAS) &&                                                      // Case 2
 710                 ((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) ||                             // Case 1
 711                  (Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
 712                  (Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
 713                  (Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
 714                  (RW_interrupt_read[0] == 1'b1)) begin                                              // Case 3
 715                     Pc_b0 = 1'b1;
 716                     Act_b0 = 1'b0;
 717                     RP_chk0 = $time;
 718                     Auto_precharge[0] = 1'b0;
 719                     Read_precharge[0] = 1'b0;
 720                     RW_interrupt_read[0] = 1'b0;
 721                     if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
 722             end
 723         end
 724         if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
 725             if ((($time - RAS_chk1 >= tRAS) &&
 726                 ((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
 727                  (Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
 728                  (Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
 729                  (Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
 730                  (RW_interrupt_read[1] == 1'b1)) begin
 731                     Pc_b1 = 1'b1;
 732                     Act_b1 = 1'b0;
 733                     RP_chk1 = $time;
 734                     Auto_precharge[1] = 1'b0;
 735                     Read_precharge[1] = 1'b0;
 736                     RW_interrupt_read[1] = 1'b0;
 737                     if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
 738             end
 739         end
 740         if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
 741             if ((($time - RAS_chk2 >= tRAS) &&
 742                 ((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
 743                  (Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
 744                  (Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
 745                  (Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
 746                  (RW_interrupt_read[2] == 1'b1)) begin
 747                     Pc_b2 = 1'b1;
 748                     Act_b2 = 1'b0;
 749                     RP_chk2 = $time;
 750                     Auto_precharge[2] = 1'b0;
 751                     Read_precharge[2] = 1'b0;
 752                     RW_interrupt_read[2] = 1'b0;
 753                     if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
 754             end
 755         end
 756         if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
 757             if ((($time - RAS_chk3 >= tRAS) &&
 758                 ((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
 759                  (Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
 760                  (Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
 761                  (Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
 762                  (RW_interrupt_read[3] == 1'b1)) begin
 763                     Pc_b3 = 1'b1;
 764                     Act_b3 = 1'b0;
 765                     RP_chk3 = $time;
 766                     Auto_precharge[3] = 1'b0;
 767                     Read_precharge[3] = 1'b0;
 768                     RW_interrupt_read[3] = 1'b0;
 769                     if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
 770             end
 771         end
 772
 773         // Internal Precharge or Bst
 774         if (Command[0] == `PRECH) begin                         // Precharge terminate a read with same bank or all banks
 775             if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin
 776                 if (Data_out_enable == 1'b1) begin
 777                     Data_out_enable = 1'b0;
 778                 end
 779             end
 780         end else if (Command[0] == `BST) begin                  // BST terminate a read to current bank
 781             if (Data_out_enable == 1'b1) begin
 782                 Data_out_enable = 1'b0;
 783             end
 784         end
 785
 786         if (Data_out_enable == 1'b0) begin
 787             Dq_reg <= #tOH {data_bits{1'bz}};
 788         end
 789
 790         // Detect Read or Write command
 791         if (Command[0] == `READ || Command[0] == `READ_A) begin
 792             Bank = Bank_addr[0];
 793             Col = Col_addr[0];
 794             Col_brst = Col_addr[0];
 795             if (Bank_addr[0] == 2'b00) begin
 796                 Row = B0_row_addr;
 797             end else if (Bank_addr[0] == 2'b01) begin
 798                 Row = B1_row_addr;
 799             end else if (Bank_addr[0] == 2'b10) begin
 800                 Row = B2_row_addr;
 801             end else if (Bank_addr[0] == 2'b11) begin
 802                 Row = B3_row_addr;
 803             end
 804             Burst_counter = 0;
 805             Data_in_enable = 1'b0;
 806             Data_out_enable = 1'b1;
 807         end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin
 808             Bank = Bank_addr[0];
 809             Col = Col_addr[0];
 810             Col_brst = Col_addr[0];
 811             if (Bank_addr[0] == 2'b00) begin
 812                 Row = B0_row_addr;
 813             end else if (Bank_addr[0] == 2'b01) begin
 814                 Row = B1_row_addr;
 815             end else if (Bank_addr[0] == 2'b10) begin
 816                 Row = B2_row_addr;
 817             end else if (Bank_addr[0] == 2'b11) begin
 818                 Row = B3_row_addr;
 819             end
 820             Burst_counter = 0;
 821             Data_in_enable = 1'b1;
 822             Data_out_enable = 1'b0;
 823         end
 824
 825         // DQ buffer (Driver/Receiver)
 826         if (Data_in_enable == 1'b1) begin                                   // Writing Data to Memory
 827             // Array buffer
 828             if (Bank == 2'b00) Dq_dqm [data_bits - 1  : 0] = Bank0 [{Row, Col}];
 829             if (Bank == 2'b01) Dq_dqm [data_bits - 1  : 0] = Bank1 [{Row, Col}];
 830             if (Bank == 2'b10) Dq_dqm [data_bits - 1  : 0] = Bank2 [{Row, Col}];
 831             if (Bank == 2'b11) Dq_dqm [data_bits - 1  : 0] = Bank3 [{Row, Col}];
 832             // Dqm operation
 833             if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0];
 834             if (Dqm[1] == 1'b0) Dq_dqm [15 : 8] = Dq [15 : 8];
 835             //if (Dqm[2] == 1'b0) Dq_dqm [23 : 16] = Dq [23 : 16];
 836            // if (Dqm[3] == 1'b0) Dq_dqm [31 : 24] = Dq [31 : 24];
 837             // Write to memory
 838             if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm [data_bits - 1  : 0];
 839             if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm [data_bits - 1  : 0];
 840             if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm [data_bits - 1  : 0];
 841             if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm [data_bits - 1  : 0];
 842             if (Bank == 2'b11 && Row==10'h3 && Col[7:4]==4'h4)
 843                 $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
 844             //$fdisplay(test_file,"bank:%h    row:%h    col:%h    write:%h",Bank,Row,Col,Dq_dqm);
 845             // Output result
 846             if (Dqm == 4'b1111) begin
 847                 if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
 848             end else begin
 849                 if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm);
 850                 // Record tWR time and reset counter
 851                 WR_chk [Bank] = $time;
 852                 WR_counter [Bank] = 0;
 853             end
 854             // Advance burst counter subroutine
 855             #tHZ Burst;
 856         end else if (Data_out_enable == 1'b1) begin                         // Reading Data from Memory
 857             //$display("%h    ,    %h,    %h",Bank0,Row,Col);
 858             // Array buffer
 859             if (Bank == 2'b00) Dq_dqm [data_bits - 1  : 0] = Bank0 [{Row, Col}];
 860             if (Bank == 2'b01) Dq_dqm [data_bits - 1  : 0] = Bank1 [{Row, Col}];
 861             if (Bank == 2'b10) Dq_dqm [data_bits - 1  : 0] = Bank2 [{Row, Col}];
 862             if (Bank == 2'b11) Dq_dqm [data_bits - 1  : 0] = Bank3 [{Row, Col}];
 863
 864             // Dqm operation
 865             if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz;
 866             if (Dqm_reg0[1] == 1'b1) Dq_dqm [15 : 8] = 8'bz;
 867             if (Dqm_reg0[2] == 1'b1) Dq_dqm [23 : 16] = 8'bz;
 868             if (Dqm_reg0[3] == 1'b1) Dq_dqm [31 : 24] = 8'bz;
 869             // Display result
 870             Dq_reg [data_bits - 1  : 0] = #tAC Dq_dqm [data_bits - 1  : 0];
 871             if (Dqm_reg0 == 4'b1111) begin
 872                 if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
 873             end else begin
 874                 if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0);
 875             end
 876             // Advance burst counter subroutine
 877             Burst;
 878         end
 879     end
 880
 881     //  Write with Auto Precharge Calculation
 882     //      The device start internal precharge:
 883     //          1.  tWR Clock after last burst
 884     //      and 2.  Meet minimum tRAS requirement
 885     //       or 3.  Interrupt by a Read or Write (with or without AutoPrecharge)
 886     always @ (WR_counter[0]) begin
 887         if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
 888             if ((($time - RAS_chk0 >= tRAS) &&                                                          // Case 2
 889                (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1) ||   // Case 1
 890                  (Burst_length_2 == 1'b1 && Count_precharge [0] >= 2) ||
 891                  (Burst_length_4 == 1'b1 && Count_precharge [0] >= 4) ||
 892                  (Burst_length_8 == 1'b1 && Count_precharge [0] >= 8))) ||
 893                  (RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 2)) begin                           // Case 3 (stop count when interrupt)
 894                     Auto_precharge[0] = 1'b0;
 895                     Write_precharge[0] = 1'b0;
 896                     RW_interrupt_write[0] = 1'b0;
 897                     #tWRa;                          // Wait for tWR
 898                     Pc_b0 = 1'b1;
 899                     Act_b0 = 1'b0;
 900                     RP_chk0 = $time;
 901                     if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
 902             end
 903         end
 904     end
 905     always @ (WR_counter[1]) begin
 906         if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
 907             if ((($time - RAS_chk1 >= tRAS) &&
 908                (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1) ||
 909                  (Burst_length_2 == 1'b1 && Count_precharge [1] >= 2) ||
 910                  (Burst_length_4 == 1'b1 && Count_precharge [1] >= 4) ||
 911                  (Burst_length_8 == 1'b1 && Count_precharge [1] >= 8))) ||
 912                  (RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 2)) begin
 913                     Auto_precharge[1] = 1'b0;
 914                     Write_precharge[1] = 1'b0;
 915                     RW_interrupt_write[1] = 1'b0;
 916                     #tWRa;                          // Wait for tWR
 917                     Pc_b1 = 1'b1;
 918                     Act_b1 = 1'b0;
 919                     RP_chk1 = $time;
 920                     if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
 921             end
 922         end
 923     end
 924     always @ (WR_counter[2]) begin
 925         if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
 926             if ((($time - RAS_chk2 >= tRAS) &&
 927                (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1) ||
 928                  (Burst_length_2 == 1'b1 && Count_precharge [2] >= 2) ||
 929                  (Burst_length_4 == 1'b1 && Count_precharge [2] >= 4) ||
 930                  (Burst_length_8 == 1'b1 && Count_precharge [2] >= 8))) ||
 931                  (RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 2)) begin
 932                     Auto_precharge[2] = 1'b0;
 933                     Write_precharge[2] = 1'b0;
 934                     RW_interrupt_write[2] = 1'b0;
 935                     #tWRa;                          // Wait for tWR
 936                     Pc_b2 = 1'b1;
 937                     Act_b2 = 1'b0;
 938                     RP_chk2 = $time;
 939                     if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
 940             end
 941         end
 942     end
 943     always @ (WR_counter[3]) begin
 944         if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
 945             if ((($time - RAS_chk3 >= tRAS) &&
 946                (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1) ||
 947                  (Burst_length_2 == 1'b1 && Count_precharge [3] >= 2) ||
 948                  (Burst_length_4 == 1'b1 && Count_precharge [3] >= 4) ||
 949                  (Burst_length_8 == 1'b1 && Count_precharge [3] >= 8))) ||
 950                  (RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 2)) begin
 951                     Auto_precharge[3] = 1'b0;
 952                     Write_precharge[3] = 1'b0;
 953                     RW_interrupt_write[3] = 1'b0;
 954                     #tWRa;                          // Wait for tWR
 955                     Pc_b3 = 1'b1;
 956                     Act_b3 = 1'b0;
 957                     RP_chk3 = $time;
 958                     if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
 959             end
 960         end
 961     end
 962
 963     task Burst;
 964         begin
 965             // Advance Burst Counter
 966             Burst_counter = Burst_counter + 1;
 967
 968             // Burst Type
 969             if (Mode_reg[3] == 1'b0) begin                                  // Sequential Burst
 970                 Col_temp = Col + 1;
 971             end else if (Mode_reg[3] == 1'b1) begin                         // Interleaved Burst
 972                 Col_temp[2] =  Burst_counter[2] ^  Col_brst[2];
 973                 Col_temp[1] =  Burst_counter[1] ^  Col_brst[1];
 974                 Col_temp[0] =  Burst_counter[0] ^  Col_brst[0];
 975             end
 976
 977             // Burst Length
 978             if (Burst_length_2) begin                                       // Burst Length = 2
 979                 Col [0] = Col_temp [0];
 980             end else if (Burst_length_4) begin                              // Burst Length = 4
 981                 Col [1 : 0] = Col_temp [1 : 0];
 982             end else if (Burst_length_8) begin                              // Burst Length = 8
 983                 Col [2 : 0] = Col_temp [2 : 0];
 984             end else begin                                                  // Burst Length = FULL
 985                 Col = Col_temp;
 986             end
 987
 988             // Burst Read Single Write
 989             if (Write_burst_mode == 1'b1) begin
 990                 Data_in_enable = 1'b0;
 991             end
 992
 993             // Data Counter
 994             if (Burst_length_1 == 1'b1) begin
 995                 if (Burst_counter >= 1) begin
 996                     Data_in_enable = 1'b0;
 997                     Data_out_enable = 1'b0;
 998                 end
 999             end else if (Burst_length_2 == 1'b1) begin
1000                 if (Burst_counter >= 2) begin
1001                     Data_in_enable = 1'b0;
1002                     Data_out_enable = 1'b0;
1003                 end
1004             end else if (Burst_length_4 == 1'b1) begin
1005                 if (Burst_counter >= 4) begin
1006                     Data_in_enable = 1'b0;
1007                     Data_out_enable = 1'b0;
1008                 end
1009             end else if (Burst_length_8 == 1'b1) begin
1010                 if (Burst_counter >= 8) begin
1011                     Data_in_enable = 1'b0;
1012                     Data_out_enable = 1'b0;
1013                 end
1014             end
1015         end
1016     endtask
1017
1018     //**********************将SDRAM内的数据直接输出到外部文件*******************************//
1019
1020 /*
1021    integer    sdram_data,ind;
1022
1023
1024     always@(sdram_r)
1025     begin
1026            sdram_data=$fopen("sdram_data.txt");
1027            $display("Sdram dampout begin ",sdram_data);
1028 //           $fdisplay(sdram_data,"Bank0:");
1029            for(ind=0;ind<=mem_sizes;ind=ind+1)
1030                     $fdisplay(sdram_data,"%h    %b",ind,Bank0[ind]);
1031 //           $fdisplay(sdram_data,"Bank1:");
1032            for(ind=0;ind<=mem_sizes;ind=ind+1)
1033                     $fdisplay(sdram_data,"%h    %b",ind,Bank1[ind]);
1034 //           $fdisplay(sdram_data,"Bank2:");
1035            for(ind=0;ind<=mem_sizes;ind=ind+1)
1036                     $fdisplay(sdram_data,"%h    %b",ind,Bank2[ind]);
1037 //               $fdisplay(sdram_data,"Bank3:");
1038            for(ind=0;ind<=mem_sizes;ind=ind+1)
1039                     $fdisplay(sdram_data,"%h    %b",ind,Bank3[ind]);
1040
1041           $fclose("sdram_data.txt");
1042       //->compare;
1043       end
1044 */
1045     integer    sdram_data,sdram_mem;
1046     reg    [24:0]    aa,cc;
1047     reg    [24:0]    bb,ee;
1048
1049     always@(sdram_r)
1050     begin
1051            $display("Sdram dampout begin ",$realtime);
1052            sdram_data=$fopen("sdram_data.txt");
1053            for(aa=0;aa<4*(mem_sizes+1);aa=aa+1)
1054                begin
1055                bb=aa[18:0];
1056             if(aa<=mem_sizes)
1057                 $fdisplay(sdram_data,"%0d    %0h",aa,Bank0[bb]);
1058             else if(aa<=2*mem_sizes+1)
1059                         $fdisplay(sdram_data,"%0d    %0h",aa,Bank1[bb]);
1060             else if(aa<=3*mem_sizes+2)
1061                 $fdisplay(sdram_data,"%0d    %0h",aa,Bank2[bb]);
1062             else
1063                 $fdisplay(sdram_data,"%0d    %0h",aa,Bank3[bb]);
1064               end
1065           $fclose("sdram_data.txt");
1066
1067           sdram_mem=$fopen("sdram_mem.txt");
1068           for(cc=0;cc<4*(mem_sizes+1);cc=cc+1)
1069               begin
1070                ee=cc[18:0];
1071             if(cc<=mem_sizes)
1072                 $fdisplay(sdram_mem,"%0h",Bank0[ee]);
1073             else if(cc<=2*mem_sizes+1)
1074                         $fdisplay(sdram_mem,"%0h",Bank1[ee]);
1075             else if(cc<=3*mem_sizes+2)
1076                 $fdisplay(sdram_mem,"%0h",Bank2[ee]);
1077             else
1078                 $fdisplay(sdram_mem,"%0h",Bank3[ee]);
1079               end
1080           $fclose("sdram_mem.txt");
1081
1082       end
1083
1084
1085
1086 //    // Timing Parameters for -75 (PC133) and CAS Latency = 2
1087 //    specify
1088 //        specparam
1089 ////                    tAH  =  0.8,                                        // Addr, Ba Hold Time
1090 ////                    tAS  =  1.5,                                        // Addr, Ba Setup Time
1091 ////                    tCH  =  2.5,                                        // Clock High-Level Width
1092 ////                    tCL  =  2.5,                                        // Clock Low-Level Width
1093 //                    tCK  = 10.0,                                       // Clock Cycle Time  100mhz
1094 //                    tCK  = 7.5,                        // Clock Cycle Time  133mhz
1095 ////                    tCK  =  7,                                // Clock Cycle Time  143mhz
1096 ////                    tDH  =  0.8,                                        // Data-in Hold Time
1097 ////                    tDS  =  1.5,                                        // Data-in Setup Time
1098 ////                    tCKH =  0.8,                                        // CKE Hold  Time
1099 ////                    tCKS =  1.5,                                        // CKE Setup Time
1100 ////                    tCMH =  0.8,                                        // CS#, RAS#, CAS#, WE#, DQM# Hold  Time
1101 ////                    tCMS =  1.5;                                        // CS#, RAS#, CAS#, WE#, DQM# Setup Time
1102 //                    tAH  =  1,                                        // Addr, Ba Hold Time
1103 //                    tAS  =  1.5,                                        // Addr, Ba Setup Time
1104 //                    tCH  =  1,                                        // Clock High-Level Width
1105 //                    tCL  =  3,                                        // Clock Low-Level Width
1106 ////                    tCK  = 10.0,                                       // Clock Cycle Time  100mhz
1107 ////                    tCK  = 7.5,                        // Clock Cycle Time  133mhz
1108 //                    tCK  =  7,                                // Clock Cycle Time  143mhz
1109 //                    tDH  =  1,                                        // Data-in Hold Time
1110 //                    tDS  =  2,                                        // Data-in Setup Time
1111 //                    tCKH =  1,                                        // CKE Hold  Time
1112 //                    tCKS =  2,                                        // CKE Setup Time
1113 //                    tCMH =  0.8,                                        // CS#, RAS#, CAS#, WE#, DQM# Hold  Time
1114 //                    tCMS =  1.5;                                        // CS#, RAS#, CAS#, WE#, DQM# Setup Time
1115 //        $width    (posedge Clk,           tCH);
1116 //        $width    (negedge Clk,           tCL);
1117 //        $period   (negedge Clk,           tCK);
1118 //        $period   (posedge Clk,           tCK);
1119 //        $setuphold(posedge Clk,    Cke,   tCKS, tCKH);
1120 //        $setuphold(posedge Clk,    Cs_n,  tCMS, tCMH);
1121 //        $setuphold(posedge Clk,    Cas_n, tCMS, tCMH);
1122 //        $setuphold(posedge Clk,    Ras_n, tCMS, tCMH);
1123 //        $setuphold(posedge Clk,    We_n,  tCMS, tCMH);
1124 //        $setuphold(posedge Clk,    Addr,  tAS,  tAH);
1125 //        $setuphold(posedge Clk,    Ba,    tAS,  tAH);
1126 //        $setuphold(posedge Clk,    Dqm,   tCMS, tCMH);
1127 //        $setuphold(posedge Dq_chk, Dq,    tDS,  tDH);
1128 //    endspecify
1129
1130 endmodule

sdram_model_plus

7.最后附上仿真结果

打印信息,简单明了,这是我喜欢的风格

再来看看波形吧

完美,忙活了一天有些坑真的自己填,因为每填完一个坑,起身更强大,明天继续

2018/730

今天继续更新,有很多事耽搁了两天

二.仲裁机制和刷新操作

1.刷新操作是sdram必须的操作,使用不当数据指定丢失,具体为什么自己去查一下,我省的废话了。

既然是刷新,那么就应该有刷新的周期,这个怎么计算呢,打开datasheet,看图。红框意思是64ms内要进行8192次刷新,那么刷新周期大约7.8us

2.该刷新时序以及命令了

看下面的时序图等初始化完成后,刷新操作的第一步就是预充电(precharge),然后等tRP时间进行auto refresh(自刷新),后面再一次刷新和active都不用进行。前面哪个时间自己对应手册查一下,一般不会有错

这儿提一下,在预充电的时候,地址引脚要同时进行操作,A0~A9、A11、A12不用管,只对A10进行操作,如果A10位1,就是对所有bank进行充电,为0时选择bank进行充电,我们是为1。

3.刷新就说完了,该附上源代码了

 1 module sdram_aref(
 2         //system signals
 3         input                    sclk            ,
 4         input                    s_rst_n            ,
 5         //comunicat with ARBIT
 6         input                    ref_en            ,
 7         output    wire            ref_req            ,
 8         output    wire            flag_ref_end    ,
 9         //others
10         output    reg     [3:0]    aref_cmd        ,
11         output    wire    [12:0]    sdram_addr        ,
12         input                    flag_init_end
13 );
14
15 //==============================================================================\
16 //*********************Define Parameter and Internal Signal ********************
17 //==============================================================================/
18 localparam        DELAY_78us        =        390        ;
19 localparam        CMD_AREF        =        4'b0001    ;
20 localparam        CMD_NOP            =        4'b0111    ;
21 localparam        CMD_PRE            =        4'b0010    ;
22 reg        [3:0]            cmd_cnt                    ;
23 reg        [8:0]            ref_cnt                    ;
24 reg                        flag_ref                ;
25
26 //=============================================================================\
27 //********************** Main Code    ***************************************
28 //=============================================================================/
29 always @(posedge sclk or negedge s_rst_n) begin
30         if(s_rst_n == 1'b0)
31                 ref_cnt <= 9'd0;
32         else if(ref_cnt >= DELAY_78us)
33                 ref_cnt <= 9'd0;
34         else if(flag_init_end == 1'b1)
35                 ref_cnt <= ref_cnt +1'b1;
36 end
37
38 always @(posedge sclk or negedge s_rst_n) begin
39         if(s_rst_n == 1'b0)
40                 flag_ref <= 1'b0;
41         else if(flag_ref_end == 1'b1)
42                 flag_ref <=    1'b0;
43         else if(ref_en == 1'b1)
44                 flag_ref <= 1'b1;
45 end
46
47 always @(posedge sclk or negedge s_rst_n ) begin
48         if(s_rst_n == 1'b0)
49                 cmd_cnt    <= 4'd0;
50         else if(flag_ref == 1'b1)
51                 cmd_cnt <= cmd_cnt + 1'b1;
52         else
53                 cmd_cnt <= 4'd0;
54 end
55
56
57 always @(posedge sclk or negedge s_rst_n) begin
58         if(s_rst_n == 1'b0)
59                 aref_cmd <= CMD_NOP;
60         else case(cmd_cnt)
61                 1:        aref_cmd <= CMD_PRE;
62                 2:        aref_cmd <= CMD_AREF;
63                 default:aref_cmd <= CMD_NOP;
64         endcase
65 end
66
67 assign  flag_ref_end = (cmd_cnt >= 4'd3) ? 1'b1 : 1'b0;
68 assign    sdram_addr    =    13'd0_0100_0000_0000;
69 assign    ref_req        =    (ref_cnt >= DELAY_78us)    ?    1'b1 : 1'b0;
70
71
72
73 endmodule

sdram_aref

4.仲裁机制

为什么要这个仲裁机制,sdram工作是有刷新、写和读3个操作,我们需要这个仲裁机制来协调这三个操作,引用邓堪文老师一个图,大家一看就应该很明白了

5.具体的操作在sdram_top模块里,附上源码自己研究一下,这只写了三种状态,其他状态后面学习了在更新

  1 module sdram_top(
  2         //system signals
  3         input                    sclk            ,
  4         input                    s_rst_n            ,
  5         //SDRAM Interfaces
  6         output    wire            sdram_clk        ,
  7         output    wire            sdram_cke        ,
  8         output    wire            sdram_cs_n        ,
  9         output    wire            sdram_cas_n        ,
 10         output    wire            sdram_ras_n        ,
 11         output    wire            sdram_we_n        ,
 12         output    wire    [1:0]    sdram_bank        ,
 13         output    wire    [12:0]    sdram_addr        ,
 14         output    wire    [1:0]    sdram_dqm        ,
 15         inout            [15:0]    sdram_dq
 16 );
 17
 18 //==============================================================================\
 19 //*********************Define Parameter and Internal Signal ********************
 20 //==============================================================================/
 21 localparam        IDLE        =    5'b0_0001        ;
 22 localparam        ARBIT        =    5'b0_0010        ;
 23 localparam        AREF        =    5'b0_0100        ;
 24
 25 //init module
 26 wire                    flag_init_end            ;
 27 wire    [3:0]            init_cmd                ;
 28 wire    [12:0]            init_addr                ;
 29 //
 30 reg        [4:0]            state                    ;
 31 //refresh module
 32 wire                    ref_req                    ;
 33 wire                    flag_ref_end            ;
 34 reg                        ref_en                    ;
 35 wire    [3:0]            ref_cmd                    ;
 36 wire    [12:0]            ref_addr                ;
 37
 38
 39 //=============================================================================\
 40 //********************** Main Code    ***************************************
 41 //=============================================================================/
 42 always @(posedge sclk or negedge s_rst_n) begin
 43         if(s_rst_n == 1'b0)
 44                 state    <=    IDLE;
 45
 46         else case(state)
 47                 IDLE:
 48                         if(flag_init_end == 1'b1)
 49                             state <= ARBIT;
 50                         else
 51                             state <= IDLE;
 52                 ARBIT:
 53                         if(ref_en == 1'b1)
 54                             state <= AREF;
 55                         else
 56                             state <= ARBIT;
 57                 AREF:
 58                         if(flag_ref_end == 1'b1)
 59                             state <= ARBIT;
 60                         else
 61                             state    <=AREF;
 62                 default:
 63                             state <= IDLE;
 64         endcase
 65 end
 66
 67
 68 //ref_en
 69 always @(posedge sclk or negedge s_rst_n) begin
 70         if(s_rst_n == 1'b0)
 71                 ref_en <= 1'b0;
 72         else if(state == ARBIT && ref_req == 1'b1)
 73                 ref_en <= 1'b1;
 74             else
 75                 ref_en <= 1'b0;
 76 end
 77
 78 assign    sdram_cke        =    1'b1;
 79 assign    sdram_addr        =    (state == IDLE)    ?    init_addr    :    ref_addr;
 80 assign    {sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n}    =    (state == IDLE)    ?    init_cmd    :    ref_cmd;
 81 assign    sdram_dqm        =    2'd0;
 82 assign    sdram_clk         =     ~sclk;
 83
 84
 85 sdram_ini        sdram_ini_inst(
 86         //systejm sign
 87         .sclk                    (sclk            ),
 88         .s_rst_n                (s_rst_n        ),
 89         //others
 90         .cmd_reg                (init_cmd        ),
 91         .sdram_addr                (init_addr        ),
 92         .flag_init_end           (flag_init_end    )
 93 );
 94
 95 sdram_aref        sdram_aref_inst(
 96         //system signals
 97         .sclk                    (sclk            ),
 98         .s_rst_n                (s_rst_n        ),
 99         //comunicat with ARBIT
100         .ref_en                    (ref_en            ),
101         .ref_req                (ref_req        ),
102         .flag_ref_end            (flag_ref_end    ),
103         //others
104         .aref_cmd                (ref_cmd        ),
105         .sdram_addr                (ref_addr        ),
106         .flag_init_end            (flag_init_end    )
107 );
108
109
110 endmodule

sdram_top

6.最后老规矩放上仿真结果以及仿真波形图

初始化没有错,刷星也一直进行,没有错误

在看看波形图,没次看到这些信号就觉得自己就是个大牛,哈哈哈! 自恋了,但是还是个入了门的菜鸡。看图信号和数据都没问题,完美!

2018.9.14

首先骂一下狗逼学校都要写完了停电了。我靠全没了,暑假就停了我那么久的网,还到处开挖,挖金子啊绝地三尺关键是堵道。无语了。。。

消气还是重写吧,一个多月了,打算每做好一个功能就更的,可惜就该这个狗逼学校事多还停水停网,但是我也没停下。现在补上吧,下午都快写完了突然停电主机关机了,呵呵,现在就这样了

首先看一下现在做好的图片显示系统,用串口发送640*480的图片给FPGA,波特率是1562500,最快的了,VGA驱动显示屏。

说实话我不想再从写了,很烦,还有很多事要忙,真心要学的可以私聊我!

转载于:https://www.cnblogs.com/hqz68/p/9373866.html

基于fpga的256m的SDRAM控制器相关推荐

  1. 学习FPGA有必要写SDRAM控制器吗?

    在学习FPGA的过程中,注意是在学习过程中,联系FPGA的使用技巧,强烈建议尝试设计一个SDRAM控制器,不要使用IP核. 学习SDRAM控制器设计,能让你掌握很多知识. 更好的使用状态机去精准控制时 ...

  2. 基于FPGA的UART全双工数据控制器

    引言: UART串行通讯协议是一种经典通讯协议,尽管在当前,它的通讯传输速度已经不能满足高数据量传输场景,但在传统的工业应用中还十分普遍广泛.在网上,一般所见到的可应用于FPGA设计的UART接口都遗 ...

  3. 基于FPGA的4x4矩阵键盘控制器verilog开发实现

    欢迎订阅<FPGA学习入门100例教程>.<MATLAB学习入门100例教程> 目录 一.理论基础 二.核心程序 三.测试结果 一.理论基础 这里第一部分的主要目标是设计一个键 ...

  4. 基于FPGA的SDRAM控制器设计(二)

    基于FPGA的SDRAM控制器设计(二) 1. SDRAM理论基础 2. SDRAM初始化模块以及仿真 3.TOP模块的仲裁机制 4. SDRAM刷新模块代码以及仿真 5.代码 6.参考资料 1. S ...

  5. 基于FPGA的SDRAM控制器设计(1)

    基于FPGA的SDRAM初始化配置 SDRAM简述 SDRAM的引脚及作用 SDRAM初始化时序控制 SDRAM上电时序代码 SDRAM测试模块的代码 仿真测试结果 参考文献 总结 SDRAM简述 S ...

  6. 基于FPGA的SDRAM控制器设计(2)

    基于FPGA的SDRAM的自刷新操作 SDRAM自刷新简述 SDRAM自刷新时序图 SDRAM自刷新代码 仿真模块的代码 仿真结果测试 参考文献 总结 SDRAM自刷新简述 SDRAM作为一个RAM并 ...

  7. FPGA之SDRAM控制器设计(三)

    FPGA之SDRAM控制器设计(三):写 由于已经涉及了上电刷新,写三个大的状态转移,先把状态转移图给出.主控状态转移图是基于手册上描述来的.在代码注释中会给出每个状态的意义解释. 写时序图 写状态转 ...

  8. 基于Qsys的SDRAM控制器

    1.Intel FPGA中SDRAM控制器IP示意图 相比LED/数码管等简单外设,SDRAM芯片配置显得复杂许多,当然可以自行编写状态机实现初始化和读写控制,但是为了加快开发速度,可以借助Intel ...

  9. 基于FPGA的SPI FLASH控制器设计

    1.SPI FLASH的基本特征 本文实现用FPGA来设计SPI FLASH,FLASH型号为W25Q128BV.支持3种通信方式,SPI.Dual SPI和Quad SPI.FLASH的存储单元无法 ...

最新文章

  1. 只需两步,Tomcat JVM 参数性能迅速调到最优!
  2. hdu4287 水题
  3. 基于opencv在摄像头ubuntu根据视频获取
  4. 我的起点(蛇形矩阵)
  5. SVN 服务器的安装和配置(Gentoo)
  6. SpringSecurity 流程图
  7. Springboot+ssm高校会议预约系统javaweb
  8. 词根词缀学单词【1】
  9. python循环5次_Python入门五:循环
  10. Win7 文件加密存储操作后,如何在事后备份证书、秘钥
  11. c语言实现图片轮播,纯css实现轮播图
  12. 关于位运算符号的辨识及运用示例
  13. 00007__文本编辑器__UltraEdit
  14. 支付宝当面付实现跳转到指定网页唤起支付
  15. Windows Server 2016 ServU-v6.30
  16. 5个APP,4220个数据,回顾Yura的2018年
  17. [附源码]Java计算机毕业设计SSM菜鸟驿站快递分发系统
  18. Java基于JSP的高校教材管理系统
  19. TeX/LaTeX相关软件
  20. Network Security JumpStart

热门文章

  1. oracle常见数据端口,各种数据库默认端口汇集
  2. MATLAB安装、使用及卸载
  3. 浪擎终端备份系统2008 完善的桌面备份方案
  4. cobra mysql_golang 命令行cobra妙用
  5. 多少企业都死在最完美的时刻
  6. 机器人导航--Dubins曲线的轨迹规划
  7. 百里峡景区内的环保卫生间
  8. wifi mouse linux,wifi mouse pro最新版下载
  9. 合成郭子php,合成大郭子链接在哪玩 合成大郭子链接分享
  10. hadoop的搭建教程