第二讲:HLS工具初探——Vivado HLS界面介绍与第一个工程
好,咱们正式开始动手了。这一讲,我带你把Vivado HLS这个工具摸个底。说白了,就是让你知道它长什么样、怎么用、跑起来是什么感觉。
我记得我第一次打开Vivado HLS时,看着满屏的英文菜单和按钮,说实话有点懵。但别怕,这东西用熟了你会发现,它比直接写Verilog要友好得多。
2.1 Vivado HLS界面概览
打开Vivado HLS后,你会看到几个主要区域。我习惯把它们分成三块:
- 工程管理区(左侧):显示你的源文件、测试文件、解决方案等。有点像VS Code的资源管理器。
- 信息输出区(底部):跑仿真、综合时的日志和警告都在这里。嗯,这里要养成随时看的习惯。
- 主编辑区(中间):写代码、看报告的地方。
你可能会问:「这么多窗口,我该看哪个?」其实刚开始,你只需要关注两个按钮:C仿真和C综合。其他的后面慢慢熟悉。
2.2 创建第一个HLS工程:Hello World
学任何语言,第一个程序都是Hello World。HLS也不例外。虽然它不输出到屏幕,但我们可以写一个简单的加法函数,跑通整个流程。
操作步骤很简单:
- 点击 Create New Project
- 给工程起个名字,比如
hello_hls - 选择顶层函数(后面会讲这是什么意思)
- 添加源文件,然后直接Finish
好,现在我们来写代码。新建一个源文件,叫 hello.cpp:
#include <ap_int.h>
int add(int a, int b) {
return a + b;
}
就这么简单?对,就这么简单。你可能会想:「这不就是C语言吗?」没错,HLS的输入就是C/C++。但注意,不是所有C代码都能综合成硬件。后面我会专门讲哪些能写、哪些不能写。
然后写个测试文件 hello_tb.cpp:
#include <iostream>
#include "hello.h"
int main() {
int result = add(3, 5);
if (result == 8) {
std::cout << "Test passed!" << std::endl;
return 0;
} else {
std::cout << "Test failed!" << std::endl;
return 1;
}
}
printf 或 cout 只在仿真时有效。综合成硬件后,这些打印语句会被忽略。我曾经犯过这个错——在综合后的代码里指望看到打印信息,结果啥也没有。
2.3 C仿真:先跑一遍软件
写完了代码,第一步不是综合,而是C仿真。说白了,就是用你的电脑CPU先跑一遍这个C程序,看看逻辑对不对。
点击工具栏上的绿色三角形按钮(C Simulation),Vivado HLS会调用GCC或VS编译器来编译运行你的测试文件。如果一切正常,你会看到控制台输出:
Test passed!
为什么要先做这一步?因为C仿真快啊!综合一次可能要几分钟甚至几小时,而C仿真几秒钟就出结果。我个人的习惯是:先仿真通过,再考虑综合。这样可以快速排除逻辑错误。
2.4 C综合:把C变成硬件
C仿真通过后,就可以点那个黄色的「小齿轮」按钮——C综合了。这一步,Vivado HLS会把你的C代码翻译成RTL(寄存器传输级)代码,也就是Verilog或VHDL。
综合过程中,你会看到进度条在跑。这时候可以喝杯咖啡,或者看看综合报告。综合完成后,工具会自动弹出综合报告窗口。
2.5 理解综合报告
综合报告是HLS里最重要的东西。它告诉你:你的设计能跑多快、占多大面积、用了多少资源。
报告主要包含这几块:
| 报告项 | 含义 | 我的经验 |
|---|---|---|
| Latency | 从输入到输出需要的时钟周期数 | 如果latency太大,考虑加pipeline |
| II (Initiation Interval) | 两次启动之间的最小间隔 | II=1是理想状态,但很难做到 |
| DSP48E | 用了多少个DSP单元 | 乘法、乘加运算会消耗DSP |
| BRAM | 用了多少块Block RAM | 数组、查找表会消耗BRAM |
| FF/LUT | 触发器和查找表 | 逻辑运算和状态机消耗这些 |
举个例子,刚才的加法函数综合后,报告大概会显示:
- Latency = 2 个时钟周期(因为输入寄存和输出寄存各占一拍)
- DSP = 0(加法可以用LUT实现)
- FF/LUT = 几十个(非常小)
你可能会问:「为什么加法要2个周期?不是一拍就能算完吗?」嗯,这里有个细节:HLS默认会在输入和输出插入寄存器,以保证时序。如果你追求极致性能,可以用 #pragma HLS pipeline 来优化。这个我们后面会详细讲。
#pragma HLS bind_storage 强制指定存储类型。所以,综合报告只是预估,最终要以布局布线结果为准。
2.6 本章知识体系
为了让你更直观地理解这一讲的内容,我画了一张流程图,展示HLS从代码到硬件的完整路径:
这张图清晰地展示了我们今天做的每一步:从写C代码,到C仿真验证,再到C综合生成RTL,最后通过综合报告来评估设计质量。注意那条虚线——它代表一个迭代循环。实际项目中,你很少能一次综合就满意,往往要反复调整代码、看报告、再优化。
2.7 小结
这一讲,我们完成了三件事:
- 认识了Vivado HLS的界面布局
- 创建了第一个HLS工程,写了一个加法函数
- 跑通了C仿真和C综合,并学会了看综合报告
说实话,加法函数虽然简单,但它背后的流程——仿真、综合、报告分析——是后续所有复杂设计的基础。你把这个流程跑熟了,后面学pipeline、array partition、dataflow这些高级优化时,就不会手忙脚乱。
下一讲,我们会深入HLS的数据类型,看看 ap_int、ap_fixed 这些自定义类型到底怎么用,以及为什么它们比C语言自带的 int、float 更适合硬件设计。
可可精品资料库