分享

Vivado进行FPGA调试“犯罪现场”,在仿真环境中重现方法

 goandlove 2019-06-19

 在FPGA调试过程中,经常遇到这样的情况:出现BUG时,想采用仿真环境把FPGA调试中遇到的BUG给重现出来,但无论怎样改变仿真环境中的激励,都无法重现FPGA上的出现BUG的情况。此时,如果有一种方法,能够把FPGA正在运行时产生BUG前所有的输入变量状态给捕获下来,然后作为激励,添加到仿真环境中去,这样以来,就能够重现FPGA运行时出现的BUG,就可以在仿真环境中去解决这个BUG,调试的复杂度瞬间降低很多,也能大大的提高FPGA调试的效率。

    本文介绍一种利用Vivado进行FPGA调试时,如何把FPGA调试中的数据给“捕获”出来,并保存为文件,转换到仿真环境中进行仿真,“重现”FPGA调试运行场景的方法。

1、背景

从一个RTL代码描述的电路到FPGA样机的过程可以分为两个阶段,第一阶段为仿真验证,第二阶段为FPGA验证。仿真验证是激励数据源常常由自己编写,往往与板级验证数据源(如TestCenter等网络测试仪产生的以太网数据包)存在较大区别,因此在这里介绍一种将板级验证数据导入仿真Testbench中的方法。使用这种方法,可以使仿真验证数据源最大限度地接近板级数据源,可以辅助排除绝大部分的逻辑错误。

2、操作流程

这里我们还以Zedboard Debug数据导出到Testbench为例,对具体实施流程进行介绍,如图1所示,该流程可以分为3个步骤:

(1) Zedboard,抓取感兴趣的数据,并通过jtag线传输到上位机;

(2) 在上位机Vivado软件的Tcl Console中输入命令,将抓取的数据另存为wave.csv文件;

(3) 将wave.csv文件中的数据导入Testbench中,最终输出波形。

图1 操作流程

3、 操作实例

下面给出一个实例,针对图1的三个步骤,对操作流程进行详细介绍。

(1) 抓取感兴趣的数据,如图2所示。

图2 抓取感兴趣的数据

(2) 如图3所示,在tclconsole中输入命令,将抓取的数据转存为wave,csv,转存后的文件如图4所示。

图3 tcl console输入命令

图4 wave.csv文件

(3)将图4中的数据存入RAM中,并在Testbench中循环读取,获得波形数据,如图5所示。

图5 波形数据

通过这样的方法,就可以把FPGA运行时的输入激励数据捕获到文件中,进而转换到仿真环境中进行调试。

按照惯例,我们给出上述过程的源码。

FPGA工程源代码

1`timescale 1ns/1ps 
2
3module  CAPTURE_TOP  (     
4                      input   clk    
5                      ) ;
6
7//REGS
8reg [30:0] cnt ;
9//WIRES
10 wire rst ;
11 wire [31:0] cnt_capture ;
12
13//INSTANTCE MODULE
14vio_rst u_vio_rst (
15    .clk(clk), // input wire clk
16    .probe_out0(rst)  // output wire [0 : 0] probe_out0
17    );
18
19ila_0 u_ila_0 (
20    .clk(clk), // input wire clk
21    .probe0(cnt_capture) // input wire [31:0] probe0
22    );
23
24//MAIN CORE
25
26always @(posedge clk or posedge rst) begin
27    if (rst == 1'b1) begin
28       cnt <>
d0 ;
29    end
30    else begin
31       cnt <>'d3 ; 
32    end
33end
34
35assign cnt_capture = {1'
b1, cnt} ;
36
37endmodule  
38

Zedboard开发板约束文件

1set_property PACKAGE_PIN Y9 [get_ports clk]
2set_property IOSTANDARD LVCMOS33 [get_ports clk]

仿真环境TESTBENCH文件

1`timescale 1ns/1ps 
2 module CAPTURE_TEST_TOP ;
3//REGS    
4 reg   clk ;
5 reg   rst ;
6 reg [9:0] addra ;
7
8//WIRES   
9 wire [30:0] dout   ;
10 wire [31:0] douta  ;  
11
12ROM_32_1024 your_instance_name (
13  .clka(clk),    // input wire clka
14  .ena(1'b1),      // input wire ena
15  .addra(addra),  // input wire [9 : 0] addra
16  .douta(douta)  // output wire [31 : 0] douta
17);
18
19  always @(posedge clk or posedge rst) begin
20      if (rst == 1'b1) begin
21          addra <>
d0 ;
22      end
23      else begin
24         addra <>1'b1 ; 
25      end
26  end
27
28  assign dout = douta[30:0] ;
29
30//MAIN CORE
31initial begin 
32    clk = 1'
b0 ;
33    rst = 1'b1 ;
34    # 100
35    rst = 1'b0 ;
36 end 
37 always # 10 clk = ~clk ;
38
39endmodule

注:上述文件中ROM模块(data_1024.coe)数据来自图4所示的数据。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多