Quick Start:快速上手 Vivado HLS
本指南将带领你从零开始,使用 Vivado HLS(High-Level Synthesis)工具,通过编写 C 语言代码快速生成 FPGA 加速器。整个过程包括安装、项目创建、代码编写、仿真与综合,最终实现一个简单的向量加法加速器。请按照以下步骤操作,确保每个环节无误。
前置条件
- 操作系统:Windows 10 或 Linux(Ubuntu 18.04/20.04 推荐)。
- 硬件:至少 8 GB 内存,50 GB 可用磁盘空间。
- 工具:Vivado Design Suite 2019.1 或 2020.1(包含 HLS 组件)。
- 基础:了解 C 语言基本语法,熟悉 FPGA 基本概念(如流水线、接口)。
目标与验收标准
完成本指南后,你将能够:
- 安装并配置 Vivado HLS 开发环境。
- 创建 HLS 项目,编写 C 语言源文件。
- 运行 C 仿真,验证功能正确性。
- 添加优化 pragma(如 PIPELINE),提升性能。
- 完成 C/RTL 协同仿真,确保 RTL 行为与 C 一致。
验收清单:
- [ ] C 仿真通过,结果正确。
- [ ] 添加了 PIPELINE pragma。
- [ ] 接口 pragma 正确配置。
- [ ] 综合报告无严重警告。
- [ ] C/RTL 协同仿真一致。
实施步骤
步骤 1:安装 Vivado HLS
从 Xilinx 官网下载 Vivado Design Suite 安装包(推荐版本 2019.1 或 2020.1)。安装时选择“Vivado HL WebPACK”或“Vivado HL Design Edition”,确保勾选“Vivado HLS”组件。安装完成后,启动 Vivado HLS 命令行或 GUI 工具,验证安装成功。
步骤 2:创建 HLS 项目
启动 Vivado HLS GUI,点击“Create New Project”。输入项目名称(如“vector_add_hls”),选择项目路径。在“Top Function”对话框中,输入顶层函数名称(如“dut”),该函数将作为硬件加速器的入口。点击“Finish”完成项目创建。
步骤 3:编写 C 代码
在“Source”目录下,右键选择“New File”,创建 C 源文件(如“dut.c”)。实现一个简单的向量加法函数:
void dut(int a[10], int b[10], int c[10]) {
for (int i = 0; i < 10; i++) {
c[i] = a[i] + b[i];
}
}该函数接收两个输入数组 a 和 b,计算逐元素加法,结果存入输出数组 c。注意:数组大小固定为 10,便于后续综合。
步骤 4:编写测试激励(Testbench)
在“Test Bench”目录下创建测试文件(如“tb.c”),用于验证功能:
#include <stdio.h>
void dut(int a[10], int b[10], int c[10]);
int main() {
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int b[10] = {9,8,7,6,5,4,3,2,1,0};
int c[10];
dut(a, b, c);
for (int i = 0; i < 10; i++) {
if (c[i] != a[i] + b[i]) {
printf("Error at index %d
", i);
return 1;
}
}
printf("Test passed!
");
return 0;
}测试激励初始化数组 a 和 b,调用 dut 函数,然后逐元素检查结果。若所有元素匹配,输出“Test passed!”。
步骤 5:运行 C 仿真
在 Vivado HLS 主界面,点击“Project”菜单,选择“Run C Simulation”。在弹出的对话框中,确认测试文件路径正确,点击“OK”。仿真完成后,查看控制台输出,应显示“Test passed!”。若出现错误,检查代码逻辑。
步骤 6:添加优化 pragma
为了提升硬件性能,在 dut.c 中添加 pragma 指令。修改代码如下:
void dut(int a[10], int b[10], int c[10]) {
#pragma HLS INTERFACE s_axilite port=return bundle=control
#pragma HLS INTERFACE bram port=a
#pragma HLS INTERFACE bram port=b
#pragma HLS INTERFACE bram port=c
#pragma HLS PIPELINE
for (int i = 0; i < 10; i++) {
c[i] = a[i] + b[i];
}
}原因与机制分析:
- PIPELINE pragma:指示 HLS 工具将循环展开为流水线,允许每个时钟周期处理一个迭代,从而提升吞吐量。对于 10 次迭代的循环,流水线启动间隔(II)通常为 1,总延迟从 10 周期降至约 10 周期(含填充)。
- INTERFACE pragma:定义 RTL 端口协议。这里将数组 a、b、c 映射为 BRAM 接口,return 端口使用 AXI4-Lite 协议,便于与 CPU 通信。
落地路径: 在代码中直接插入 pragma 即可,无需修改算法逻辑。综合工具会自动解析并生成对应硬件结构。
风险边界:
- PIPELINE 可能增加资源消耗(如寄存器、LUT),若资源紧张,需权衡性能与面积。
- BRAM 接口要求数组大小固定,且数据宽度与 BRAM 匹配(通常为 32 位)。
步骤 7:运行 C/RTL 协同仿真
点击“Solution”菜单,选择“Run C/RTL Cosimulation”。在对话框中,选择“RTL”仿真语言(Verilog 或 VHDL),设置时钟周期(如 10 ns)。点击“OK”开始仿真。完成后,查看协同仿真报告,确认结果与 C 仿真一致。若不一致,检查接口配置或 pragma 设置。
验证结果
完成上述步骤后,应满足验收清单中的所有项目:
- C 仿真通过,输出“Test passed!”。
- PIPELINE pragma 已添加,综合报告中显示流水线启动间隔为 1。
- 接口 pragma 配置正确,综合报告无接口警告。
- 综合报告无严重警告(如时序违例、资源超限)。
- C/RTL 协同仿真结果一致,无数据错误。
排障指南
常见问题及解决方案:
- C 仿真失败:检查测试激励中的数组初始化与预期结果。确保 dut 函数声明与定义一致。
- 综合报告有严重警告:查看具体警告内容。例如,“Unbound interface”表示接口 pragma 未正确匹配,需检查端口名称。
- C/RTL 协同仿真不一致:检查时钟周期设置是否合理。若 RTL 仿真时间过长,可减少测试数据量。
扩展阅读
完成本指南后,可尝试以下扩展:
- 修改数组大小为可变参数,使用
#pragma HLS ARRAY_PARTITION优化存储访问。 - 实现更复杂的算法,如矩阵乘法或 FIR 滤波器。
- 将生成的 RTL 代码集成到 Vivado 项目中,在 FPGA 板上运行。
参考资源
- Xilinx UG902:Vivado Design Suite User Guide: High-Level Synthesis。
- Xilinx UG871:Vivado Design Suite Tutorial: High-Level Synthesis。
- Vivado HLS 官方示例:
<Vivado_install_dir>/examples/hls/。
附录:完整代码清单
dut.c(优化后):
void dut(int a[10], int b[10], int c[10]) {
#pragma HLS INTERFACE s_axilite port=return bundle=control
#pragma HLS INTERFACE bram port=a
#pragma HLS INTERFACE bram port=b
#pragma HLS INTERFACE bram port=c
#pragma HLS PIPELINE
for (int i = 0; i < 10; i++) {
c[i] = a[i] + b[i];
}
}tb.c:
#include <stdio.h>
void dut(int a[10], int b[10], int c[10]);
int main() {
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int b[10] = {9,8,7,6,5,4,3,2,1,0};
int c[10];
dut(a, b, c);
for (int i = 0; i < 10; i++) {
if (c[i] != a[i] + b[i]) {
printf("Error at index %d
", i);
return 1;
}
}
printf("Test passed!
");
return 0;
}


