- 软件控制:通过在嵌入式 Arm 处理器或外部 x86 处理器上运行的软件应用来控制系统,使用驱动程序来访问硬件设计的各种元件,并通过读取和写入硬件中的寄存器来控制系统中 IP 的执行。
- 自同步:在此模式下,IP 将公开各种信号,用于启动和停止内核。这些信号受系统设计的其他 IP 或其他元件驱动,此系统设计负责处理 IP 的执行。
Vivado IP 流程支持存储器、串流和寄存器接口范例,其中每个范例都支持不同接口协议与外部世界进行通信,如下表所示。请注意,虽然 Vitis 内核流程仅支持 AXI4 接口适配器,但此流程支持多种不同的接口类型。
范例 | 描述 | 接口类型 |
---|---|---|
存储器 | 内核通过存储器(如 DDR、HBM、PLRAM/BRAM/URAM)来访问数据 |
ap_memory 、bram 和 AXI4 存储器映射 (m_axi ) |
串流 | 数据将从其他串流源(如视频处理器或其他内核)串流至内核,并且可从内核向外串流。 |
ap_fifo , AXI4‑Stream (axis ) |
寄存器 | 内核通过寄存器读取和写入所执行的寄存器接口来访问数据。 |
ap_none 、ap_hs 、ap_ack 、ap_ovld 、ap_vld 和 AXI4‑Lite 适配器 (s_axilite )。 |
默认接口由顶层函数中的 C 语言实参类型和默认范例来定义,如下表所示。
C 语言实参类型 | 受支持的范例 | 默认范例 | 默认接口协议 | ||
---|---|---|---|---|---|
输入 | 输出 | 输入输出 | |||
标量变量(通过值来传递) | 寄存器 | 寄存器 | ap_none | 不适用 | 不适用 |
阵列 | 存储器、串流 | 存储器 | ap_memory | ap_memory | ap_memory |
指针 | 存储器、串流、寄存器 | 寄存器 | ap_none | ap_vld | ap_ovld |
参考 | 寄存器 | 寄存器 | ap_none | ap_vld | ap_vld |
hls::stream
|
串流 | 串流 | ap_fifo | ap_fifo | 不适用 |
Vivado IP 流程的默认执行模式为顺序执行,要求 HLS IP 完成前一次迭代后才能开始下一次迭代。这是通过 ap_ctrl_hs
块控制协议指定的。控制协议可按 块级控制协议 中指定的方式来更改。
以下代码中的 vadd
函数提供了在 Vivado IP 流程中进行接口综合的示例。
#define VDATA_SIZE 16
typedef struct v_datatype { unsigned int data[VDATA_SIZE]; } v_dt;
extern "C" {
void vadd(const v_dt* in1, // Read-Only Vector 1
const v_dt* in2, // Read-Only Vector 2
v_dt* out_r, // Output Result for Addition
const unsigned int size // Size in integer
) {
unsigned int vSize = ((size - 1) / VDATA_SIZE) + 1;
// Auto-pipeline is going to apply pipeline to this loop
vadd1:
for (int i = 0; i < vSize; i++) {
vadd2:
for (int k = 0; k < VDATA_SIZE; k++) {
out_r[i].data[k] = in1[i].data[k] + in2[i].data[k];
}
}
}
}
vadd
函数包括:
- 两个指针输入:
in1
和in2
- 指针:
out_r
,结果写入该指针 - 标量值
size
通过 Vivado IP 流程所使用的默认接口综合设置,设计将综合到含端口的 RTL 块中,如下图所示。
在默认 Vivado IP 流程中,该工具会在 RTL 上创建三种类型的接口端口,以处理数据流和控制流。
- 时钟和复位端口:
ap_clk
和ap_rst
均添加到内核中。 - 块级控制协议:
ap_ctrl
接口是作为s_axilite
接口来实现的。 - 端口级协议:这些协议是针对顶层函数和函数返回(如果函数返回值)中的每个实参创建的。如上表所述,大部分实参都使用端口协议
ap_none
,并且不含控制信号。在以上vadd
示例中,这些端口包括:in1
、in2
和size
。但是,out_r_o
输出端口使用ap_vld
协议,因此与out_r_o_ap_vld
信号相关联。
Vivado IP 流程中的 AP_Memory
ap_memory
是上表中所述存储器范例的默认接口。在 Vivado IP 流程中,它用于与存储器资源(如 BRAM 和 URAM)进行通信。ap_memory
协议同样遵循地址和数据阶段方式来进行操作。该协议首先请求读/写资源,并等待至它收到资源可用确认为止。随后,它会发起读/写的数据传输阶段。
ap_memory
的重要注意事项之一是它仅执行单节拍数据传输并传输至单一地址,这有别于 m_axi
,后者可执行突发访问。因此,相比其他协议,ap_memory
属于轻量级协议。
- 存储器资源:默认情况下,Vitis HLS 会实现协议以便与单端口 RAM 资源进行通信。您可在 INTERFACE 编译指示或指令中指定
storage_type
来控制该协议的实现。storage_type
指令允许您显式定义使用的 RAM 类型,以及所创建的 RAM 端口(单端口或双端口)。如果不指定storage_type
,那么 Vitis HLS 会使用:- 单端口 RAM(默认情况下)。
- 双端口 RAM,前提是这样可缩短启动时间间隔或减少时延。
Vivado IP 流程中的 M_AXI 接口
m_axi
) 接口允许 IP 读取和写入全局存储器(DDR、HBM 或 PLRAM)中的数据,存储器映射接口是跨多个 IP 共享数据的便利方法。以下列出了 m_axi
接口的主要优势: - 每个接口均有独立的读取通道和写入通道
- 它支持基于突发的访问
- 它可提供未完成传输事务队列
- 认识突发访问
-
AXI4 存储器映射接口支持高达 4K 字节的高吞吐量突发,且只需单一地址阶段即可。对于突发模式传输,Vitis HLS 会使用单一基址读取或写入数据,后接多次顺序数据采样,因此,该模式支持更高的数据吞吐量。使用 C
memcpy
函数或经流水打拍的for
循环时,即可执行突发模式操作。如需了解更多信息,请参阅 控制 AXI4 突发行为 或 AXI 突发传输。 - 自动端口拓宽和端口宽度对齐
-
如 端口宽度自动调整 中所述,Vitis HLS 能够自动拓宽端口宽度以便执行数据传输,并改善突发访问,前提是突发的所有前置条件均得到满足。在 Vivado IP 流程中,默认情况下,以下配置设置会禁用端口宽度自动调整。要启用此功能,必须更改这些配置选项(请注意,其中一条命令指定为位,另一条命令则指定为字节):
syn.interface.m_axi_max_widen_bitwidth=0 syn.interface.m_axi_alignment_byte_size=0
- 为 Vivado IP 模式指定对齐
-
m_axi
端口的对齐允许该端口根据指定对齐方式来读取和写入存储器。选择正确的对齐方式之所以如此重要,是因为最好情况下,它会影响性能,最差情况下,则会影响功能。对齐的存储器访问意味着指针(或数据起始地址)是特定类型的值(称为对齐)的倍数。对齐是自然地址倍数,其类型必须或者应该存储在存储器上(例如,出于性能原因)。例如,标准 32 位架构在存储器中存储的数据字为 32 位,每个字均为 4 字节。此数据对齐到单个字或 4 字节边界。
对齐方式在整个系统中应保持一致。当 IP 在 AXI4 主模式下工作时,即可确定并且应该指定对齐方式,如采用 4 字节对齐的 32 位架构。当此 IP 在从模式下工作时,对齐应与主模式对齐方式相匹配。
- 偏移规则
-
m_axi
偏移默认设置为 offset=direct 和 syn.interface.default_slave_interface=s_axilite。但在 Vivado IP 流程中,您可按 偏移和操作模式 中所述方式对其进行更改。 - 捆绑接口 - 性能对比资源使用情况
-
默认情况下,Vitis HLS 将具有兼容选项的函数实参组合到单个
m_axi
接口适配器中,如 M_AXI 捆绑 中所述。将端口捆绑到单个接口中可消除 AXI4 逻辑,因而有助于节省器件资源,在拥塞的设计内工作时可能需要这些资源。但是,单一接口捆绑可能会限制 IP 性能,因为所有存储器传输都必须穿越单个接口。
m_axi
接口具有独立的读取 (READ) 和写入 (WRITE) 通道,因此单个接口即可同时执行读取和写入,但仅限单一位置。使用多个捆绑即可创建多个接口以连接到存储体,从而能够改善性能。
Vivado IP 流程中的 S_AXILITE
在 Vivado IP 流程中,默认执行流程由寄存器读取和写入通过 s_axilite
接口使用默认 ap_ctrl_hs
控制协议来进行管理。此 IP 由软件控制,方法是读取和写入 s_axilite
接口的控制寄存器,如 S_AXILITE 控制寄存器映射 中所述。
s_axilite
接口可提供下列功能特性:
- 控制协议
- 采用 块级控制协议 中指定的块控制协议。
- 标量实参
- 来自顶层函数的标量实参可映射到
s_axilite
接口,此接口会为值创建寄存器,如 S_AXILITE 控制寄存器映射 中所述。软件可对此寄存器空间执行读/写操作。 - 偏移规则
- Vivado IP 流程可以基于顶层函数中关联的 C 语言实参的数据类型来定义端口的大小或分配给端口的地址范围。但该工具还允许您手动定义偏移大小,如 S_AXILITE 偏移选项 中所述。
- 捆绑规则
- 在 Vivado IP 流程中,您可使用
s_axilite
接口来指定多个捆绑,这样将为您定义的每个捆绑创建一个独立的接口适配器。但您应熟悉一些有关使用多个捆绑的规则,如 S_AXILITE 捆绑规则 中所述。
Vivado IP 流程中的 AP_FIFO
在 Vivado IP 流程中,ap_fifo
接口协议是默认接口,用于供该接口上的串流范例与存储器资源 FIFO 进行通信,并用作为 IP 内不同函数之间的通信通道。仅当数据采用顺序访问时,才应使用此协议,并且 AMD
强烈建议使用 hls::stream<data type>
,它可实现 FIFO。
<data type>
不应与 T_data_type
相同,后者应仅限在接口上使用。Vivado IP 流程中的 AXIS 接口
AXI4‑Stream 协议 (axis
) 可作为备选用于串流接口,该协议定义了一条单向通道用于按顺序串流数据。不同于 m_axi
协议,AXI4‑Stream 接口可突发的数据量是无限的,故而能显著提升性能。不同于需要地址才能读/写存储器的 AXI4 存储器映射接口,axis
接口可直接将数据传递至另一个 axis
接口,无需地址,因此使用的器件资源更少。通过将这些功能特性相结合,即可使串流接口成为轻量级高性能接口,如 AXI4-Stream 接口 中所述。