3 “Hello, world”测试
3.1 目标
Xillybus 是一种用作逻辑设计构建模块的工具。因此,了解 Xillybus 功能的最佳方式是将它集成到您自己的用户应用逻辑中。demo bundle 的目的是作为使用 Xillybus 的起点。
因此,demo bundle 实现了最简单的应用: 两个设备文件之间的环回(loopback)。这是通过将 FIFO 的两端 连接到 FPGA 内部的 Xillybus IP 核来实现的。结果,当主机向一个设备文件写入数据时,FPGA 通过另一个设备文件将相同的数据返回给主 机。
以下章节将说明如何测试这一简单功能。该测试是验证 Xillybus 正确运行的简单方法: FPGA 中的 IP 核按预期工作,主机 正确检测到 PCIe 外设,并且驱动程序已正确安装。此外,通过对 FPGA 中的逻辑设计进行小的修改,该测试也是一个学习 Xillybus 工作原 理的机会。
作为第一步,建议先用 demo bundle 进行简单的实验,以理解 FPGA 中的逻辑与设备文件如何协同工作。这通常足以阐明 如何针对您自己的应用需求使用 Xillybus。
除了上面提到的环回之外,demo bundle 还实现了 RAM 和另一个环回。后者将在下文简要讨论。关于 RAM,它演示了如何 访问存储器阵列或寄存器。更多信息见第 3.4 节。
3.2 准备工作
“Hello, world”测试包括在命令提示符(Command Prompt)窗口中运行简单的命令行程序。
首先,下载 Xillybus 的 Windows 程序包。这是一个 zip 文件,可在提供驱动程序的同一网页上找到。该 zip 文件包含这些程 序的源代码以及可直接运行的可执行二进制文件。
最简单的方法是使用可执行二进制文件来执行“Hello world”测试。不过,也可以编译这些程序,详见第 4.2 节。
另一种可能性是创建一个类似 Linux 的工作环境,如第 4.3 节所述。如果选择这种 方式,请按照 在 Linux 主机上入门 Xillybus 指南中的“Hello world”测试说明进行操作。
3.3 简单的环回测试
下面展示一个使用两个命令提示符窗口进行环回测试的简单示例。
打开一个普通的命令提示符窗口,将目录切换到 Xillybus 的 Windows 程序包中的 “precompiled-demoapps” 子目录。若要使 用自己编译的结果(如第 4.2 节所示),请切换到 XP32_DEBUG 目录。
在该命令提示符窗口中键入以下内容:
> streamread \\.\xillybus_read_8
这会使 “streamread” 程序打印出它从 xillybus_read_8 设备文件中读取的所有内容。目前预期不会发生任何操作。
注意,反斜杠没有重复。如果在 Cygwin 下执行(而非在普通的命令提示符窗口中),则应为 \\\\.\\xillybus_read_8。
现在打开另一个命令提示符窗口。切换到与第一个命令提示符相同的目录,然后键入:
> streamwrite \\.\xillybus_write_8
该命令会将第二个窗口中键入的任何内容发送到设备文件(即 \\.\xillybus_write_8)。
在第二个命令提示符窗口中键入一些文本,然后按 ENTER。相同的文本将出现在第一个命令提示符窗口中。注意,在按下 ENTER 之前不会发送任何内容。这与标准输入的预期行为一致。
如果尝试这两个命令时收到错误消息,建议执行以下操作:
-
检查拼写错误。
-
确认驱动程序已安装且 FPGA 被检测为 Xillybus 设备: 打开设备管理器并与第 2.1 节的最后一张图片进行比 较。
-
如第 2.3 节所述,检查事件查 看器中是否有错误。
-
确认设备文件已创建,如第 2.2 节所述(搜索 xillybus_read_8 和 xillybus_write_8)。
注意,FPGA 内部的 FIFO 不会发生上溢(overflow)或下溢(underflow): 核会尊重 FPGA 内部的 ‘full’(满)和 ‘empty’(空)信号。必要时,Xillybus 驱动程序会强制计算机程序等待,直到 FIFO 准备好进行 I/O。这称为阻塞(blocking), 即强制用户空间程序休眠。
另外注意,streamwrite 分别处理每一行,并且在按下 ENTER 之前不会向 FPGA 发送任何内容。这与 Linux 下同名的程序 不同。
还有另一对具有环回连接的设备文件: xillybus_read_32 和 xillybus_write_32。这些设备文件以 32 位字为单位工作,FPGA 内部的 FIFO 也是如此。使用这些设备文件进行 “hello world” 测试将产生类似的行为,但有一个区别: 所有 I/O 都以 4 字节的组 为单位进行。因此,当输入未达到 4 字节边界时,输入的最后一个字节将不会被传输。
3.4 存储器接口
memread 和 memwrite 程序更有意思,因为它们演示了如何访问 FPGA 上的存储器。这是通过对设备文件调用 _lseek() 函数来实现 的。Xillybus Windows 主机应用程序编程指南 中有一节解释了与 Xillybus 设备文件相关的此 API。
注意,在 demo bundle 中,只有 xillybus_mem_8 允许寻址(seeking)。该设备文件也是唯一一个可以同时以读写方式打开 的文件。
在本节中,使用名为 “hexdump” 的工具来显示 FPGA 的 RAM 内容。该工具可在 Xillybus 的 Windows 程序包的 “unixutils” 子目录中找到。另外,第 4.3 节提供了获取该工具的 其他选项。
在写入存储器之前,可以先使用 hexdump 观察现有情况。
> hexdump -C -v -n 32 \\.\xillybus_mem_8 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020
输出为存储器阵列的前 32 个字节: hexdump 打开了 xillybus_mem_8 并从此设备文件中读取了 32 个字节。当打开允许 _lseek() 的文件时,初始位置始终为零。因此输出由存储器阵列中位置 0 到位置 31 的数据组成。
您的输出可能不同: 该输出反映了 FPGA 的 RAM,其中可能包含其他值。特别是,由于先前对 RAM 的实验, 这些值可能不为零。
关于 hexdump 的几个标志: 上面显示的输出格式是 “-C” 和 “-v” 的结果。“-n 32” 表示仅显示前 32 个字节。存 储器阵列只有 32 字节长,因此读取更多内容没有意义。
可以使用 memwrite 更改阵列中的值。例如,将地址 3 处的值更改为 170(十六进制 0xaa),命令如下:
> memwrite \\.\xillybus_mem_8 3 170
为了验证命令是否生效,可以重复上面的 hexdump 命令:
> hexdump -C -v -n 32 \\.\xillybus_mem_8 00000000 00 00 00 aa 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020
可见命令生效了。
在 memwrite.c 中,关键部分是 “_lseek(fd, address, SEEK_SET)”。该函数调用会更改设备文件的位置。因此,这会改变 FPGA 内部所访问的阵列元素的地址。随后的读操作或写操作将从该位置开始。每次这样的访问都会根据所传输的字节数增加位置。
允许寻址的设备文件对于轻松向 FPGA 发送配置命令也很有用。这可以通过在 FPGA 中放置寄存器而不是存储器阵列来实 现。以下是一个寄存器的示例,它在对地址 2 进行写操作时接收新值:
reg [7:0] my_register;
always @(posedge bus_clk)
if (user_w_mem_8_wren && (user_mem_8_addr == 2))
my_register <= user_w_mem_8_data;
同样,可以通过在 FPGA 逻辑中使用 “case” 语句来读回寄存器的值。
