亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> VHDL

使用集成逻辑分析器 (ILA) 和虚拟输入/输出 (VIO)

本教程介绍如何使用集成逻辑分析仪 (ILA)虚拟输入/输出 (VIO) 在 Xilinx Vivado IDE 中调试和监控您的 VHDL 设计的内核。

在许多情况下,设计人员需要执行片上验证。也就是说,为了验证目的,在他们的 FPGA 设计中访问内部信号的行为。

一种选择是将这些信号带到 FPGA 引脚并将它们连接到 LED 以直观地查看它们的行为。此选项简单、快速且适用于简单案例,但不灵活、可扩展或不现实。

另一种选择是拥有一个具有高级功能的外部逻辑分析仪,可以显示和描绘这些信号的行为,但它需要外部且相对昂贵的设备。

集成逻辑分析仪 (ILA) 是一种结合了先前两种选择的优点的替代方案。它简单、快速、灵活,并具有许多高级功能,可帮助设计人员快速查看和检查所选信号的行为。

概述

本文包含来自 Vivado GUI 的多个屏幕截图。 点击图片放大!

使用侧边栏浏览大纲 对于本教程,或者如果您使用的是移动设备,请向下滚动并单击右上角的弹出导航按钮。

ILA 和 VIO

ILA 和 VIO 是 Xilinx 的免费可定制 IP。 ILA IP 可帮助您轻松探测 FPGA 内部的内部信号,并将它们带入类似模拟的环境中,以监控它们并验证它们的行为。

与 ILA 不同,VIO IP 允许您虚拟驱动 FPGA 内部的内部信号,以刺激或控制您的设计,例如驱动 RESET 信号。

要求

  1. Xilinx FPGA 板
  2. Vivado 设计套件
  3. VHDL 基础知识

我使用的是 Kintex-7 FPGA KC705 评估套件,但本教程中显示的方法应该适用于任何现代 Xilinx FPGA 板。

下载示例项目

您可以使用下面的表格下载示例项目和 VHDL 代码。它应该在 Vivado 2020.2 或更高版本中工作。

提取 Zip 并打开 ila_tutorial.xpr 在 Vivado 中的文件以查看示例设计,或阅读本文的其余部分以学习从头开始创建它。

使用 Vivado 创建项目

首先打开 Vivado。在 Vivado 的欢迎屏幕中,单击 创建项目 按钮。

点击下一步 继续。

将项目名称更改为 ila_tutorial 并点击下一步。

注意: 不要在项目名称中使用空格。而是使用下划线或破折号。

选择RTL 项目 并取消选中此时不要指定来源 然后点击下一步 继续。

添加源文件; counter.vhdlcounter_top.vhdl 从设计文件夹。选择 VHDL 为目标语言。勾选将源代码复制到项目中 然后点击下一步 继续。

添加约束文件top.xdc 从设计文件夹。检查将约束文件复制到项目中 然后点击下一步 继续。

注意: 此约束文件特定于 KC705 板。您需要更改 clk 引脚led 引脚 根据你的董事会。还有,-时期 你的董事会时钟。

搜索您的板并从列表中选择它。点击下一步 继续。

这是新建项目向导的最后一个屏幕。点击完成 打开你的项目。

设计实例说明

我们将在本教程中使用一个简单的双计数器链示例。

counter.vhdl 文件包含一个普通的 4 位计数器的 RTL 代码,该计数器在启用时从 0 计数到 15。当计数在 12 和 15 之间时,它断言 1 位输出。对于所有其他值,输出保持 低“0” .

这是计数器模块的实体接口。

----------------------------------------------------------------------------
-- ENTITY DECLARATION.
----------------------------------------------------------------------------
  ENTITY counter IS
    PORT(clk     : IN  STD_LOGIC;  -- Main clock 
         reset   : IN  STD_LOGIC;  -- reset, active_high
         enable  : IN  STD_LOGIC;  -- enable the next counter
         trigger : OUT STD_LOGIC   -- trigger the next counter
        );
  END ENTITY;

计数器设计有两个内部信号:count trigger_o .

- 计数 用于实现计数功能。

– 和 trigger_o 是连接输出端口触发器的中间信号 .

不用担心属性 ,后面会解释。

