vitis hls使用基本介绍
我们之前在外国教材上已经实现了最简单的加法器电路,并且用HLS进行了仿真。今天我们来记一下笔记并且实现一个新的电路也就是led灯。
创建项目
如图所示,输入项目名称后,这里可以添加现有的c语言文件。默认没有的话直接next,下面的testbench同理。
下面要确定我们的解决方案名称,解决方案在一个项目中可以有很多个,用来帮我们对比哪种更好。
默认不用动即可。时钟频率默认也就是10ns。
成功创建工程之后,打开左边的include可以看到安装好的一些头文件和库。
我们要生成的模块算法,要放到源文件source里面。testbench我们已经熟悉了,他是激励文件。
电路原理
电路原理图如下:
然后开始创建源文件
编写项目文件
在左边的source点击新源文件,可以在我们的项目目录中再创建一个src文件夹保存所有源文件,创建两个源文件,第一个是c语言实现算法,后缀为cpp文件,另一个是头文件,定义数据类型等,后缀.h。
然后编写c语言代码。
头文件代码如下:
1 |
|
shift_led.cpp
的代码如下:
1 |
|
然后在左边的testbench中定义testbench_shift_led文件
1 |
|
启动仿真
注意,实际上在source文件中,我们的.h头文件是不允许存在的,所以此刻删掉.h文件。
打开project栏看到c仿真
我们看到报错很快,因为头文件的引用已经不成立了呀,刚刚被我们删除了头文件。
我们打开project settings然后选择synthesis
部分选择top_function
注意这个并不是引起头文件错误的原因,这只是需要我们额外操作的部分。
头文件虽然在项目中被删除,但是文件还在,在src文件夹中并没有被删除,所以我们在testbench
文件testbench_shift_led.cpp
文件中第一行改为
1 |
即可找到!
当没有报错,完成仿真时,可以看到日志如下:
我们可以在此日志上面看到生成结果
符合,只不过没有输出成2进制的形式。
转换成verilog文件
如图所示激活我们目前的solution,生成verilog文件!终于到了核心的部分。
当然,我们完全可以创建一个新的solution,并且和之前的solution之前来回切换。
生成后的结果如图所示
可以看到左边一栏中多出了仿真结果,有VDHL语言,VERILOG语言和SYSTEMVERILOG语言,非常全面。并且包含了核心算法代码,也就是我打开的shift_led.v
文件。
我们打开此文件,如图所示
看到led_i也就是输入部分,竟然占到了32位,实在是太浪费了,因为比如我们刚才的输入只有3’b110也就是3位而已。
解决位宽问题
我们可以直接从头文件修改,修改shift_led.h
如下
1 |
|
可以看到我们引入了一个vivado带的库,他非常方便可以定义任意位的整形或者浮点型。所以我们直接定义3位的整形即可。
然后重新运行c synthesis
里面的active solution
运行结束之后再来查看位宽如下
发现直接对应led输入输出变量部分变成了3位!
在输出报告里面可以看到只用了28个flip flop
和135个LUT
比较节省。
接口配置
然后打开核心算法文件,看到右边出现directive,可以约束我们的输入和输出。
比如我们先来配置一下输出接口led_o
。
选择INTERFACE项。
模式我们选择OVLD,代表输出标志信号的意思,标志信号就是一个方波脉冲,作为信号的标志的意思。输入标志信号也是如此,只不过代号用VLD表示。
注意,加入这些之后,在右边栏可以看到directive的一些声明。但是注意,添加在这里只是这一个solution
下的directive。我们最好加在源文件中,就可以在所有solution
中使用了。所以我们可以删除刚才添加的,从新添加到源文件中。添加之后如图所示
然后重新运行c synthesis
生成对应verilog代码。
结果如图
可以看到我们定义的硬件接口。
然后进行联合仿真,如图所示,
也就是c/rtl cosimulation
。
然后即可查看仿真运行结果,也就是一个信号输入,对应输出图。
第一次发现报错如图所示:
实际上是输出类型出了问题,因为我们的led_o已经定义为ap_fixed类型,然而这种类型其实属于无符号整型 unsigned int所以在输出的地方应用强制类型转换。
输出行变成
1 | fprintf(stdout, "output result = %x", (unsigned int)led_o&0x7); |
重新运行联合仿真即可。