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

相关推荐

发表回复

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

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