上一节已经实现了能够顺利的实现队DDR 3 写入16个递增数和把写入的递增数成功地读出来后,那么接下来就是对DDR3芯片的所有地址都进行读写测试,验证FPGA与DDR3芯片的链路是否正常。方法就是通过比较读出来的数据与写入进去的数据进行比较,看是否是一致的。

           如上图所示,是DDR的规格说明书。我们用到的型号是MT41J64M16—8Meg  x  16  x 8Banks,具体含义是:8Meg 表示含有8M个地址,位宽是16个BIT,8个bank。

            计算字节地址:8*8*2=128M字节地址(乘2是因为每个地址可以存放2个字节的数据),一个字节=8个bit 

            计算字节数据: 8*1024*1024*16=134217728byte

            总的突发次数:134217728/16/8=1048576

时序设计图

         

 

 

 

 

各个端口的介绍

          在此实验中,我所设计的是P0端口用来向DDR中写入数据,P1的端口用来读取写入的数据:

          p0_wr_en :写入数据的使能信号,

          wr_cnt  : 对写入的数据的个数计数寄存器,即突发一次写入16个数据,在p0_wr_en 有效时开始进行计数,16个数据后,清零同时p0_wr_en拉低,一次写数据的突发操作完成;

          wr_data :写入的数据寄存器,在此仅仅为测试DDR的各个链路的读写是否存在问题,所以写入的数就是从0 开始是递增的一串递增数,写数据寄存器要先于写数据命令到来之前准备好,因为对DDR写入数据时相当于对一个写FIFO进行操作,对于这个FIFO来说就是读取数据,如果没有数据事先准备好的话,会出现读空的现象。

          p0_cmd_en:写数据命令使能,当此信号到来的时候,DDR的写数据的相关命令,便开始进行配置;此信号一般在写入数据寄存器的数据准备好后再拉高;

          p1_cmd_en:,读数据命令使能,当此信号到来的时候,DDR的读数据的相关命令,便开始进行配置;此信号一般在 p0_cmd_en写命令使能拉高后再拉高;

          rd_flag : 读数据的操作标志信号,所有的读数据相关的操作,都在此使能条件下完成,可以看成是读操作的总开关;在写命令拉高后就可以;

          rd_cnt: 读操作的计数器,此计数器不仅仅包括了16个数据的读数据突发个数,还包括了,从的安全完成写入数据,到有效读数据的所需要的准备时间;这里的准备时间不同的板子是不一样的,即使板子的时钟是一样的,需要根据仿真时序来一步一步调试;

          rd_en: 与p0_wr_en 信号是对应的,此信号的拉高时间周期个数要满足读数据的一次突发个数;即16个

          byte_addr:地址位,读数据突发一次是16个数据,每个数据是8字节,所以突发一次16*8=128个地址;

          check_data: 校验数据,这里使用来检测与独处的数据是否一致,所以在rd_en 有效的时候进行自加;

          burst_cnt:突发次数,需要知道测试一遍要突发多少次,能够与把所有的地址检测完;

          error_flag:错误标志位,在chaeck_data与读出来的数据不一致的时候,此标志信号拉高;

          error_num: 错误的个数,error_flag信号拉高一次,此信号加一次;

      编写代码:    

         

  1 module    ddr_drive(
  2 
  3      // system signals
  4         input                   sclk                    ,       
  5         input                   s_rst_n                 ,       
  6         // DDR3 User Interfaces
  7         output  reg             p0_cmd_en               ,       
  8         output  wire    [ 2:0]  p0_cmd_instr            ,       
  9         output  wire    [ 5:0]  p0_cmd_bl               ,       
 10         output  wire    [29:0]  p0_byte_addr            ,
 11         output  reg             p0_wr_en                ,       
 12         output  wire    [ 7:0]  p0_wr_mask              ,       
 13         output  reg     [63:0]  p0_wr_data              ,
 14         output  reg             p1_cmd_en               ,       
 15         output  wire    [ 2:0]  p1_cmd_instr            ,       
 16         output  wire    [ 5:0]  p1_cmd_bl               ,       
 17         output  reg     [29:0]  p1_byte_addr            ,
 18         output  reg             p1_rd_en                ,       
 19         input           [63:0]  p1_rd_data                    
 20         // Debug
 21  //        input                   wr_trig                        
 22 );
 23 
 24 //========================================================================\
 25 // =========== Define Parameter and Internal signals =========== 
 26 //========================================================================/
 27 localparam      RD_END          =       'd45                    ;
 28 
 29 localparam      BURST_NUM_END   =       1048575                 ;
 30 // localparam      BURST_NUM_END   =       9                       ;
 31 
 32 reg     [ 3:0]                  wr_cnt                          ;       
 33 reg                             rd_flag                         ;       
 34 reg     [ 5:0]                  rd_cnt                          ;       
 35 
 36 reg     [63:0]                  check_data                      ;       
 37 reg     [20:0]                  burst_cnt                       ;       
 38 reg                             error_flag                      ;       
 39 reg     [15:0]                  error_num                       ;
 40 
 41 reg                             wr_trig                         ;       
 42 
 43 //=============================================================================
 44 //**************    Main Code   **************
 45 //=============================================================================
 46 assign  p0_cmd_instr    =       3'b000;
 47 assign  p0_cmd_bl       =       'd15;
 48 assign  p0_byte_addr    =       p1_byte_addr;
 49 assign  p0_wr_mask      =       8'h0;
 50 assign  p1_cmd_instr    =       3'b001;
 51 assign  p1_cmd_bl       =       'd15;
 52 
 53 
 54 always  @(posedge sclk or negedge s_rst_n) begin
 55         if(s_rst_n == 1'b0)
 56                 p0_wr_en        <=      1'b0;
 57         else if(wr_trig == 1'b1)
 58                 p0_wr_en        <=      1'b1;
 59         else if(rd_cnt == RD_END && burst_cnt < BURST_NUM_END)
 60                 p0_wr_en        <=      1'b1;
 61         else if(wr_cnt == 'd15)
 62                 p0_wr_en        <=      1'b0;
 63 end
 64 
 65 always  @(posedge sclk or negedge s_rst_n) begin
 66         if(s_rst_n == 1'b0)
 67                 wr_cnt  <=      'd0;
 68         else if(p0_wr_en == 1'b1)
 69                 wr_cnt  <=      wr_cnt + 1'b1;
 70 end
 71 
 72 always  @(posedge sclk or negedge s_rst_n) begin
 73         if(s_rst_n == 1'b0)
 74                 p0_wr_data      <=      64'h0;
 75         else if(p0_wr_en == 1'b1)
 76                 p0_wr_data      <=      p0_wr_data + 1'b1;
 77 end
 78 
 79 always  @(posedge sclk or negedge s_rst_n) begin
 80         if(s_rst_n == 1'b0)
 81                 p0_cmd_en       <=      1'b0;
 82         else if(wr_cnt == 'd15)
 83                 p0_cmd_en       <=      1'b1;
 84         else
 85                 p0_cmd_en       <=      1'b0;
 86 end
 87 
 88 //------------------------------------------------------------------
 89 always  @(posedge sclk or negedge s_rst_n) begin
 90         if(s_rst_n == 1'b0)
 91                 rd_flag <=      1'b0;
 92         else if(rd_cnt == RD_END)
 93                 rd_flag <=      1'b0;
 94         else if(p0_cmd_en == 1'b1)
 95                 rd_flag <=      1'b1;
 96 end
 97 
 98 always  @(posedge sclk or negedge s_rst_n) begin
 99         if(s_rst_n == 1'b0)
100                 p1_cmd_en       <=      1'b0;
101         else if(rd_cnt == 'd19)
102                 p1_cmd_en       <=      1'b1;
103         else
104                 p1_cmd_en       <=      1'b0;
105 end
106 
107 always  @(posedge sclk or negedge s_rst_n) begin
108         if(s_rst_n == 1'b0)
109                 rd_cnt  <=      'd0;
110         else if(rd_flag == 1'b1)
111                 rd_cnt  <=      rd_cnt + 1'b1;
112         else
113                 rd_cnt  <=      'd0;
114 end
115 
116 always  @(posedge sclk or negedge s_rst_n) begin
117         if(s_rst_n == 1'b0)
118                 p1_rd_en        <=      1'b0;
119         else if(rd_cnt == 'd29)
120                 p1_rd_en        <=      1'b1;
121         else if(rd_cnt == RD_END)
122                 p1_rd_en        <=      1'b0;
123 end
124 
125 always  @(posedge sclk or negedge s_rst_n) begin
126         if(s_rst_n == 1'b0)
127                 check_data      <=      64'h0;
128         else if(p1_rd_en == 1'b1)
129                 check_data      <=      check_data + 1'b1; 
130 end
131 
132 always  @(posedge sclk or negedge s_rst_n) begin
133         if(s_rst_n == 1'b0)
134                 p1_byte_addr    <=      'd0;
135         else if(p1_cmd_en == 1'b1)
136                 p1_byte_addr    <=      p1_byte_addr + 'd128;
137         else if(wr_trig == 1'b1)
138                 p1_byte_addr    <=      'd0;
139 end
140 
141 always  @(posedge sclk or negedge s_rst_n) begin
142         if(s_rst_n == 1'b0)
143                 burst_cnt       <=      'd0;
144         else if(rd_cnt == RD_END)
145                 burst_cnt       <=      burst_cnt + 1'b1;
146         else if(wr_trig == 1'b1)
147                 burst_cnt       <=      'd0;
148 end
149 
150 always  @(posedge sclk or negedge s_rst_n) begin
151         if(s_rst_n == 1'b0)
152                 error_flag      <=      1'b0;
153         else if(p1_rd_data != check_data &&  p1_rd_en == 1'b1)
154                 error_flag      <=      1'b1;
155         else 
156                 error_flag      <=      1'b0;
157 end
158 
159 always  @(posedge sclk or negedge s_rst_n) begin
160         if(s_rst_n == 1'b0)
161                 error_num       <=      'd0;
162         else if(error_flag == 1'b1)
163                 error_num       <=      error_num + 1'b1;
164         else if(wr_trig == 1'b1)
165                 error_num       <=      'd0;
166 end

使用chiop_scop 抓取波形:

 

 1 wire    [35:0]                  CONTROL0                        ;       
 2 wire    [35:0]                  CONTROL1                        ;       
 3 wire    [243:0]                 ila_data                        ;       
 4 wire                            vio_out                         ;       
 5 reg                             vio_out_r1                      ;       
 6 reg                             vio_out_r2                      ;       
 7 
 8 assign  ila_data[0]     =       wr_trig;
 9 assign  ila_data[16:1]  =       error_num;
10 assign  ila_data[17]    =       error_flag;
11 assign  ila_data[18]    =       p0_cmd_en;
12 assign  ila_data[19]    =       p1_cmd_en;
13 assign  ila_data[49:20] =       p1_byte_addr;
14 assign  ila_data[50]    =       p0_wr_en;
15 assign  ila_data[114:51]=       p0_wr_data;
16 assign  ila_data[115]   =       p1_rd_en;
17 assign  ila_data[179:116] =     p1_rd_data;
18 assign  ila_data[243:180] =     check_data;
19 
20 always  @(posedge sclk) begin
21         vio_out_r1      <=      vio_out;
22         vio_out_r2      <=      vio_out_r1;
23 end
24 
25 always  @(posedge sclk or negedge s_rst_n) begin
26         if(s_rst_n == 1'b0)
27                 wr_trig <=      1'b0;
28         else
29                 wr_trig <=      vio_out_r2 ^ vio_out_r1;
30 end
31 
32 
33 chipscope_icon chipscope_icon_inst (
34         .CONTROL0               (CONTROL0               ),// INOUT BUS [35:0]
35         .CONTROL1               (CONTROL1               )// INOUT BUS [35:0]
36 );
37  
38 
39 chipscope_ila chipscope_ila_inst (
40         .CONTROL                (CONTROL0               ), // INOUT BUS [35:0]
41         .CLK                    (sclk                   ), // IN
42         .TRIG0                  (ila_data               )// IN BUS [35:0]
43 );
44 
45 chipscope_vio chipscope_vio_inst (
46         .CONTROL                (CONTROL1               ), // INOUT BUS [35:0]
47         .CLK                    (sclk                   ), // IN
48         .SYNC_OUT               (vio_out                )// OUT BUS [0:0]
49 );
View Code

利用上一节写好的tb文件,稍作修改;

  1 `timescale    1ps/1ps
  2 
  3 
  4 module      tb_ddr_top ;
  5 
  6 reg                                      ddr3_ref_clk         ;
  7 reg                                      ddr3_rst_n           ;
  8 //bebug   signals 
  9 reg                                      wr_trig              ;
 10 wire                                     c3_calib_done        ;
 11 
 12 //ddr3 interface 
 13 wire [15:0]                               mcb3_dram_dq        ;
 14 wire [12:0]                               mcb3_dram_a         ;
 15 wire [2:0]                                mcb3_dram_ba        ;
 16 wire                                      mcb3_dram_ras_n     ;
 17 wire                                      mcb3_dram_cas_n     ;
 18 wire                                      mcb3_dram_we_n      ;
 19 wire                                      mcb3_dram_odt       ;
 20 wire                                      mcb3_dram_reset_n   ;
 21 wire                                      mcb3_dram_cke       ;
 22 wire                                      mcb3_dram_dm        ;
 23 wire                                      mcb3_dram_udqs      ;
 24 wire                                      mcb3_dram_udqs_n    ;
 25 wire                                      mcb3_rzq            ;
 26 wire                                      mcb3_zio            ;
 27 wire                                      mcb3_dram_udm       ;
 28 wire                                      mcb3_dram_dqs       ;
 29 wire                                      mcb3_dram_dqs_n     ;
 30 wire                                      mcb3_dram_ck        ;
 31 wire                                      mcb3_dram_ck_n      ;
 32 
 33 
 34 
 35 
 36 parameter C3_MEMCLK_PERIOD     = 20000;
 37 
 38 
 39 initial    begin
 40     
 41         ddr3_ref_clk     =     1;
 42         ddr3_rst_n       =     0;
 43         #20000;
 44         ddr3_rst_n       =     1;    
 45     
 46     
 47 end 
 48 
 49 
 50 
 51 
 52 //produce debug  signals 
 53 initial    begin
 54           wr_trig      <=     0;
 55           @(posedge c3_calib_done)
 56           #100000
 57           wr_trig      <=     1;
 58           #25600
 59           wr_trig      <=     0;
 60 end 
 61 
 62 
 63 
 64 
 65 always   #(C3_MEMCLK_PERIOD/2)  ddr3_ref_clk     =     ~ddr3_ref_clk ;
 66 
 67 
 68  ddr_top   ddr_top_inst(
 69 
 70    
 71    
 72    //sysyterm  interface
 73    .c3_sys_clk                               (ddr3_ref_clk       ),  
 74    .c3_sys_rst_i                             (ddr3_rst_n         ), 
 75    //ddr3 interface 
 76    .mcb3_dram_dq                             (mcb3_dram_dq       ),
 77    .mcb3_dram_a                              (mcb3_dram_a        ),
 78    .mcb3_dram_ba                             (mcb3_dram_ba       ),
 79    .mcb3_dram_ras_n                          (mcb3_dram_ras_n    ),
 80    .mcb3_dram_cas_n                          (mcb3_dram_cas_n    ),
 81    .mcb3_dram_we_n                           (mcb3_dram_we_n     ),
 82    .mcb3_dram_odt                            (mcb3_dram_odt      ),
 83    .mcb3_dram_reset_n                        (mcb3_dram_reset_n  ),
 84    .mcb3_dram_cke                            (mcb3_dram_cke      ),
 85    .mcb3_dram_dm                             (mcb3_dram_dm       ),
 86    .mcb3_dram_udqs                           (mcb3_dram_udqs     ),
 87    .mcb3_dram_udqs_n                         (mcb3_dram_udqs_n   ),
 88    .mcb3_rzq                                 (mcb3_rzq           ),
 89    .mcb3_zio                                 (mcb3_zio           ),
 90    .mcb3_dram_udm                            (mcb3_dram_udm      ),
 91    .mcb3_dram_dqs                            (mcb3_dram_dqs      ),
 92    .mcb3_dram_dqs_n                          (mcb3_dram_dqs_n    ),
 93    .mcb3_dram_ck                             (mcb3_dram_ck       ),
 94    .mcb3_dram_ck_n                           (mcb3_dram_ck_n     ),
 95    //debug   signals 
 96    .wr_trig                                   (wr_trig)          ,
 97    .c3_calib_done                            (c3_calib_done)
 98 
 99 );
100 
101  ddr3_model_c3 u_mem_c3(                             
102   .ck         (mcb3_dram_ck),                        
103   .ck_n       (mcb3_dram_ck_n),                      
104   .cke        (mcb3_dram_cke),                       
105   .cs_n       (1'b0),                                
106   .ras_n      (mcb3_dram_ras_n),                     
107   .cas_n      (mcb3_dram_cas_n),                  
108   .we_n       (mcb3_dram_we_n),                      
109   .dm_tdqs    ({mcb3_dram_udm,mcb3_dram_dm}),        
110   .ba         (mcb3_dram_ba),                        
111   .addr       (mcb3_dram_a),                         
112   .dq         (mcb3_dram_dq),                        
113   .dqs        ({mcb3_dram_udqs,mcb3_dram_dqs}),      
114   .dqs_n      ({mcb3_dram_udqs_n,mcb3_dram_dqs_n}),  
115   .tdqs_n     (),                                    
116   .odt        (mcb3_dram_odt),                       
117   .rst_n      (mcb3_dram_reset_n)                    
118   ); 
119   
120 // The PULLDOWN component is connected to the ZIO signal primarily to avoid the    
121 // unknown state in simulation. In real hardware, ZIO should be a no connect(NC) pin. 
122    PULLDOWN zio_pulldown3 (.O(zio3));   PULLDOWN rzq_pulldown3 (.O(rzq3));            
123                                                                                       
124 
125   
126      endmodule                                                 
View Code

注意:

        在进行板级操作之前,我们需要对时钟在进行一些先关操作,我的板载时钟是单口50MHZ,但在先前的仿真过程中和实际操作中DDR3我们设置的是312.5MHZ,在以下路径:F:\STUDAY_FPGA\USB_DDR\usb2.0_read_ddrPN\ise_prj\usb_read\ipcore_dir\mig_39_2\user_design\rtl\mig_39_2.v

localparam C3_CLKFBOUT_MULT = 25; //原来是1
localparam C3_DIVCLK_DIVIDE = 2;//原来是0;

计算公式:312.5/50=12.5

                  25/2= 12.5   

抓取到的波形

 

 OK完成,有问题加微信交流: