Vivado HLS 提供了多种灵活的方式来修改子函数的 interface,课程中讲解了三种方式,最后总结中的 Setting the property of reset 方式没讲。

1. Adding Registers to IO Ports

给输入输出端口添加寄存器是解决时序收敛的很有效的方式,但默认情况下 Vivado HLS 不会给我们添加寄存器的,需要我们手动在 Driective 中选择。下图中间选择 register 后相当于给输出端口添加了寄存器,对于输入端口则需要像右侧图所示,选择对应的端口名称去添加寄存器。

如下图所示修改完 Directive 后三个输入端口,return 返回值输出端口都添加了寄存器。此外,对于控制电路 ap_CS_fsm 也消耗了寄存器,总共消耗了 44 个。需要注意的是,添加IO 寄存器时需要确保 Directive 中 Interface 的 Protocol 是 ap_ctrl_hs

2. Implementing Design with Global CE

添加全局的时钟使能信号,最后生成 ap_ce 信号。具体操作是在 Solution 层面勾选 config_interface 并选中 clock_enable。通过这样,确保全局的电路只有在时钟使能的情况下才能工作。

在 GUI 中操作大致如下:右击 solution,在 General 中选择 Add,从 Command 中选中 config_interface,最后勾选 clock_enable 即可。

image-20240301105556022

3. Controlling the Number of Design IOs

以矩阵加法为例,可以通过对 for-loop 设置 pipeline 来实现低的 latency,后面课程会具体讲 for-loop 的优化方式。

设置 pipeline 的效果如下,可以看到 latency 明显降低但 IO 个数增加了些。

采用折中的方式,使用 Single Port RAM 进行约束。右击 Directive 列表中作为函数参数的数组,然后存储类型选择 RESOURCE,之后在下面的 core 中的 下拉栏中选择 RAM_1P 即可。

image-20240301104616001

可以看到左侧 port 数目不变,虽然 latency 相比纯 Pipeline 方式要高一些但仍然是比最开始的要低。

通过修改 config_rtl 可以指定状态机的编码方式,如 auto、binary、onehot 以及 gray 等,此外还可以指定 reset 方式比如是高有效还是低有效。

4. Summary

5. Demo

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "MatAdd.h"

void MatAdd(data_t mat_a[M][N], data_t mat_b[M][N], data_t sum[M][N])
{
int i = 0;
int j = 0;
loop_i:
for (i = 0; i < M; i++)
{
loop_j:
for (j = 0; j < N; j++)
{
sum[i][j] = mat_a[i][j] + mat_b[i][j];
}
}
}