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

基于fpga的256m的SDRAM控制器2018/7/26受教于邓堪文老师,开始真真学习控制sdram由于自己买的sdram模块是256的,原来老师的是128,所以边学边改,不知道最后好不好使,但是我有信心一.sdram的初始化sdram介绍啥的就不用了,上来就是干,简单粗暴。1.下面是引脚说明,看不懂自己可以用百度翻译,需要注意的是红框内的地址引脚和行列地址是复…

大家好,又见面了,我是你们的朋友全栈君。

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

 

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

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

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

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

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

 

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

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

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

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

5.再来一张时序图

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

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

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

 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

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

 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

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

 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的不能用,但是我改好了

 

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

   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.最后附上仿真结果

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

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

再来看看波形吧

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

 

 

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

 

2018/730

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

二.仲裁机制和刷新操作

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

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

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

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

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

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

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

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

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

 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个操作,我们需要这个仲裁机制来协调这三个操作,引用邓堪文老师一个图,大家一看就应该很明白了

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

 

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

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

  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.最后老规矩放上仿真结果以及仿真波形图

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

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

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

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

 

 

2018.9.14

由于学校突然断电,我写三个小时,马上写完的内容就没了,快被气死了。不想重写了,还有很多事情要做,顾不过来了。

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

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

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

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

欢迎关注我的公众号:芯王国,有更多的FPGA&数字IC的技术分享,还可以获取开源FPGA项目!

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/129175.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • sublime text3激活码【注册码】[通俗易懂]

    sublime text3激活码【注册码】,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • 微软面试-微软面试题(5)[通俗易懂]

    微软面试-微软面试题(5)[通俗易懂]微软面试题-头脑  ★如果你有一个许多部件可以拆卸的时钟,你将它一块块拆开,但是没有记住是怎样拆的。然后你将各个零件重新组装起来,最后发现有三个重要零件没有放进去。这时你如何重新组装这个时钟?  ★如果你需要学习一门新的计算机语言,你会怎样做?  ★假设由你负责设计比尔·盖茨的卫生间。当然,钱不成问题,但是你不可以和比尔谈。你会怎样做?  ★到目前为止,你遇到的最难回答的问题是什么?  ★如果微软

  • 使用CityScapes数据集训练实例分割网络YOLACT

    使用CityScapes数据集训练实例分割网络YOLACT#2020开年第一篇,谁能预料新年伊始的世界如此脆弱,中国疫情肆虐,美伊箭拔弩张,英国愤懑脱欧,儿时的偶像科比和女儿也不幸离世,生命之渺小,生活之曲折,兄弟们,要充满阳光地活着啊,人间,值得。:-)今天还是鄙人生日,愿世间多点爱,与和平。上一篇介绍了博主用CityScapes数据集提取了五类实例,并转换成了COCO数据集的标注格式(将CityScapes数据集转换为COCO格式的实例分割数据集…

  • linux上安装软件详细步骤(开关安装方法图解)

    软件安装及管理一.软件的类型二.Tar包安装、升级、卸载(必须会)三.RPM软件包安装及管理(必须会)四.脚本安装、升级、卸载五.SRPM包安装(知道就行,很少用)一.软件的类型1.软件是指计算机系统中的程序及其文档程序必须装入机器内部才能工作文档一般是给人看的,不一定装入机器软件是用户与硬件之间的接口界面系统软件和应用软件2.应用程序与系统命令的关系文件位置系统命令:…

  • 数据库DSN是什么

    数据库DSN是什么

    2021年10月31日
  • 个人网站如何赚钱

    个人网站如何赚钱

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号