如何将FPGA设计验证效率提升1000倍以上(2)
本文为系列文章的第二篇。
如果对处于全速(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)beginif (!sys_reset)begincounter <= 0;break <= 0;endelse if (clk_en)beginif (counter == breakpoint)beginbreak <= 1'b1;endelsebeginif (sig_in)counter <= counter + 1;break <= 1'b0;endendendBUFGCE inst_bufgce (.O(task_clk),.I(sys_clk),.CE(clk_en & ~break));always @(posedge task_clk)beginif (!sys_reset) begincycles <= 0;end elsebegincycles <= cycles + 1;endendendmodule
该模块非常精简,对您的原生设计的改动很小,所占用的硬件资源也很少。
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)
- 信号位宽Probe Width [1-256]:64;
- 初始值Initial Value (in hex):0x31
- 即该样例在位流载入完成之后,在运行阶段遇到的首个断点地址。
在本样例中,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代码在经过硬件编译后,信号名称可能会被优化改变,那么如何在源码和调试信号(位流数据)之间建立精准对应关系,大幅减少工程师的硬件经验成本;
包括更先进的以硬件速度仿真,直接对关键寄存器、状态机的故障注入测试,高效验证。真正做到所见即所得,所改即所需。
全文完,感谢您的耐心阅读