基于fpga的256M SDRAM控制器 【内含256m sdram仿真模型】

基于fpga的256m的SDRAM控制器

 

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:  [email protected]
  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驱动显示屏。

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

 
 
 
 
 
 
 
posted @ 2018-07-26 19:36 宏强子 阅读(...) 评论(...) 编辑 收藏
发布了36 篇原创文章 · 获赞 28 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_40377195/article/details/88408504