用HDL、HLS C流程实现流处理方式的时域滤波(FIR),要求:
输入直流及2个频率分别为2kHz和10kHz的正弦实信号叠加,三个信号幅度为2.0、1.0、1.5要求过滤掉0Hz和10kHz信号,仅剩2kHz正弦实信号定点化,获得输入/输出信号和FIR系数的定点精度。要求与浮点实现的均方差不大于-40dB生成的IP放入SysGen中验证生成bit文件在板验证直接结构用到了多个移位寄存器,相乘后累加,思路简单但是效率较低,改变拓扑之后的转置结构有更高的效率;格形结构又较为复杂,因此在本实验的两个流程和定浮点实现方案中,均采用转置结构,保持前后统一。
在本实验中使用 sysgen 的 fdatool 工具对滤波器系数进行初步的构造,在后面的实验中发现得到的一组系数具有较好的性能。设计的滤波器为带通,窗函数为Hamming窗,阶数取68阶,截止频率为2.01kHz和4.49kHz。采样频率为奈奎斯特采样频率的4倍,即80kHz,滤波器波形以及具体系数如下。
Directive的优化中,对函数使用了HLS PIPELINE II=1 (流水线处理) 和HLS INTERFACE ap_ctrl_none port = return;对din和dout使用了HLS INTERFACE ap_none port ;对循环操作使用HLS UNROLL进行展开,以谋求并行化处理提高系统运行速度。
#ifndef _FIR_1X_H #define _FIR_1X_H #include "hls_dsp.h" #define FIR_TAP_NUM 69 #define RUN_LENGTH 1300 const unsigned SCALAR_ROUND_MODE = 0;//AP_TRN, etc; const unsigned SCALAR_OVERFLOW_MODE = 2;//AP_WRAP, etc; const unsigned SCALAR_SATURATION_BITS = 0; // input data types const unsigned INPUT_SCALAR_WIDTH = 16; const unsigned INPUT_SCALAR_INTEGER_BITS = 4; typedef ap_fixed< INPUT_SCALAR_WIDTH, INPUT_SCALAR_INTEGER_BITS, (ap_q_mode)SCALAR_ROUND_MODE, (ap_o_mode)SCALAR_OVERFLOW_MODE, SCALAR_SATURATION_BITS> t_input_scalar; // output data types const unsigned OUTPUT_SCALAR_WIDTH = 32; const unsigned OUTPUT_SCALAR_INTEGER_BITS = 8; typedef ap_fixed< OUTPUT_SCALAR_WIDTH, OUTPUT_SCALAR_INTEGER_BITS, (ap_q_mode)SCALAR_ROUND_MODE, (ap_o_mode)SCALAR_OVERFLOW_MODE, SCALAR_SATURATION_BITS> t_output_scalar; void fir_1x ( const t_input_scalar& din, t_output_scalar& dout); extern const t_input_scalar coe[FIR_TAP_NUM]; #endif #include <stdio.h> #include <stdlib.h> #include "hls_stream.h" #include "fir_1x.h" using namespace hls; const t_input_scalar coe[FIR_TAP_NUM] = { #include "Yourdata.txt" }; void fir_1x ( const t_input_scalar& din, t_output_scalar& dout) { #pragma HLS INTERFACE ap_none port=dout #pragma HLS INTERFACE ap_none port=din #pragma HLS PIPELINE II=1 #pragma HLS INTERFACE ap_ctrl_none port=return static t_output_scalar product1[FIR_TAP_NUM+1]={t_output_scalar(0)}; #pragma HLS ARRAY_PARTITION variable=product1 complete dim=1 // output dout = product1[FIR_TAP_NUM]; label_mulacc: for (int gv_i=0;gv_i<FIR_TAP_NUM;gv_i++) { #pragma HLS UNROLL product1[FIR_TAP_NUM-gv_i] = din * coe[FIR_TAP_NUM-gv_i-1] + product1[FIR_TAP_NUM-gv_i-1]; } };首先对HLS C流程的定点实现方式和sysgen的FIR Compiler 7.2进行下比较 发现HLS C生成的IP 放入sysgen中与sysgen自带的FIR还是存在一定的差距(猜测是所采用的FIR结构并不一样),前者与后者相比存在一定的幅度衰减,但是处理时延较低,谱的纯度也较好,已经较好地滤除了0频分量和10kHz高频分量。接下来将HLS C的定浮点方式在sysgen中进行比较 发现浮点处理方式时延十分严重,但二者的幅度是相近的,另一个足以说明定点方式优于浮点方式的理由是,浮点方式占用的资源过多,在实际的上板操作中是难以实现的(下面两图分别为浮点和定点实现)
在Matlab中对HLS C与HDL流程定浮点方案的差别进行比较,将各波形平移对齐后进行最小均方差计算,再将最小均方差用dB进行表示。假设两种信号 { x k } { y k } \{x_k\}\{y_k\} {xk}{yk}所取得采样点数均为 K K K,我们取 { x k } \{x_k\} {xk}作为基准信号,则均方差的计算公式为 ξ = ∑ k = 1 K ( x k − y k ) 2 ∑ k = 1 K x k 2 ξ ( d B ) = 10 ∗ log 10 ξ \begin{array}{l} \xi=\dfrac{\sum_{k=1}^{K}\left(x_{k}-y_{k}\right)^{2}}{\sum_{k=1}^{K} x_{k}^{2}} \\ \xi_{(d B)}=10 * \log _{10} \xi \end{array} ξ=∑k=1Kxk2∑k=1K(xk−yk)2ξ(dB)=10∗log10ξ 有想要了解Vivado各个流程实现的朋友可以参考本链接
