文章目录
- 一、前言
- 二、ILA的基本功能使用以及局限性
- 2.1 ILA的调用
- 2.2 ILA波形窗口观察
- 2.3 ILA基本功能的局限性:如何观测低频的数据?
- 二、Capture Control 功能介绍
- 三、Advanced Trigger功能以及TSM编写
- 3.1 触发状态机的写法
- 3.2 设置Advanced Trigger
- 3.3 编写触发状态机(TSM)
- 3.4 下载程序后,加载TSM文件并且编译
- 四、总结
一、前言
在XILINX FPGA开发中,我们经常使用逻辑分析仪(ILA)对工程进行debug调试。绝大部分情况ILA的基本功能就可以满足大部分人的使用;但是存在少数情况使用基本的ILA无法捕捉到我们想要观看的波形,所以就有了ILA高级捕获的功能:Capture Control 与Advanced Trigger。
二、ILA的基本功能使用以及局限性
2.1 ILA的调用
大家经常用的ILA(Integrated Logic Analyzer)有三种配置方式:
-
创建ILA核并且例化到所要测试的模块里
按照步骤生成ILA后,例化到程序模块,把对应的信号连接上对应探针端口即可。 -
使用标记语句对信号进行标记 (* MARK_DEBUG=“true” *)
在程序模块,在想要观测的信号前面加上这语句然后综合。
综合完成后,打开综合设计(Open Synthesized Design)
点击(Set Up Debug)
创建完记得保存约束文件,然后布局布线再生成bit流即可
-
标记数据路径
综合完成后,打开综合设计(Open Synthesized Design),在Netlist中选择想要观测的信号,单击右键选择(Mark Debug)
在最下方Debug窗口选择设置的信号,单击右键,创建ILA,步骤与其它方式一致,这里不在赘述。
2.2 ILA波形窗口观察
在调用ILA并且生成bit流后下载程序,窗口会自动弹出ILA窗口。
至此,已完成ILA的基本使用。
2.3 ILA基本功能的局限性:如何观测低频的数据?
根据手册我们知道,连接ILA的时钟必须是一个“自由”的时钟,即上电就有的时钟,例如外部晶振。不能是从serdes恢复出来的时钟,自分频的时钟等等,否者下载程序会报错。ILA时钟频率也必须是JTAG时钟的2.5倍以上,JTAG也有最低的速率要求:
因此,由上图JTAG时钟的列表可以找到,JTAG时钟最低可设置为125KHZ,所以理论上连接ILA的时钟最低也是312.5KHZ,但是对于ILA低于 20M 的采样时钟会不能正常工作。而且过低的JTAG时钟会导致下载程序时间非常长,默认的JTAG时钟为15M。通常在FPGA设计中,程序的时钟大多数都在几十兆甚至几百兆,如果我想看频率只有几十K的信号,用几十兆的时钟去采样,那么波形窗口将全是重复的点,达不到预期想要的效果。
例如:我们用50M时钟要产生一个PWM信号,PWM周期为2s,如图所示:
程序如下:
`timescale 1ns / 1ps
module breath_led#
(
parameter cnt_1us = 6'd50,
parameter cnt_1ms = 10'd1000,
parameter cnt_1s = 10'd1000
)
(
input sys_clk ,
input sys_rstn ,
output reg pwm
);
reg [5:0] cnt_us ; //1us计数器
reg [9:0] cnt_ms ; //1ms计数器
reg [9:0] cnt_s ; //1秒计数器
reg pwm_flag ;//pwm输出flag
reg cnt_1ms_done ; //1ms计数完成信号
//1us计数器
always @(posedge sys_clk or negedge sys_rstn) begin
if(sys_rstn == 1'b0)
cnt_us <= 6'd0;
else if(cnt_us == cnt_1us - 1)
cnt_us <= 6'd0;
else
cnt_us <= cnt_us + 1'b1;
end
//1ms计数器
always @(posedge sys_clk or negedge sys_rstn) begin
if(sys_rstn == 1'b0)
cnt_ms <= 10'd0;
else if((cnt_ms == cnt_1ms - 1) && (cnt_us == cnt_1us - 1))
cnt_ms <= 10'd0;
else if(cnt_us == cnt_1us - 1)begin
cnt_ms <= cnt_ms + 1'b1;
cnt_1ms_done <= 1'b1;
end
else begin
cnt_ms <= cnt_ms;
cnt_1ms_done <= 1'b0;
end
end
//1s计数器
always @(posedge sys_clk or negedge sys_rstn) begin
if(sys_rstn == 1'b0)
cnt_s <= 10'd0;
else if((cnt_s == cnt_1s -1)&&(cnt_ms == cnt_1ms - 1)&&(cnt_us == cnt_1us - 1))
cnt_s <= 10'd0;
else if((cnt_ms == cnt_1ms - 1)&&(cnt_us == cnt_1us - 1))
cnt_s <= cnt_s + 1'b1;
else
cnt_s <= cnt_s;
end
//pwm_flag
always @(posedge sys_clk or negedge sys_rstn) begin
if(sys_rstn == 1'b0)
pwm_flag <= 1'b0;
else if((cnt_s == cnt_1s -1)&&(cnt_ms == cnt_1ms - 1)&&(cnt_us == cnt_1us - 1))
pwm_flag <= ~pwm_flag;
else
pwm_flag <= pwm_flag;
end
//输出pwm
always @(posedge sys_clk or negedge sys_rstn) begin
if(sys_rstn == 1'b0)
pwm<= 1;
else if(((cnt_ms <= cnt_s) && (pwm_flag ==1'b0)) ||((cnt_ms >= cnt_s)&&(pwm_flag ==1'b1)))
pwm<= 1'b0;
else
pwm<= 1'b1;
end
ila_0 u_ila (
.clk(sys_clk),
.probe0(pwm)
);
endmodule
设置ILA采样时钟为50M,如果我们想用观看完整波形的话,则需要2s/20ns=100000000个采样深度,显然这是不可能的。ILA抓取波形如下图所示:
由debug波形图可以看出,我们将采样深度设置到65536,也只能抓取完整波形的局部图,因为PWM相对于采样时钟而言太是低频信号,采样时钟在抓取PWM波形时,基本上都是抓取的重复点,因此想要正确的抓出完整的低频信号,则必须打开Capture Control 选项。
二、Capture Control 功能介绍
如图所示,打开ILA捕获模式:
在没打开捕获模式时,当触发条件满足时,波形窗口会在用户设置的触发位置上显示出:触发条件前后的波形数据,总长度为用户设置的触发深度。
在捕获模式下,用户可以设置特定的触发条件,当这些条件满足时,调试工具会捕获并记录指定的信号。这些条件可能包括特定的数据模式、信号的特定值或特定的时间间隔。一旦触发条件被满足,工具将开始捕获数据,并将其存储在内存或文件中以供后续分析。
因此,我们想要显示总长度为2s的波形数据,可以设定捕获条件,例如捕获条件为:每计数完1ms就捕获一个数据,这样我们就能显示出完整的波形图:
我们放大局部观看一下波形,可以看出每个周期的低电平都在增加,符合我们PWM的设计。
此时我们显现出了我们想要观侧的PWM波形,其采样时间可以任意调节,因此采用capture control可以采样到低频的信号。
三、Advanced Trigger功能以及TSM编写
在上面我们以及学会了ILA的高频和低频采样的使用,但是有些情况下依然不能满足我们的需求。例如:在高速串行系统中,我们想抓取第二帧的数据,其中第一帧和第二帧间隔时间不确定。我们只能设置触发帧头数据作为匹配条件,但是我们无法知道当前获取的是第几帧数据,因此就需要使用Advanced Trigger和编写触发状态机。
3.1 触发状态机的写法
- 触发状态机包含多达16种状态;
- 每种状态可包含1、2或3个条件分支;
- 在触发器状态机程序中最多可以使用4个16比特计数器;$counter0, $counter1 , , ,$counter2, $counter3
- 使用 g o t o goto goto 实现状态跳转
- 控制计数器的命令有两条:increment_counter和reset_counter;
- 触发使用trigger语句,每个状态中最后一个分支必须是goto或trigger语句;
- 计数器的判断只有等于(==)和不等于(!=);
- 在触发器状态机程序中最多可以使用4个flag来指示某些事件发生;$flag0, $flag1, $flag2, $flag3
- 在进行数值比较的时候,只有三种数据格式可以选择:b,h和u,即二进制,十六进制,和无符号数;
3.2 设置Advanced Trigger
3.3 编写触发状态机(TSM)
按照上图所示,打开ILA的高级触发选项,此时我们依然用上面的PWM测试程序,我们从程序可以知道,时钟频率50Mhz,时钟周期20ns,每计数20次为1us,每1us计数器计数1000次为1ms,每1ms计数器计数1000次为1s。此时我们想捕获第53ms里的第200us的位置,编写触发状态机程序(文件后缀为 .tsm)
#ILA TSM STATE
state tsm_state1: //定义第一个状态机
if(cnt_s == 10'u53)then //如果cnt_s为53,则跳转到状态二
goto tsm_state2;
else
goto tsm_state1;
endif
state tsm_state2: //定义第二个状态机
if(cnt_ms == 10'u200)then //如果cnt_ms为200,则触发
trigger;
else
goto tsm_state2;
endif
3.4 下载程序后,加载TSM文件并且编译
编译触发状态机文件,然后启动触发
四、总结
以上我们学会了ILA的所有功能的使用,只要把各种触发功能和怎么使用掌握了,在debug程序时才会更佳得心应手。
参考:
《UG908》
《UG936》
MicroZed Chronicles: Advanced ILA — the Trigger State Machine