整体的工程公开在这:
maxs-well/HLS4BPSKgithub.com本工程主要使用HLS实现m序列,文中将介绍HLS的使用和优化,HLS的C库文件的使用,HLS的单bit信号的实现,并最终生成IP核。
m序列的相关基础知识可以参考m序列的verilog实现以及使能信号解决跨时钟域问题。
初次自主使用HLS生成代码,学习HLS从简入深,这意味着我写的程序可能会有部分错误和不足,欢迎指出!
HLS作为Xilinx推出的一款工具,旨在降低FPGA的使用难度和学习难度,能够更快地使用软件编程语言C/C++生成需要的verilog代码。
作为HLS初学者的我,通过C/C++生成m序列的verilog代码,下面跟着步骤一步步来吧。
使用HLS创建新的工程,参数设置如下:
在图1填写项目名称和存储路径,然后一路'Next',直到出现下图的设置;
如图2,设置工程的时钟周期和FPGA型号;
注意,可以将时钟周期设置的比实际用的周期要小,比如m序列实际使用的时钟周期为20ns,但在HLS中,时钟周期设为10ns,这样HLS生成的代码,时钟会有更高的冗余性,分析结果更为准确;
Source里添加需要生成的C/C++代码,Test Bench添加对Source代码的仿真验证C/C++代码。
由于m序列产生的只是'0','1'代码,m序列输出的信号为1bit信号,所以m序列的产生函数不能使用C中常见的char、int类型,需要使用更加精确的数据类型。
而Xilinx正好为用户提供了这种精确的数据类型的实现方式,使用前提需要在m_seq.h的头文件里include一个"ap_int.h"。
使用ap_int<W> 或ap_uint<W>可以实现一个Wbit精度的有符号整数或无符号整数信号;为了后续优化和使用方便,m_seq.h使用typedef将ap_int<1>设为'BIT'的别名;
m_seq.cpp中初始化一个'BIT'的数组code,长度为4,并赋予初值{0, 0,0,1};void m_seq(BIT * y)是最终m序列生成函数,变量y是函数的输出; m_seq中的实现逻辑也较为简单:
- 将code[0]赋值给y ;
- for循环,将code整体右移,并将for循环使用一个标签'SHIFT_REG'标记;
- 将原code[0]和原code[3]异或后的结果保存到code[3];
在实现仿真和综合前,需要在项目的选项中做一个设置,让HLS的编译器知道该分析实现哪一个函数。
在Synthesis Setting的Top Function中,选择需要实现的函数m_seq();
m_seq_test.cpp里使用文件存储m_seq函数产生的结果,并与预期结果比较,根据比较结果判断输出结果是否正确;
在不做优化的情况下,经过C simulation和C synthesis后,可以看到HLS的分析结果;
可以从图6看到,最终实现中,时钟预估是满足10ns周期的要求,整个运算周期,也就是输出数值更新周期为4,也就是4个时钟周期后才能更新一次m序列的输出结果;Utilization Estimates的Summary表格显示了最终生成的verilog代码所使用的的资源预估情况。
根据m序列的verilog实现以及使能信号解决跨时钟域问题可以知道,m序列的更新周期是可以达到0周期(也就是一个时钟周期输出一个数值);
所以还需要对HLS的代码进行优化,点击C Synthesis结果页面的Analysis标签,可以看到下图:
可以看到,for循环占用了一个时钟周期实现,而这个for循环其实只是简单的寄存器组左右移,是可以展开实现的。
回到m_seq.cpp,点击Directive标签,找到m_seq下的SHIFT_REG,右键点击'Insert Directive',Directive选择'UNROLL',点击OK;
重新仿真综合之后,可以看到结果:
可以与图7做对比,优化后Latency和资源占用都达到极致。
'UNROLL'在这里的作用是展开for循环,减小关键路径的Latency;可以看到展开for循环后,资源占用不仅没有增多,反而减少,这也许就是优化指令的魅力吧。
通过Project下的Export RTL,会产生一个zip的压缩文件;
将zip复制到Vivado项目文件夹下解压,在Vivado项目Project Setting下的IP标签的Repository里,将zip解压的文件夹加入进去;HLS的IP核就加入IP Catalog;
VCS仿真中,我们不使用IP核,而直接中仿真源文件m_seq.v,Testbench采用m序列的verilog实现以及使能信号解决跨时钟域问题的仿真文件;
在解压文件夹的hdlverilog文件夹下,将m_seq.v做仿真;ap_clk,ap_rst连接时钟和复位信号,ap_start可以用作m序列的使能信号,实现高速时钟下的低速运行;y_V是m序列的输出数值,y_V_ap_vld是输出数据的有效信号值;
可以看到,图15的仿真图与m序列的verilog实现以及使能信号解决跨时钟域问题中的最终仿真结果一样。
第一次使用HLS生成verilog,欢迎各位给出更有建设性的意见。
学习HLS主要参考资料为Xilinx的UG871和UG902,关注BUG记录公众号回复102获取HLS的参考资料。
万物皆可卷积:(实现BPSK学习Verilog)2. m序列的verilog实现以及使能信号解决跨时钟域问题zhuanlan.zhihu.com