HLS:接口完整学习与综合测试


一、引言

之前HLS工具帮忙生成的m_axi和s_axi接口,可以很简单的挂接到PS端,进行通信。这次学习的是其他接口的lab,这些接口虽然不能直接与PS端进行通信,但与dma等模块进行组合后,也可以完成与PS端的通信。

之所以要学其他接口,是因为m_axi和s_axi接口功能特定,无法自己更改成自己想要的读写方式。

HLS生成电路:接口功能+模块功能,都可以按照自己的想要的生成。

涉及的接口:ap_hs、ap_fifo、ap_ack、ap_vld、ap_ovld、ap_stable、ap_memory、ap_none和ap_bus。


二、案例

以一个FIR(有限冲击响应滤波器)的例子,来实验这些接口。
在这里插入图片描述
1、fir.h文件。

#ifndef __FIR_H__
#define __FIR_H__

typedef int dtype;
// volatile表示不要对变量进行优化。 为了防止同个变量名读出的结果一直一样,避免被优化掉。
void fir(volatile dtype *in,volatile dtype *out,unsigned int length);

#endif

2、fir.cpp文件。

#include "fir.h"

void fir(volatile dtype *in,volatile dtype *out,unsigned int length)
{

	dtype para1,para2,para3;    // 3个参数,表示3个抽头的滤波器。
	para1=1;para2=1;para3=1; 

	dtype d0=0,d1=0,d2=0;

	for(int i=0;i<length;i++)
	{
		// 每次进来一个数in,就把该数保存到d1里,而d1又把数保存到d2中,如此往复。
		// 每次进来一个数,先做延迟,一个in的就产生一个out出去。
		d2=d1;d1=d0;d0=*in;
		*out=para1*d0+para2*d1+para3*d2;

	}
}

3、main.cpp文件。

#include "fir.h"

int main()
{
	dtype in[10];
	dtype out[10];
	// 赋值
	for(int i=0;i<10;i++)
	{
		in[i]=1;
	}
	// 进去10个数,出来10个数
	fir(in,out,10);

	return 0;
}

4、预期目标。
一个周期,in一个数,out一个数。至少周期数是length。


三、实验

