Vivado 入门 —— HLS HelloWorld 流水灯(一)—— 制作 IP
Vivado HLS 新建项目
首先我们点击创建一个新的 Project ,这里和使用 Quartus 的方法相似
注意:这我们打开的不是 Vivado 而是 Vivado HLS
这里我们选择自己的路径,这里操作和
我们不需要添加文件,文件可以在后面添加进来,但是这里我们要设置好顶层文件名称:
配置 Solution Name,一般默认即可
配置Clock Period,单位是ns
配置Uncertainty,默认为空
选择产品型号,完成后点击Finish
创建成功后界面如下:
右键点击 source - Add Files 可以添加我们本地的代码文件,注意顶层文件里面的顶层函数名称一定要与我们前面设置的一致
这里我们创建三个代码文件,一个头文件,一个用做仿真,一个用作顶层文件:
当我们添加好文件之后,我们就可以开始编辑我们的代码了
代码设计
首先我们设计流水灯程序,完整程序如下:
HLS_HelloWorld.h
#ifndef _HLS_HELLOWORLD_H_
#define _HLS_HELLOWORLD_H_
#include "ap_int.h"
#define CNT_MAX 100000000
//#define CNT_MAX 100
#define FLASH_FLAG CNT_MAX-2
//typedef int led_t;
//typedef int cnt_t;
// 修改指定位宽,如果使用 int 则会默认使用 32 位宽,我们并不需要,所以选择自定义位宽
typedef ap_int<1> led_t;
typedef ap_int<32> cnt_t;
void flash_led(led_t *led_o , led_t led_i);
#endif
HLS_HelloWorld.c
#include "HLS_HelloWorld.h"
void flash_led(led_t *led_o , led_t led_i){
#pragma HLS INTERFACE ap_vld port=led_i
#pragma HLS INTERFACE ap_ovld port=led_o
cnt_t i;
for(i=0;i<CNT_MAX;i++){
//#pragma HLS PIPELINE
if(i==FLASH_FLAG){
*led_o = ~led_i;
}
}
}
测试文件:
HLS_HelloWorld_tb.c
#include "HLS_HelloWorld.h"
#include <stdio.h>
int main(){
led_t led_i=0x01;
led_t led_o;
const int SHIFT_TIME = 4;
int i;
for(i=0;i<SHIFT_TIME;i++){
flash_led(&led_o , led_i);
led_i = led_o;
printf("shift_out is %d \n",(int)(led_o&0x01));
}
}
运行综合
C 仿真
点击运行仿真:
或
这里我们什么都不选,直接点击 ok 即可
出现如下画面就说明我们已经仿真成功了:
这里我们能够看到输出一直是 0101 在0、1之间不断跳变,说明我们的仿真已经成功得到了我们想要的结果
C 综合
只要我们项目中已经存在了主要的 cpp 和 testbench 仿真文件,我们就可以进行综合
这里我们需要将我们要进行综合的 led 灯闪烁的函数映射成 RTL 代码,首先我们需要选择顶层函数:
首先我们点击源文件,然后选择函数,这里就选择我们的 flash_led 函数即可:
注意:如果前面已经设置了顶层函数,那么我们就不需要再次设置
设置成功之后,我们直接点击 C 综合即可
C 综合结束后,会有一个总结文件如下:
clock 是时钟
Latency 是从输入到输出等待的时钟周期数
Interval 是两次数据输入之间的间隔
下面就是 C 综合完成后的资源占用情况
这里总共使用了 70 个查找表和 32 个触发器
最后就是对接口的描述
最左列就是信号名称,一般由 HLS 综合出来的都会带有这些以 ap 开头的信号
Protocol 表示使用的协议
综合成功后,我们也可在 solution 下找到综合自动生成的 RTL 代码:
我们并不需要看懂,只需要会使用即可
Directive 说明
这里我们需要通过对接口进行 Directive 说明达到可以按照我们想使用的接口进行 Directive 添加
这里我们直接右键选中变量,点击添加即可:
这里解释一下我们上面的选项:
-
Directive 类型这里我们选择接口类型
-
策略存储位置我们选择直接在源文件中生成
-
选择模式,这里选择这里我们的 led_o 为信号输出,所以这里我们选择输出有效信号 ap_ovld,led_i 为信号输入,这里我们就选择信号有效输入 ap_vld 即可
运行仿真
C 综合之后,我们要进行仿真操作:
首先我们需要简单修改一下程序中的时间设置,时间设置的越长,仿真需要的时间也就越长,我们这里设置小一点就可以
点击进行联合仿真:
这里我们选择 modelsim 进行仿真,Dump Trace 选择所有信号,点击 ok 开始仿真
仿真时间较长,需要耐心等待
联合仿真过程详解
首先会生成一个脚本:
然后脚本会运行 RTL 仿真,这里可以看到我们使用的 modelsim 版本和仿真的全过程:
仿真结果如下:
这里得到的仿真结果与前面一致,并且仿真输出结果提示 pass,可以看出这里我们仿真结果完全正确,这里仿真得到的结果就是我们最终电路生成的结果
仿真结束后我们需要将我们前面修改的市场修改回来,并重新执行 C 综合,避免在上板验证时发生错误
打包导出 IP
前面仿真全部通过了,我们只有打包并导出 IP,才能在实际设计程序中进行调用
点击打包
这里使用默认设置,点击 ok 即可
打包成功如下:
同时我们也可以找到我们打包好的 IP 文件
我们的 IP 文件就存放在 zip 压缩包中,hdl 文件夹中存放的就是 IP 的代码文件,xgui 中存放的就是我们打开 IP 时的界面文件
报错问题解决方案
C 仿真/综合报错
如果出现如下一系列报错:
这就说明我们的源文件存放地址有问题,这里推荐新建文件,而不是导入外部源文件,否则就会出现找不到某函数或者某文件的问题
打包 IP 报错
如果在打包 IP 时报错如下:
这里有两种解决方案:
方法一(推荐):
可以直接将 windows 系统时间调整到 2021 年之前,就能够解决
这里在我们打包完成之后需要及时将系统时间修改回来
可以看到这里我们在修改了时间之后,已经成功打包
方法二:
更新(Updata):
参考Xilinx官网的补丁及使用方法进行修改
https://support.xilinx.com/s/article/76960?language=en_US
如果你在运行后出错或未正确执行,可以参考成功运行的 log 信息,复制automg_patch_20220104.tcl 文件到指定文件夹。
如果你使用的为低版本的Vivado HLS,只需要复制一次(因为只有一个文件夹)