这是一个相当复杂的主题,因为它们是解决方案的许多变体。这部分在 ug871 的第 2 章中有介绍,但不幸的是它使用了 EDK 而不是 Vivado。不过,Vivado HLS 概念是相同的。你也可以看看xapp890。
基本上,Zynq 使用 AXI 端口连接到 PL。AXI 端口是经典的地址+数据总线。AXI 有 2 种类型,标准和精简版。lite 版本不支持突发,专注于以性能为代价使用更少的区域,通常用于寄存器接口。标准 AXI 具有非常高的性能并支持突发,您通常使用它来连接 DDR 内存。
Zynq 有多个 AXI 端口,作为主端口和从端口。从端口允许您的 IP 读取/写入 Zynq 的内存空间。主端口允许 Zynq 读取/写入内核的内存空间。几个端口有不同的性能,GP 应该用于低性能的 AXI-Lite,HP 到 IP 需要更直接地访问 Zynq DDR 内存。
连接 IP 的最简单方法是使用 AXI-lite。在 Vivado HLS 中,在地址 0 处定义寄存器 a,在地址 4 处定义寄存器 b,在地址 d 处定义寄存器 c(答案)。函数 add 看起来像:
int add(int a, int b)
{
volatile int *my_ipaddr = MY_IP_BASEADDR; // Address is configured in Vivado block design
*(my_ipaddr+0) = a;
*(my_ipaddr+1) = b;
return *(my_ipaddr+2);
}
由于我不使用 Vivado HLS,我不知道该怎么做。但略读ug871,它涵盖了AXI-Lite 寄存器接口。
第三种类型的 AXI 称为 AXI-Stream。它是一个没有地址的通信总线,只有带有一些标志的数据存在以同步流。它通常用于不关心地址的内核之间或与 AXI-DMA 引擎一起使用。主要问题是您无法将 AXI-Stream 直接连接到 Zynq、AFAIK。
一个示例应用程序是 xapp890,尽管它们使用 Video-DMA 内核,因为它是一个视频应用程序。它提供了更高性能的解决方案。在您的示例中,它将有一个输入从 AXI-Stream 来接收 a/b,以及一个输出主 AXI-Stream 来返回 c。您可以将内核与 AXI-DMA IP 内核连接起来,伪代码将是:
void add(int *ab, int *c, unsigned int length)
{
XAxi_Dma_Start_Transfer((void *)ab, length, CHANNEL_MM2S); // Not actual function, MM2S stands for memory to stream
XAxi_Dma_Start_Transfer((void *)c, length, CHANNEL_S2MM); // S2MM = stream to memory
while(XAxi_Dma_Transfer_Done == 0) {} // Wait end of transfer
}
这是很多信息,但希望它能让您理解应用笔记。总而言之,您的 IP 必须提供 AXI(Lite,流标准)接口来交换数据,您将其连接到 Zynq AXI 端口。此外,您的 IP 也可以有一个中断信号。