1、第一次尝试。
第一次综合的结果出现了问号,这是因为length的长度是不确定的,综合工具也不知道需要多少个latency才能完成一个功能。一种比较笨的方法,是可以直接把length改成定值,后续再改回来就好,但比较麻烦。有一个选项可以告诉HLS循环多少次,在Vivado HLS Directive Editor的LOOP_TRIPCOUNT中,等价于#pragma HLS LOOP_TRIPCOUNT min=100 max=100 avg=100命令。这个命令只对性能评估有作用,解决问号的问题,但对模块的功能,并没有影响。
在这里插入图片描述
添加命令后的测试结果。
在这里插入图片描述
2、第二次尝试。
首先,看接口部分,in_r的接口类型默认是ap_none,只有一个端口,没有啥使能之类的。out_r的类型是ap_vld,表示还有一个out_r_ap_vld信号,当out_r输出一次时,就会拉高一个周期的out_r_ap_vld脉冲信号,连续输出十次,就出现拉高out_r_ap_vld信号十个周期。
在这里插入图片描述
为了做接口部分的修改,先对接口做一个学习。这些接口可以在选项卡中看到。
在这里插入图片描述
1°ap_none:仅仅有数据,没有数据有效信号的这种接口,就是ap_none。测试时,把out_r信号的接口给改成ap_none,发现也确实没有了vld信号。这种ap_none在一个地方有用到,就是组合逻辑的实现时。
在这里插入图片描述
2°ap_vld:产生一个数据有效的标志。因为,在1°提到的,在数据传输中,如果只单独有数据信号,在传输中无法判断哪些信号是有效的,必须要一个数据有效信号,而ap_vld接口就产生了这种数据的有效信号。再举个输入的例子,如果把in的接口设成ap_vld,那么当数据输入时,也会有一个数据的有效信号输入,如果模块需要检测到4个数据输入后,再进行工作,就会不断等待4个vld的标志。如果在输出模块与输入模块之间,都使用ap_vld接口,可以实现点对点的通信,也即相连基本没有阻碍。但也会存在一个问题,就是后面一个模块是否可以接收数据,前一个模块是不知道的,如果一直发出去,后一个模块无法接收,那还是会出错。需要一个ready反馈信号,变成了3°中的ap_hs信号。
3°ap_hs:handshake,即握手信号,后续用的非常多的一个接口类型。握手是为了解决模块间是否能通信而诞生的,之前在AXI等很多地方都学过,但一直无法很有把握说自己懂了,这次用一段篇幅整理下。
3_1°举一个例子,A模块需要通过握手信号,往B模块中传4个数据。握手信号包括vld和ready两个。
在这里插入图片描述
3_2°当A模块数据准备好,放在数据线上后,开始拉高vld信号,但ready信号还是低的,表示模块B没有准备好接收数据。
3_3°当B准备好可以接收数据时,ready信号被拉高,此时满足了vld&ready的结果为1的条件,放在数据线上的数据就被传入B模块了。
3_4°B接收完数据。vld信号为高,表示A模块待输出的下一个数据也准备好了,放在数据线上了。但B模块还无法接收,所以数据在数据线上一直保持,直到ready为1,可以接收。并且后面ready和vld持续为1,表示同时发送和接收多个数据了。
3_5°vld为0时,表示A模块数据还没有准备好,需要等待下,即使此时ready为1,B模块可以接数据了,数据线上没准备好的数据,也不会传输到B模块中。
3_6°这里将输入接口和输出接口设为ap_hs,可以发现输出多了一个ack信号,就是之前讲的ready信号。
在这里插入图片描述
3_7°仿真跑跑波形。得到下面的图。
在这里插入图片描述
4°ap_ack:这种接口相当于ap_hs的特例,即原来的vld信号给去除掉了。数据传输时只有data和ack两根线,当后一级模块需要接收X个数据时,就会发出X个脉冲的ack信号,而前一级模块收到ack为1的情况,就会把数据传输给后一级模块。这种接口适合于前一级模块的数据都是有效的情况。这种接口其实不是很保险,因为前一级模块的数据很难做到都有效,或者说很难ack一为高,数据就准备好。
5°ap_fifo:和ap_hs非常的像,会形成一个fifo的通路,ap_hs中的vld和ready相当于ap_fifo中的wr_en和full(read和empty)。更改后综合的效果如下面这图。
在这里插入图片描述
5°ap_ovld:这种接口和ap_vld基本是一样的,没啥区别,只是将输入的信号设为ap_ovld后,是没有效果的,只针对输出有效。但ap_vld对输入和输出都是有效的。
在这里插入图片描述
6°ap_stable:这个接口和ap_none很像,用于表示某个接口的信号在一次工作期间都是稳定的,用在配置寄存器中非常多,比如fir模块中的length就可以做成ap_stable的形式,每次工作期间都是个常数,但这次工作和下次工作期间可能会发生变化。再举个例子:卷积运算时需要KX和KY来配置kernel的大小,33或55,先配置好,单次运算的过程中,并不会发生改变。
7°ap_memory:之前数组就是这种,假设数据来源于存储器的接口。
7°ap_bus:这种接口是Xilinx自己定义的一个接口,基本上用不着。通常都是用ap_hs来代替其。
在这里插入图片描述


四、小结

ap_hs最重要,很多都是其变形。ap_stable也是个重点。


五、时间线

一些关键时间点的记录:

2021年04月13日:学习各种接口,并综合测试。
后续可能做的工作:暂无,但接口的很多思想可以在其他功能设计中体现。

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vivado HLS(High-Level Synthesis)是一种高层次综合工具,可以将C/C++代码转换为硬件描述语言(如Verilog或VHDL),从而实现快速的硬件设计。在Vivado HLS中实现排序的过程可以分为以下步骤: 1. 编写排序算法的C/C++代码。可以选择使用任何经典的排序算法,如冒泡排序、选择排序、插入排序、快速排序等。 2. 在Vivado HLS中创建一个新的工程,并将排序算法的C/C++代码导入到工程中。在导入代码时,需要注意将排序算法的函数声明为“hls::stream”类型。 3. 在Vivado HLS中创建一个测试函数,用于生成输入数据并检查输出数据。测试函数可以使用C/C++编写。在测试函数中,需要创建输入和输出流,并将它们连接到排序算法的输入和输出流上。 4. 进行综合和优化。在Vivado HLS中,可以选择不同的优化选项,以便生成更优化的硬件设计。 5. 导出硬件描述语言(如Verilog或VHDL)。在Vivado HLS中,可以通过单击“Export RTL”按钮来将硬件描述语言导出到指定的目录。 6. 将导出的硬件描述语言文件添加到Vivado工程中,并进行综合、实现和生成比特流的流程。 7. 将比特流文件下载到FPGA板子中,并通过相应的接口测试排序算法的性能和正确性。 需要注意的是,在实现排序算法时,需要考虑到数据的大小、数据类型、排序方式等因素,以确保硬件设计的正确性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学不懂啊阿田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值