Vivado HLS实现FIR滤波器(2)——Vivado调用HLS生成的FIR IP核

版权声明:转载请注明出处 https://blog.csdn.net/DengFengLai123/article/details/83957134

系统框图

器件xq7a50tfg484-2I,两个DDS,输入时钟100MHz,输出分别为8MHz和12MHz,位宽为16位,相乘后输出位宽32位,三角函数积化和差得4MHz信号和20MHz信号,滤波器设计采用Filter Solutions 2015,截止频率10MHz,采样率100MHz,Hamming窗,11阶,所得系数同时扩大100倍后四舍五入得到整数存入单口RAM,调用VIVADO HLS中生成的FIR滤波器IP核,输出滤波后的信号。
在这里插入图片描述

DDS IP核参数设置

(1)DDS IP核,IP Catalog->dds
在这里插入图片描述
(2)输入时钟100MHz,最下面的框中System Parameters中第一个设置不同的dB值获得不同的m_axis_data_tdata的位宽,此处设成70dB,最开始设成50dB时也是可以的,但是如果90dB位宽也是16位,相乘后滤波出来波形混乱,初步估计是溢出了。根据(3)中设置成输出Sine后位宽只有8位,设成70dB时位宽为16位,这样设置的原因是VIVADO HLS中生成的FIR滤波器IP核输入数据为32位,若两个DDS均输出16位,经过乘法器相乘后正好为32位,直接输入FIR滤波器,否则还需要做位宽处理。
在这里插入图片描述
(3)此图中的Output中算则Sine,如果选择了Sine and Cosine,那么位宽至少为16位,而选择了Sine选项输出数据位宽最少只需8位。在这里插入图片描述
(4)输出设置成8MHz和12MHz,相乘后得4MHz和20MHz信号。这样设置的原因有两个:一是因为频率较高时只需要仿真较短的时间即可看到完整的波形,如果设成几KHz信号需要仿真很长时间;二是因为滤波效果的原因,这也是我之前一直仿真不成功的原因,在Filter Solution 2015中设计FIR滤波器时有个选项是采样频率,之前我一直是按截止频率10倍设计的,但是考虑到VIVADO中仿真时输入时钟100MHz,相当于以100MHz的速率输入数据,按照100MHz采样率设计FIR时发现,对于几百KHz的截止频率下,11阶FIR滤波器滤波效果微乎其微,此处按照截止频率10MHz截止频率设计。
在这里插入图片描述

乘法器IP参数设置

(1)Mult乘法器
在这里插入图片描述
(2)参数设置
输入均16位,输出32位,输入输出均为有符号数signed
在这里插入图片描述

HLS生成的FIR IP核

(1)将HLS生成的IP核添加到VIVADO中。找到https://blog.csdn.net/DengFengLai123/article/details/83934462中提到的生成的.zip压缩包,将其移到一个新的文件夹下(最好是当前工程下),解压缩。

(2)在Setting->IP->Repository中点击add(加号),找到刚刚解压缩的文件路径,添加。
在这里插入图片描述
(3)此时就和官方自带的IP核一样使用了,Fir即为我的HLS生成的FIR滤波器IP核。
在这里插入图片描述
(4)如下图,生成的HLS的IP核会有VIVADO HLS的标注,会有一些多出的引脚和控制信号。因为在HLS中对输出的滤波器系数数组约束成了BRAM,所以会在时钟来时产生RAM的地址,通过该地址读取RAM中的滤波器系数,通过c_q0[31:0]输入。此时ap_start、ap_rst输入信号的高低电平需要根据HLS进行C/RTL协同仿真后的波形图设计。
在这里插入图片描述

RAM的IP核参数设置

(1)调用Block Memory Generator。
在这里插入图片描述
(2)设成单口RAM
在这里插入图片描述
(3)设置输入输出位宽32,深度11,其他保留默认设置。
在这里插入图片描述
(4)加载.coe文件,生成方法参考网上资料。
在这里插入图片描述
如下图,生成后的.coe文件第一行的10代表十进制,第二行是截止频率为10MHz的11阶FIR滤波器系数,该系数为Filter Solution 2015生成(生成方法参考网上资料http://www.mamicode.com/info-detail-2293172.html),对生成的系数扩大100倍后取四舍五入,获得整数系数。
在这里插入图片描述

仿真

(1)将该连接的线连好后,右键生成verilog文件和顶层调用。编写test bench文件test3。
在这里插入图片描述
在这里插入图片描述
(2)test3文件代码,两个dds的输出等信号我都引出了引脚查看波形。C/RTL协同仿真后查看波形,根据仿真波形的控制信号时序设定test3中信号的时序。ap_start信号先低后高,ap_rst信号先高后低,时钟100MHz,ena为RAM使能信号。

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Create Date: 2018/11/07 13:38:46
// Design Name: 
// Module Name: test3
//////////////////////////////////////////////////////////////////////////////////

module test3(

    );
    
reg ap_clk;
reg ap_rst;
reg ap_start;
reg ena;

wire [15:0] dds_0;
wire [15:0] dds_1;
wire [31:0] P;
wire [31:0] y;
wire [3:0] c_address0;
wire [31:0] douta;
wire [31:0] data_out;
wire y_ap_vld;

initial 
begin 
    ap_clk = 0;
    ap_start = 0;
    ap_rst = 1;
    ena = 0;
    #10;
    ap_start = 1;
    ap_rst = 0;
    ena = 1;
end
                
always #5 ap_clk = ~ap_clk;
    
hls_fir_1_wrapper hls_fir_1_wrapper_1
           (
                   .P(P),
                   .ap_clk(ap_clk),
                   .ap_rst(ap_rst),
                   .ap_start(ap_start),
                   .c_address0(c_address0),
                   .data_out(data_out),
                   .dds_0(dds_0),
                   .dds_1(dds_1),
                   .douta(douta),
                   .ena(ena),
                   .y(y),
                   .y_ap_vld(y_ap_vld)
               );
            
endmodule

在这里插入图片描述
在这里插入图片描述
(3)文件结构
在这里插入图片描述
(4)设置仿真顶层文件
在这里插入图片描述
在这里插入图片描述
(5)点击Run Simulation,进行仿真。应该是输出y[31:0]一直为高阻态X,细心的如果看到我(3)中的程序结构,会发现有一个ram_out_0一直没有提到,这个模块是我自己写的,如果没有这个模块,输出y会是高阻态X,下一篇会讲为什么。
在这里插入图片描述

提示,注意观察HLS中c_addr有一段是为高阻态,是因为[3:0]表示0-15,但只用到了0-10,其他为高阻态,高阻态时的c_q0输出为0。但是在vivado中当给定RAM地址为高阻态时输出也为高阻态,这样在计算输出y时每次都有高阻态存在,导致y输出为高阻态,从这个方向上去想可以解决问题了。(如何让输入Fir IP核的滤波器系数在c_addr为高阻态时输出为0而不是高阻态)
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/DengFengLai123/article/details/83957134