----------------------------------------------------------------------------
-- ARCHITECTURE DECLARATION.  
----------------------------------------------------------------------------
  ARCHITECTURE rtl OF counter IS

    -- INTERNAL SIGNALS DECLARATION --
    SIGNAL count     : UNSIGNED(3 DOWNTO 0) := (OTHERS => '0');
    SIGNAL trigger_o : STD_LOGIC := '0';
  
    -- ATTRIBUTE DECLARATION --  
    ATTRIBUTE MARK_DEBUG : STRING;
    ATTRIBUTE MARK_DEBUG OF count : SIGNAL IS "true";

在下面的清单中,我们看到了计数器的实现。 seq_proc 进程在输入端口的上升沿触发 clk 并在输入端口reset 时处于复位模式 是高'1'。

计数 当输入端口 enable 时信号递增 为高“1”,trigger_o 当信号 count 的值时,信号被置为高电平 介于 12 到 15 之间。

seq_proc: PROCESS (reset, clk)
BEGIN -- for seq_proc
  IF (reset = '1') THEN
    count     <= (OTHERS => '0');
    trigger_o <= '0';
  ELSIF rising_edge(clk) THEN
    IF (enable = '1') THEN
      count <= count + 1;
      IF (count > x"B" AND count <= x"F") THEN
        trigger_o <= '1';
      ELSE
        trigger_o <= '0';
      END IF;
    END IF;
  END IF;
END PROCESS;

文件 counter_top.vhdl 包含两个顺序连接的计数器瞬间。

counter_1_inst 始终启用,它为 counter_2_inst 提供时钟 .即输出端口触发器 counter_1_inst 连接到输入端口 clk counter_2_inst .

– 结果行为是 counter_1_inst 激活 counter_2_inst 16 个时钟周期中只有 4 个。因此,counter_2_inst 每 16 个计数将增加其计数器四次。

为 RESET 创建 VIO 内核

现在您已经了解了设计示例,我们将创建一个 VIO 来控制输入端口 reset .这将使我们能够从 Vivado IDE 操作(切换)重置,以便我们可以手动控制何时启动/停止计数器。

点击IP目录 ,然后搜索 VIO ,然后双击VIO(虚拟输入/输出) .

首先,我们把名字改成vio_reset .

其次,我们只需要一个用于复位的输出端口,所以我们在输入探针计数框中输入0, 我们在输出探针计数框中输入 1 .

点击PROBE_OUT 端口选项卡。由于 reset 是一个 1 位信号,我们将 1 放入 probe_width 框中, 我们还将 0x1 放入初始值框 所以它以高“1”开头。然后点击确定生成 . Vivado 现在将开始合成 VIO。

在 Vivado 完成 VIO 综合后,我们需要通过为它声明一个组件并在 counter_top.vhdl 中实例化它来将它添加到我们的设计中 文件如下。

首先,为 vio_reset 添加组件声明 在 counter_top.vhdl 的组件声明部分中 文件。

  -- Declare vio_reset
  COMPONENT vio_reset
    PORT(
      clk        : IN STD_LOGIC;
      probe_out0 : OUT STD_LOGIC_VECTOR(0 DOWNTO 0)
    );
  END COMPONENT;

现在,VIO 已经完成,我们准备好综合设计。但在此之前,我们需要更改合成设置 flatten_hierarchy .

点击运行合成 然后确定 .

当 Vivado 完成综合后,点击 Open Synthesized Design .

将布局更改为 debug 通过点击布局 然后调试 .

插入调试探测流程

我们的合成设计现在包含 vio_reset 例如,是时候指定我们想要探测的信号了。有以下三种方法:

  1. 从 VHDL 文件插入
  2. 从网表插入
  3. 从 xdc/tcl 文件插入

我们将使用前两种方法,将第三种方法留给以后的教程。

从 VHDL 文件插入

这种方法是插入探针最简单、最快的方法,尤其是当它是复合类型(数组或记录)时。但这需要在设计文件中添加代码,VHDL 代码在实际产品中是多余的。

我们可以通过以下方式在 VHDL 设计文件中插入探针:

  1. 声明一个名为 MARK_DEBUG 的特殊属性
  2. 使用此属性附加我们要探测的信号
  3. 并通过将其设置为“true”来激活它,如下所示:
    -- ATTRIBUTE DECLARATION --  
    ATTRIBUTE MARK_DEBUG : STRING;
    ATTRIBUTE MARK_DEBUG OF count : SIGNAL IS "true";

注意: 我们只需要在每个 VHDL 设计文件中声明一次属性,就可以将它附加到多个信号上。

我们可以从综合设计中看到,信号 count 在两个 counter_1_instcounter_2_inst 列在未分配的调试网络下 并在 Netlist 中都标有错误图标 和原理图 .

从网表插入

这种插入方法也很简单,但需要先综合设计,然后手动点击每个信号进行标记以进行调试。如果设计很大并且您想要监控许多信号,这可能会让人筋疲力尽。

我们将探测输出端口触发器 在两个计数器中使用 Netlist .我们可以从 Netlist 窗口 执行此操作 或原理图 通过定位信号网络,然后右键单击 在其上并选择 Mark Debug .

在 Netlist 窗口中,找到 trigger counter_1_inst → 篮网 → 触发 .然后,右键单击它并选择标记调试 .

在 Schematic 窗口中,找到 trigger counter_2_inst 的输出 .然后,右键单击它并选择标记调试 .

我们可以看到它们现在列在 Unassigned Debug Nets 下 .

创建 ILA 调试核心

现在是创建 ILA 调试核心的时候了。我们需要为要分析的每个信号创建一个探针。最简单的方法是利用 Vivado 向导 设置调试 .

点击设置调试 然后点击下一步 .

Vivado 将列出所有调试信号并自动为您捕获时钟域。在这里,我们看到列出了我们的四个信号。您可以删除您不感兴趣的信号或添加额外的信号,但我们将使用所有这些信号。

注意: 我们不必使用我们标记为 Debug 的所有信号。

点击下一步 .

现在我们通过选择 FIFO 深度 来配置 ILA 并检查捕获控制 .我们可以将 FIFO 保留在 1024,因为它对于我们的示例来说已经足够了。

点击下一步 .

现在我们看到 Vivado 找到了一个时钟并将创建一个调试内核。

点击完成 .

我们现在可以看到一个 ILA 调试核心,其中添加了四个探针到 调试选项卡网表窗口 .

重要提示: 在此阶段保存约束非常重要,因此可以将其添加到设计中。否则,我们可能会失去 ILA 核心。

点击保存 图标或按 Ctrl+S。

将文件命名为 ila_core 并点击确定 .

ila_core.xdc 文件将被添加到约束中,其中包含 ILA 的代码和设置。

让我们看一下文件内容。您可以通过转到 Source 窗口 → 展开约束文件夹 → 展开 constr_1 来打开文件 .

首先,我们看到该文件将调试属性添加到我们使用网表插入标记为调试的信号。

接下来,我们将看到 ILA 核心的创建和配置。

接下来,我们查看每个探针的创建、配置和连接。

接下来,我们将看到调试中心 (dbg_hub )。

调试中心负责 Vivado IDE 和调试内核(ILA 和 VIO)之间的通信。我们看到它定义了一个时钟频率(默认为 300 MHz)。您需要更改该时钟以匹配您的时钟频率并保存文件。

注意: 连接到 ILA 和 Debug_hub 的时钟必须是自由运行的时钟。

现在,ILA 已完成并保存。我们需要重新运行综合,以便将 ILA 添加到综合设计中。

点击运行合成 然后确定 .

当 Vivado 完成综合运行后,点击 Open Synthesized Design 然后在 原理图 .

现在我们可以看到,Vivado 已将 ILA 和 Debug_Hub 添加到我们的设计中,并将调试信号连接到 ILA 探针。

现在我们已经准备好实现我们的设计并生成比特流,这样我们就可以测试我们的设计了。

点击运行实现 然后确定 .

在 Vivado 完成运行实施后,点击 Generate Bitstream 然后确定 .

Vivado 完成生成比特流后,点击打开硬件管理器 然后在打开目标, 最后是自动连接 .

接下来,我们需要使用位文件 (*.bit) 和调试探针文件 (*.ltx) 对 FPGA 进行编程。 Vivado 会自动为您找到它们。

点击编程设备 然后在 程序 .

配置 ILA 触发器

对器件进行编程后,我们可以看到 Vivado 的 GUI 布局发生了变化,并且出现了一个新的 hw_ila_1 仪表板已打开,包含多个窗口。

我们会尽量减少一些我们不需要的窗口,以便我们可以舒适地工作。

从仪表板选项中,检查 hw_vio_1 并取消选中捕获设置 .

另外,关闭 hw_vios 选项卡,因为当我们检查 hw_vio_1 ,它已被添加到触发器设置 窗口。

现在,我们需要添加 reset 按钮到 VIO,以便我们可以控制 reset .

点击 hw_vio_1 然后添加 重置 如下图所示。

我们可以看到 hw_vio_1 现在包含 reset 探测。

改变reset的值 如果不是 1,则在 vio_reset 中设置为 1。

现在,我们将添加我们将使用的触发器。触发信号值的变化将导致 ILA 开始记录探测信号。

假设我们要在输出端口的上升沿触发(开始录制)trigger counter_1_inst .为此,请按以下步骤操作:

  1. 转到触发器设置 - hw_ila_1 窗口
  2. 点击+ 图标以添加新触发器并选择 counter_1_inst/trigger 并点击确定。

  1. 我们可以看到已经添加了触发器,现在我们需要设置条件。点击值框 并选择 R(0 到 1 过渡) .点击操作符框 并选择 ==(equal)

我们还将触发位置更改为 32,这意味着它将记录触发事件之前的 32 个样本以及之后的样本。

现在,触发器已设置好并准备就绪。

现在,我们转到波形窗口 添加我们要查看的信号。首先,让我们最大化内部窗口以获得更好的视图。

其次,我们需要在探针中添加一些缺失的信号。 Vivado 通常会自动添加所有分配的信号,但在这种情况下,它没有。

现在,我们改变 count 的基数 向 Unsigned 发出信号,因为它更容易理解。

右键单击计数 信号名称,然后选择 radix 然后 无符号 .

运行 ILA 和 VIO

现在,我们已经完成了 ILA 的配置和自定义,可以运行它了。

ILA 有两种运行模式:立即 触发器 .

立即模式

立即模式立即触发 ILA 并直接开始记录样本,直到 FIFO 已满。

点击立即运行触发器 按钮。

我们现在可以在波形窗口中看到记录的样本。我们看到这两个 count 信号为 0, 和两个触发器 信号为低“0” 因为重置 处于活动状态。

触发模式

触发模式要求我们为至少一个触发器设置条件并对其进行布防。 ILA 会一直等待武装触发器的条件变为真,然后它会直接开始记录样本,直到 FIFO 已满。

我们已经添加了触发器并将其设置为 R(0 to 1 transition) .

使用一个触发器运行 ILA

更改重置 返回1 来自 vio_reset .

点击窗口状态 hw_ila_1 .我们看到核心状态是Idle 因为没有触发器武装。点击运行触发器 按钮,这将触发触发器。

我们现在看到核心状态变为等待触发 .作为重置 高,我们的触发信号(端口 trigger counter_1_inst ),而 ILA 正在等待。

现在,让我们更改 reset 0 以便计数器开始工作。

我们现在看到 ILA 已被触发并记录了样本,并且核心状态变回 Idle .

我们在触发信号(端口 trigger 的上升沿看到红色垂直线(标记) counter_1_inst ),并且它位于 位置 32 .我们还可以验证信号 count 行为正确且信号 counter_1_inst/trigger 在 12 到 15 之间的四个时钟周期为高电平(输出延迟一个时钟周期)。

如果我们稍微缩小一点,我们也可以验证 count 的行为 触发 counter_2_inst 的信号 .

使用多个触发器运行 ILA

我们可以将触发器组合用于复杂或高级条件。要在同一个波形中捕获多个不相交的时间帧,我们可以使用多个重复触发的触发器。

例如,假设我们要在 count 时触发 来自 counter_1_inst 的信号 等于 9 (count ==9) 并且当 count 来自 counter_2_inst 的信号 大于 2(计数> 2)。为此并将 FIFO 拆分为四个时间窗口,请执行以下步骤:

  1. 更改重置 返回1 来自 vio_reset
  2. 移除之前的触发探针:

  1. 同时添加 count 信号作为触发器:

  1. 配置信号计数 对于 counter_1_inst 到(计数 ==9):

  1. 配置信号计数 对于 counter_2_inst 到(计数> 2):

  1. 将窗口数量配置为4 和 FIFO 深度为 256, 并定位到 32 .

  1. 点击运行触发器 按钮,这将触发触发器。请注意,在窗口 Status hw_ila_1 ,捕获状态现在是 window 1 of 4 因为我们有四个窗口。

更改重置 返回0 来自 vio_reset .

最大化波形窗口。我们现在看到我们有四个窗口和一个与每个窗口关联的触发器。请注意,这些窗口是独立的而不是连续的。

ILA 等待触发事件发生,当触发事件发生时,ILA 使用第一个窗口记录 256 个样本。然后它立即等待下一次触发,直到所有窗口都满了。

以自动重新触发模式运行 ILA

ILA 有一个很好的功能,叫做自动重新触发 这将在触发后自动触发触发器。当监视很少发生的事件并且您想在一夜之间运行测试时,它很有用。或者您可以在触发频繁且快速以至于您无法手动触发触发以重复捕获样本时使用它。

让我们假设输出端口 trigger counter_2_inst3 小时断言一次, 并且您想在每次发生时记录数据。要使用自动触发器,请按以下步骤操作:

  1. 更改重置 返回1 来自 vio_reset
  2. 移除之前的触发探针
  3. 添加 trigger_2_OBUF 信号作为触发器:

  1. 将触发器配置为等于 (==) 和下降沿 F(1 到 0 转换)
  2. 将窗口数量配置为1 和 FIFO 深度为 1024, 并定位到 32:

  1. Click on Auto re-trigger button:

  1. Finally, change reset back to 0 from vio_reset:

We can see now that the waveform window is getting refreshed and updated as the trigger happen. It is fast, but the behavior is noticeable.

Click on Stop trigger and toggle Auto re-trigger .

Running ILA with Capture mode

Another feature of ILA is the Capture mode . In some cases, you are not interested in recording all the data but rather capture a specific sample. Capture mode helps you filter out data and record only the samples you are interested in.

Let’s say we are only interested in sampling when the output port trigger of counter_1_inst is ‘1’ AND the output port trigger of counter_2_inst is ‘0’.

To use Capture mode to achieve this, follow these steps:

  1. Change reset back to 1 from vio_reset
  2. Remove the previous trigger probe
  3. From the dashboard, Uncheck Trigger Setup and check Capture Setup . Notice that a Capture Setup window will appear. From the Settings – hw_ila_1 window, Change Capture mode to BASIC , the window to 1, the FIFO depth to 1024, and position to 1:

  1. Add trigger_2_OBUF , and counter_1_inst/trigger from the Capture Setup window:

  1. Configure counter_1_inst/trigger to the condition equal (==) and 1 (logical one) :

  1. Configure trigger_2_OBUF to the condition equal (==) and 0 (logical zero) :

  1. Change the Capture Condition to Global AND :

  1. Click on the Run trigger button and then change reset 0 from vio_reset :

As we can see from the image below, the waveform has only recorded data when counter_1_inst’s count signal is 13, 14, 15, or 0. Any other counts are filtered out because counter_1_inst/trigger is high on these counts only.

Conclusion

In this tutorial, we learned about ILA and VIO and different use-cases for them. ILA and VIO are excellent options for on-chip debugging. They are free, easy to use, flexible, scalable, and simple yet offer advanced features. The use of multiple triggers and Capture mode helps you achieve a complex debugging scheme.


VHDL

  1. 教程 - 编写组合和顺序代码
  2. 云无限,以及超越
  3. 集成电路
  4. C# 基本输入和输出
  5. C++ 基本输入/输出
  6. C 输入输出 (I/O)
  7. Python 输入、输出和导入
  8. Java 基本输入和输出
  9. Python 和 Raspberry Pi 温度传感器
  10. D 锁存器
  11. C - 输入和输出
  12. RightHand Robotics 和 Element Logic 推出集成机器人分拣解决方案