2、Vivado HLS工具入门:工具安装与环境配置、创建第一个HLS项目、理解HLS工程结构

好,咱们正式开始动手了。这一章我带你走一遍 Vivado HLS 的完整入门流程。说实话,很多初学者卡在第一步——工具装好了,但不知道点哪里。别急,我当年也踩过这个坑。

2.1 工具安装与环境配置

先聊聊安装。Vivado HLS 是 Xilinx 家的工具,现在叫 Vitis HLS 了,但核心逻辑没变。我个人习惯用 2019.1 或 2020.1 版本,稳定,坑少。

安装前你要知道的事

  • 操作系统:Windows 10/11 或 Ubuntu 18.04/20.04 都行。我建议用 Linux,编译速度快不少。
  • 硬盘空间:至少 50GB 空闲。别问我怎么知道的——我第一次装完发现 C 盘爆了。
  • 内存:16GB 起步。如果你跑大一点的工程,32GB 更稳。
注意:安装路径不要带中文或空格。我曾经因为路径里有个“项目”两个字,折腾了一下午。

环境变量配置

装完之后,记得配环境变量。Linux 下加一行到 .bashrc:

source /opt/Xilinx/Vivado/2019.1/settings64.sh

Windows 用户直接在系统环境变量里加 %XILINX_VIVADO%/bin 就行。

配好之后,打开终端敲 vivado_hls,能看到版本信息就说明成了。

2.2 创建第一个HLS项目

好,工具就绪了。咱们来建个最简单的项目——一个加法器。别嫌简单,麻雀虽小五脏俱全。

图形界面方式

  1. 打开 Vivado HLS,点击 Create New Project。
  2. 给项目起个名字,比如 adder_prj。路径别乱放,我习惯建一个 hls_workspace 文件夹统一管理。
  3. 选择顶层函数。这里先跳过,后面再指定。
  4. 选择器件。如果你用的是 Zynq 系列,选 xc7z020clg484-1 就行。
  5. 点击 Finish,项目就建好了。
小技巧:器件型号可以在板子的官方文档里找到。实在不确定,选个同系列的通用型号也行。

命令行方式(我推荐)

说实话,图形界面点来点去效率不高。我更喜欢用 Tcl 脚本。下面是一个最小示例:

open_project adder_prj
set_top adder
add_files adder.cpp
add_files -tb adder_tb.cpp
open_solution "solution1"
set_part {xc7z020clg484-1}
create_clock -period 10
csynth_design

把这段保存成 run.tcl,然后执行 vivado_hls -f run.tcl。嗯,这才是工程师该有的样子。

2.3 理解HLS工程结构

项目建好了,咱们看看里面都有啥。打开工程目录,你会看到这样的结构:

adder_prj/
├── solution1/
│   ├── impl/          # 综合后的实现文件
│   ├── syn/           # 综合报告
│   ├── report/        # 各种报告
│   └── verilog/       # 生成的RTL代码
├── src/               # 你的源代码
├── tb/                # 测试文件
└── vivado_hls.log     # 日志文件

这里我重点说几个关键目录:

  • src/:放你的 C/C++ 源码。注意,HLS 支持 C、C++ 和 SystemC。
  • tb/:测试文件。没有测试文件,你都不敢说你的设计是对的。
  • solution1/:每个 solution 对应一组约束和配置。你可以建多个 solution 做对比实验。

核心概念:HLS 的本质是把 C 代码翻译成 RTL。你写的 C 函数会被综合成硬件模块,循环会被展开或流水线化,数组会被映射成 BRAM 或 LUTRAM。

一个完整的加法器示例

咱们写个简单的加法器,看看 HLS 怎么处理:

// adder.cpp
#include "adder.h"

int adder(int a, int b) {
    #pragma HLS INTERFACE s_axilite port=return
    return a + b;
}

对应的头文件:

// adder.h
#ifndef ADDER_H
#define ADDER_H

int adder(int a, int b);

#endif

测试文件:

// adder_tb.cpp
#include "adder.h"
#include <iostream>

int main() {
    int result = adder(3, 5);
    if (result == 8) {
        std::cout << "Test passed!" << std::endl;
        return 0;
    } else {
        std::cout << "Test failed!" << std::endl;
        return 1;
    }
}

你看,代码和普通 C++ 几乎一样。唯一的区别是那个 #pragma HLS 指令,它告诉工具怎么生成硬件接口。

2.4 知识体系总览

为了让你对本章内容有个整体认识,我画了张图:

Vivado HLS 入门知识体系 工具安装与环境配置 创建第一个HLS项目 理解HLS工程结构 操作系统与硬件要求 环境变量配置 图形界面方式 Tcl命令行方式 src/tb/solution目录 综合报告与RTL生成 核心目标:从C代码到RTL的自动化硬件生成 理解HLS的本质:用软件思维做硬件设计

2.5 避坑指南

最后,分享几个我踩过的坑:

  • 路径问题:项目路径不要有中文、空格、特殊字符。我曾经用“测试项目”做名字,结果综合报错找不到文件。
  • 版本匹配:Vivado HLS 版本要和 Vivado 版本一致,否则生成的 IP 可能用不了。
  • 仿真 vs 综合:C 仿真通过了不代表综合没问题。有些 C 语法 HLS 不支持,比如动态内存分配。
我的习惯:每建一个新项目,先跑一个最小示例(比如加法器),确认工具链没问题再开始写正式代码。这能省下大量调试时间。

好了,这一章就到这里。工具装好了,项目建起来了,结构也搞清楚了。下一章咱们开始写真正的 HLS 代码,看看怎么把 C 语言变成硬件。

可可精品资料库