VIO即虚拟输入输出单元,可以实时地监控和驱动FPGA内部的逻辑信号,本文将演示具体的调试过程。
很多时候我们需要在调程序的时候输入具体的数值,以找到最佳的参数,以往我们只能通过串口或者按键的方式将数据传输给系统,但是这就对硬件有一定的要求(必须有对应的硬件接口),而且用这种方式我们就需要额外编写对应串口的FPGA代码。 这里xilinx给了我们另一种思路,即VIO虚拟输入输出核,通过VIO,我们只需要在VIVADO 上通过JTAG数据线就可以完成上述的要求。
与ILA有不同,VIO的数据是实时的(可以显示当前的数值)而ILA只能抓取一个时间段的波形,并且VIO可以支持参数的输入,
本文在 vivado2018.3版本上 演示, 其他版本请自行研究
以下是具体的实现过程
VIO模块的添加
本文用一个计数器的简单工程来演示下 VIO功能模块的使用。
创建工程:(本文仅对VIO的部分进行介绍,对工程创建过程不熟悉的可以看工程一)
Smart ZYNQ板 工程一 用ZYNQ的PL资源点亮一个LED
这里用一个很简单的程序进行演示
`timescale 1ns / 1ps module VIO_TEST( input CLK, output LED0, output LED1 ); wire [1:0]LED_STATE;//时钟计数器 assign LED0=LED_STATE[0]; assign LED1=LED_STATE[1]; endmodule
非常简单,LED0,LED1的状态分别对应LED_STATE[0],LED_STATE[1]
我们接下来用VIO来输入LED_STATE的值。相当于用VIO来控制LED灯的亮与灭
调用VIO模块
在vivado软件中,打开IP核目录(IP Catalog),搜索VIO,如下图所示
这里 input选择2个探针,来显示2个LED的状态
output选择1个探针,来给系统输入LED_STATE的值
2个输入都设置成1位
输出的数据选择2位位宽,默认值设置成0
之后选择ok生成VIO资源
在我们之前写的代码里加入VIO模块的例化代码(例化就是生成一个实体)
vio_0 u_vio ( .clk(CLK), // input wire clk .probe_in0(LED0), // input wire [0 : 0] probe_in0 .probe_in1(LED1), // input wire [0 : 0] probe_in1 .probe_out0(LED_STATE) // output wire [2 : 0] probe_out0 );
完整代码如下:
`timescale 1ns / 1ps module VIO_TEST( input CLK, output LED0, output LED1 ); wire [1:0]LED_STATE;//时钟计数器 assign LED0=LED_STATE[0]; assign LED1=LED_STATE[1]; vio_0 u_vio ( .clk(CLK), // input wire clk .probe_in0(LED0), // input wire [0 : 0] probe_in0 .probe_in1(LED1), // input wire [0 : 0] probe_in1 .probe_out0(LED_STATE) // output wire [2 : 0] probe_out0 ); endmodule
增加约束文件
set_property IOSTANDARD LVCMOS33 [get_ports LED0] set_property IOSTANDARD LVCMOS33 [get_ports LED1] set_property IOSTANDARD LVCMOS33 [get_ports CLK] set_property PACKAGE_PIN K16[get_ports LED0] set_property PACKAGE_PIN J16[get_ports LED1] set_property PACKAGE_PIN H16[get_ports CLK]
之后点选run 和 generate bitstream进行综合 布线,和生成二进制文件
2. 下载代码
2.1 接通好JTAG 和主板,并且将主板供上电源, 点选 open target 来连接目标板子
2.2接通成功后会出现下面这个图
2.3 右键选择芯片型号,并点program device进行FPGA的代码下载(这些操作都和正常FPGA工程一致)
点选Program 下载
VIO调试
执行完之前的下载操作后,系统如果运行没问题会自动弹出一个VIO调试窗口, 如下图所示
默认调试窗口是空的没有任何参数可以调,这里点选加号,然后选中出现的所有信号,点选OK
这时候我们就得到了我们所要信号的调试窗口了
因为LED_STATE我们需要按位去调整,所以我们这里将LED_STATE的十六进制调整成二进制
准备工作做好了接下来我们来实际调试,首先没有任何动作情况下两个LED灯应该默认是熄灭的,之后我们点选LED_STATE信号的 VALUE,将信号改成10
修改之后 点选OK后,我们会发现其中一个LED(LED2)灯被点亮
此时观察我们的VIO窗口可以看到 下面两个input窗口其中一个变成1了,并且右边有个向上箭头(代表这个信号有变化,并且是由低变高)
同样我们把LED_STATE由10改成01(可以看到下面input窗口中也同样读到信号变成1和0了,并且一个带向上箭头,一个带向下箭头)
同样的LED灯和之前反向了(LED1被点亮)
VIO还有其他玩法,我们还可以将我们之前观察的信号换算成LED指示灯
将低电平设置成灰色,高电平设置成红色
同样另一个输入信号也作相同处理,得到以下的调试结果(红色和灰色,跟板子上的LED灯的亮灭对应了,让调试更为直观)
当然还有很多玩法(包括输出可以设置成按键形式的)这边只作简单演示,大家自行尝试
通过以上试验,我们可以知道VIO可以对实际运行的程序中的指定的信号进行实时的写入和读出,这大大缩短了我们在做工程时的调试时间。
以下是完整工程(仅供学习参考):