FPGA基於ISE的DDR3讀寫循環校驗的實現以及波形的抓取(8)


             上一節已經實現了能夠順利的實現隊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完成,有問題加微信交流:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM