5

我正在学习vivadoHLS,教程u871已经介绍了如何使用HLS,并优化了我的C/C++代码。但我想知道如何将它们加载到我的板上 zynq 7020 中,让它在板上运行。

我要实现的是:主机(板载CPU)调用PL(FPGA)进行计算,并将参数发送给PL,然后PL将结果发送回CPU。

例如,C 中的一个函数:add(int* a, int* b),它将分别添加 a[i] 和 b[i] 并返回一个数组int* 结果。,通过HLS,我可以展开for循环,这样计算起来会更快。CPU将a和b的地址发送给PL,PL计算,并将结果地址发送回CPU。

在本教程中,它只介绍了如何使用 HLS,没有解释如何通信 PL 和 CPU,或者如何将它加载到板上以便它可以在板上运行。

请推荐一个教程或告诉我在哪里学习它,非常感谢!!

4

2 回答 2

5

这是一个相当复杂的主题,因为它们是解决方案的许多变体。这部分在 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 也可以有一个中断信号。

于 2015-05-16T18:00:49.260 回答
0

正如乔纳森所想,这是一个相当复杂的主题。您可以自己完成 PL 和 CPU/RAM 之间的所有通信工作(不要忘记驱动程序开发),但您也可以尝试使用一些现有工具。例如,我们尝试过 RSoC 框架,但可能存在更多这样的“框架”。

于 2015-05-25T12:53:33.140 回答