如何将FPGA设计验证效率提升1000倍以上(2)

发布于:2025-07-05 ⋅ 阅读:(23) ⋅ 点赞:(0)

本文为系列文章的第二篇。

如果对处于全速(at-speed)运行下的FPGA调试,工程师在现有通用“能力技术”基础上,再增加“硬件断点”功能,那么对高速运行FPGA,也就拥有像调试软件程序类似的完整可观测能力(Full Visibility)和可控制能力(Controllability)。

以赛灵思FPGA的应用开发为例,用户已经能从硬件的运行特征出发,为设计增加两类硬件断点。除了前文所介绍的时钟断点功能,本文将详细介绍事件断点(Event-based Breakpoint)的集成和使用。

与适用于算法设计、接口控制等全同步设计的时钟断点相比,事件断点是由用户自定义的事件触发信号来冻结时钟,即以“事件发生的次数”为中断地址。适用于对包含UART、以太网等通信接口在内,较复杂的FPGA应用开发设计。

例如,在网络处理系统中,可将“数据包接收/发送”作为事件断点;在数据加密处理应用中,将“一个数据块处理结束”作为事件触发信号。

用户在设计阶段,与前文介绍的时钟断点类似,事先将硬件断点控制模块(interruption logic)集成到待测DUT的顶层(hw_top),就可获得这样的在线调试能力。

本文将以按图索骥的方式,详细介绍在设计中集成事件断点的实现过程,对原有设计的改动非常小,仍然保持优异的时序性能。

以下为正文

1. 样例简要介绍

uart-demo作为串口数据传输样例,用于控制uart串口数据的发送,以及led输出。

通信协议设置为“9600 bps,8位数据位,没有校验位、1位停止位”。

源码获取地址:https://gitee.com/forgeda/forgedaX-35T/tree/master/demo/vivado-uart/Source
 

2.  事件断点控制模块

模块定义如下:

module interruption_logic(
   	(* dont_touch = "true" *) output reg [63:0] cycles,
   	input sig_in,
   	input sys_clk,
	input sys_reset,
	output task_clk
);

	wire clk_en;
	wire [63:0] breakpoint;
    reg [63:0] counter;
    reg break;
    
    il_vio_0 il_vio (
         .clk(sys_clk),
         .probe_in0(counter),
         .probe_in1(cycles),
         .probe_out0(breakpoint),
         .probe_out1(clk_en)
    );

	always @(posedge sys_clk)
	begin
		if (!sys_reset)
		begin
			counter <= 0;
			break <= 0;
		end
		else if (clk_en)
		begin
			if (counter == breakpoint)
			begin
				break <= 1'b1;
			end
			else
			begin
			    if (sig_in)
				counter <= counter + 1;
				break <= 1'b0;
			end
		end
	end

	BUFGCE inst_bufgce (
		.O(task_clk),
		.I(sys_clk),
		.CE(clk_en & ~break)
	);
	
	always @(posedge task_clk)
    begin
        if (!sys_reset) 
        begin
            cycles <= 0;
        end  
        else
        begin
            cycles <= cycles + 1;
        end
	end

endmodule

该模块非常精简,对您的原生设计的改动很小,所占用的硬件资源也很少。

3.  将事件断点模块集成到设计中

在原有设计中集成事件断点控制模块,全程在Xilinx Vivado环境下完成,共有以下四个步骤。

Step 1. 导入控制模块interruption logic,并对VIO进行参数设置

单击“Finish”,确认导入该模块文件。

导入断点控制模块所使用的VIO IP

在Vivado中,选择“IP Catalog”,导入VIO IP核。

在IP Catalog搜索框中,直接输入VIO,显示如下:

设置VIO IP核的输出端口(PROBE_OUT0),设置事件断点的初始地址。

在Customize IP核界面,对VIO IP进行参数设置:

接下来,设置两个关键输出端口的参数:

  • 事件断点的初始地址(PROBE_OUT0)
  1. 信号位宽Probe Width [1-256]:64;
  2. 初始值Initial Value (in hex):0x31
  3. 即该样例在位流载入完成之后,在运行阶段遇到的首个断点地址。

在本样例中,UART端口在板卡上电后,直接输出“\n\rARTY GPIO/UART DEMO!      \r\n”消息,我们选择将UART设计中的“bit_done”作为中断触发信号,表示“串口已发送1 bit数据”。

换而言之,当事件断点设置为0x31,表示设计将在传输49 bit,即传输第五个字符“T”的停止位时,暂停运行。

  • 时钟使能信号(PROBE_OUT1)

信号位宽Probe Width [1-256]:1;

初始值Initial Value (in hex):0x1

初始值设置为1,表示开启时钟使能。

点击“OK”,确认以上参数配置。

点击“Generate”,生成VIO IP核。

显示“Generation of output products completed successfully”消息,表示IP核已成功导入。

Step 2.  对设计顶层(hw_top)进行更改处理

以下为集成事件断点模块后的设计顶层,原有设计的改动部分已用红色标记。

集成断点控制模块之后的Vivado工程文件,详见
https://gitee.com/forgeda/forgedaX-35T/tree/master/demo/vivado_uart_event_bp/uart_breakpoint

Step 3.  重新启动Vivado编译过程
启动Vivado编译,生成新的设计结果文件(.dcp), 得到的配置位流文件top.bit,以及调试支撑文件debug_nets.ltx。

完成以上工作后,就可以直接下载运行,并通过Hardware Manager,自行验证以上集成过程是否已经正确无误。

4. 自检方法

您可直接在Vivado Hardware Manager中快速验证,具体步骤如下:

如下图所示,样例在初始化结束后,输出字符“ART”之后暂停运行,该断点地址即为Step 2 设置的0x31。

可继续在VIO窗口,设置新的断点地址,例如,输入“0x3B”,表示设计将在传输59 bit,即第六个字符“Y”发送结束时,暂停运行。

最后,将断点地址设置为FFFF_FFFF_FFFF_FFFF,清除断点,如下图所示。

样例将继续全速运行,输出完整的“ARTY GPIO/UART DEMO!      ”消息。

在前文的时钟断点、本文的事件断点这两个硬件断点准备工作后,下一篇我们将介绍如何在板级在线调试过程中,无需在源码、网表插探针,在不占用任何硬件资源,就可得FPGA运行状态的全可观测能力,对设计拥有100%的信号可见性,这是ILA、Chipscope等现有工具不能提供的功能;

以及RTL代码在经过硬件编译后,信号名称可能会被优化改变,那么如何在源码和调试信号(位流数据)之间建立精准对应关系,大幅减少工程师的硬件经验成本;

包括更先进的以硬件速度仿真,直接对关键寄存器、状态机的故障注入测试,高效验证。真正做到所见即所得,所改即所需。

全文完,感谢您的耐心阅读


网站公告

今日签到

点亮在社区的每一天
去签到