[原创] FPGA设计一个FIR数字滤波器(vivado+MATLAB)

1nnocent   2024-11-18 11:13 楼主

要求

    设计一个带通滤波器,并验证其功能。

1、使用MATLAB设计滤波器系数

    MATLAB首页找到APP后找到滤波器设计工具并打开,使用该工具可以生成数字滤波器的系数后续用于FPGA配置FIR IP核。

image.png  

    打开滤波器设计工具后即可输入相关参数并设计需要的滤波器,本次设计一个带通滤波器,所以滤波器响应类型选择带通;设计方案选择FIR(有限冲激响应);滤波器阶数这里选择最小阶,也可以自己指定阶数,阶数越大滤波器的滤波效果越好但越耗费FPGA资源,阶数可以根据实际情况进行取舍;密度因子默认20;频率设定,本次设计的采样率设置为10MHz,滤波器的频率特性设置可以按照图示进行填写,图片指示的意义很清楚,Fstop1为下限阻带截止频率,这里设置为50kHz,Fpass1为下限通带截止频率,这里设置为100kHz,Fpass2为上限通道截止频率,这里设置为400kHz,Fstop2为上限阻带截止频率,这里设置为450kHz(Fpass1-Fstop1和Fstop2-Fpass2为过渡带宽度,本次设计的过渡带宽度为50kHz;Fpass2-Fpass1为通带宽度,本次设计的通带宽度为400kHz;其余为阻带);幅值设定,其中Astop为阻带衰减的幅度值,本次设计阻带衰减50dB,Apass为通带的纹波,这里限制通带纹波不超过0.1dB。

image.png  

    设置好以上参数后点击滤波器设计,等待片刻即可设计好所需滤波器,从左侧窗口当前滤波器信息中可以发现符合本次设计需求的最小阶数为483阶。

image.png  

    点击工具栏   image.png 可以查看滤波器幅值响应、相位响应、零极点等。

    点击工具栏文件--导出,即可导出设计的滤波器系数。导出后可以在工作区中看到滤波器系数的变量Num。

image.png  

    以下为本次导出的系数,一共484个。

image.png       滤波器系数在FPGA中导入时每个系数之间需要逗号隔开,所以这里将系数保存到txt并使用逗号隔开,注意最后一个数的逗号需要删除。

image.png  

    生成后的系数删除最后的逗号。

image.png  

2、FPGA中FIR的实现

  这里省略FPGA工程建立过程,新建工程后点击Create Block Design。

image.png  

    添加FIR IP核。

image.png  

    配置FIR IP核,Filter Option中Select Source选择Vector,Coefficient Vector中粘贴之前MATLAB生成的系数,其余保持默认。左边Freq.Response窗口中可以查看频率响应曲线。

image.png  

    Channel Specification中主要配置采样率和工作时钟,input Sampling Frequency(MHz)配置10MHz采样率,后续DDS工作时钟需要和采样率保持一致;Clock Frequency(MHz)配置200MHz后续FIR IP核的工作时钟给200MHz。

image.png       Implement配置,Coefficient With可以根据需要进行配置,本次设计时配置成24,配置成24时通过查看左边Freq.Response窗口可以发现两条红色和蓝色曲线重合较接近理想曲线Ideal,所以这里配置成24,也可以根据需要进行配置。

image.png       Interface这里配置如下:

image.png      FIR配置完后再增加一个fifo,配置如下:

image.png

    配置完后将FIR和fifo相连并引出接口:

image.png  

    最后右击block design先generate Output ...再Create HDL...。

image.png

 

3、FPGA中DDS的实现

    这里DDS用于产生FIR的输入信号。同样点击Create Block Design,添加DDS IP核。

image.png  

    Configuration配置System Clock(MHz)为10MHz即可,其余保持默认配置。

image.png       Detailed Implementation配置如下:

image.png  

    最后输出频率配置成0.15MHz即150kHz,也可以根据需要进行配置。

image.png       按照上述配置再生成50kHz、350kHz、450kHz频率的DDS。

image.png  

    生成完DDS后再生成一个fifo。该fifo用于跨时钟域,将DDS产生的10MHz时钟域的信号转到200MHz时钟域输入FIR进行滤波。fifo配置如下,深度16,数据位宽16bit。

image.png  

    最后将生成的IP核按下图连线,该dds用于测试fir滤波器。可以外部可以将DDS生成的350kHz和150kHz进行叠加后再输入到fifo中,最后经过跨时钟域后从Multi_wave_M_AXIS输出到FIR进行滤波,叠加后的波形存在和频(500kHz)、差频(200kHz),经过滤波器后只剩下差频200kHz,如果滤波器输出200kHz正弦波则说明设计符合预期。也可以将单频信号(50kHz/150kHz/350kHz/450kHz)输入滤波器查看滤波器输出幅度情况。

image.png  

4、top模块编写

     顶层模块例化两个block_design ,dds产生50kHz、150kHz、350kHz和450kHz的正弦信号,外部将dds生成的其中两个信号做乘法后输入到dds的fifo接口中,使相乘的信号从10Mhz时钟域到200Mhz时钟域,最后输入到FIR中进行滤波。如果需要测试FIR单频信号的滤波器则可以将DDS输出的其中一个信号与常数相乘后再输入到FIR中进行测试。另外top模块中还需例化一个pll产生10MHz时钟用于DDS产生信号,以及200MHz时钟用于FIR。


module fir_top(
    input       pl_ref_clk_100m_p,
    input       pl_ref_clk_100m_n
);
    reg  [4:0]          cnt;
    wire                clk_10m,clk_200m;
    wire signed [7:0]   M_AXIS_50k_tdata;
    wire                M_AXIS_50k_tvalid,M_AXIS_50k_tready;
    wire signed [7:0]   M_AXIS_150k_tdata;
    wire                M_AXIS_150k_tvalid,M_AXIS_150k_tready;
    wire signed [7:0]   M_AXIS_350k_tdata;
    wire                M_AXIS_350k_tvalid,M_AXIS_350k_tready;
    wire signed [7:0]   M_AXIS_450k_tdata;
    wire                M_AXIS_450k_tvalid,M_AXIS_450k_tready;
    wire signed [15:0]  Multi_wave_S_AXIS_tdata;
    wire                Multi_wave_S_AXIS_tvalid,Multi_wave_S_AXIS_tready;
    wire signed [15:0]  Multi_wave_M_AXIS_tdata;
    wire                Multi_wave_M_AXIS_tvalid,Multi_wave_M_AXIS_tready;
    wire signed [15:0]  FIR_S_AXIS_tdata;
    wire                FIR_S_AXIS_tvalid,FIR_S_AXIS_tready;
    wire signed [23:0]  FIR_M_AXIS_tdata;
    wire                FIR_M_AXIS_tvalid,FIR_M_AXIS_tready;
    assign rst_n = locked;
    // Multi_wave_S_AXIS
    assign Multi_wave_S_AXIS_tdata  = M_AXIS_450k_tdata   *   8'hff/*M_AXIS_350k_tdata    */;
    assign Multi_wave_S_AXIS_tvalid = M_AXIS_450k_tvalid  &   1/*M_AXIS_350k_tvalid   */;
    assign M_AXIS_50k_tready        = Multi_wave_S_AXIS_tready;
    assign M_AXIS_150k_tready       = Multi_wave_S_AXIS_tready;
    assign M_AXIS_350k_tready       = Multi_wave_S_AXIS_tready;
    assign M_AXIS_450k_tready       = Multi_wave_S_AXIS_tready;
    // Multi_wave_M_AXIS
    assign FIR_S_AXIS_tvalid        = Multi_wave_M_AXIS_tvalid;
    assign FIR_S_AXIS_tdata         = Multi_wave_M_AXIS_tdata;
    assign Multi_wave_M_AXIS_tready  = FIR_S_AXIS_tready;
    
    assign FIR_M_AXIS_tready        = (cnt == 'd19) && Multi_wave_M_AXIS_tvalid;
dds_design_wrapper dds_design(
    .M_AXIS_150k_tdata      (M_AXIS_150k_tdata      ),
    .M_AXIS_150k_tready     (M_AXIS_150k_tready     ),
    .M_AXIS_150k_tvalid     (M_AXIS_150k_tvalid     ),
    .M_AXIS_350k_tdata      (M_AXIS_350k_tdata      ),
    .M_AXIS_350k_tready     (M_AXIS_350k_tready     ),
    .M_AXIS_350k_tvalid     (M_AXIS_350k_tvalid     ),
    .M_AXIS_450k_tdata      (M_AXIS_450k_tdata      ),
    .M_AXIS_450k_tready     (M_AXIS_450k_tready     ),
    .M_AXIS_450k_tvalid     (M_AXIS_450k_tvalid     ),
    .M_AXIS_50k_tdata       (M_AXIS_50k_tdata       ),
    .M_AXIS_50k_tready      (M_AXIS_50k_tready      ),
    .M_AXIS_50k_tvalid      (M_AXIS_50k_tvalid      ),
    .Multi_wave_M_AXIS_tdata (Multi_wave_M_AXIS_tdata ),
    .Multi_wave_M_AXIS_tready(Multi_wave_M_AXIS_tready),
    .Multi_wave_M_AXIS_tvalid(Multi_wave_M_AXIS_tvalid),
    .Multi_wave_S_AXIS_tdata (Multi_wave_S_AXIS_tdata ),
    .Multi_wave_S_AXIS_tready(Multi_wave_S_AXIS_tready),
    .Multi_wave_S_AXIS_tvalid(Multi_wave_S_AXIS_tvalid),
    .aresetn                (rst_n                  ),
    .clk_10m                (clk_10m                ),
    .clk_200m               (clk_200m               )
); 
    always@(posedge clk_200m or negedge rst_n)begin
        if(!rst_n)begin
            cnt <= 'd0;
        end 
        else begin
            cnt <= (cnt == 'd19)? 'd0 : (cnt + 1'b1);
        end 
    end 
bandpass_fir_wrapper bandpass_fir(
    .FIR_M_AXIS_tdata   (FIR_M_AXIS_tdata   ),
    .FIR_M_AXIS_tready  (FIR_M_AXIS_tready  ),
    .FIR_M_AXIS_tvalid  (FIR_M_AXIS_tvalid  ),
    .FIR_S_AXIS_tdata   (FIR_S_AXIS_tdata   ),
    .FIR_S_AXIS_tready  (FIR_S_AXIS_tready  ),
    .FIR_S_AXIS_tvalid  (FIR_S_AXIS_tvalid  ),
    .aresetn            (rst_n              ),
    .clk_200m           (clk_200m           )
);
clk_wiz_0 pll(
    .clk_10m(clk_10m),
    .clk_200m(clk_200m),     // output clk_200m
    .reset(1'b0), // input reset
    .locked(locked),       // output locked
    .clk_100m_in(clk_100m)      // input clk_100m_in
);  
IBUFDS clk_100m_ibufds(
    .O	(clk_100m),
    .I	(pl_ref_clk_100m_p),
    .IB	(pl_ref_clk_100m_n)
);
endmodule

5、功能仿真

 

     DDS产生的四个信号如下:

50kHz信号,一个时钟周期的时间为102.31-82.31=20us,刚好为50kHz。

image.png  150kHz,一个时钟周期的时间为82.51-75.91=6.6us,频率约为151515Hz。

image.png  350kHz,一个是时钟周期的时间为71.21-68.31=2.9us,频率约为344827Hz。

image.png  450kHz,一个时钟周期的时间为91.51-89.31=2.2us,频率约为454545Hz。

image.png       将150kHz正弦和350kHz正弦叠加后输入到FIR,输入信号代码修改如下:

image.png  

    两个光标之间的间隔为112.975-102.975=10us,每个时钟周期为5us,所以滤波器输出的频率为200kHz。由于输入的信号为150kHz正弦波叠加350kHz的正弦波,叠加后的波形存在和频500kHz和差频200kHz,由于500kHz在滤波器通频带外,所以500kHz的信号会被滤除,经过滤波器后只剩下200kHz的正弦波。所以仿真结果符合滤波器特性。仿真波形如下图,其中FIR_M_AXIS_tdata信号为FIR滤波输出信号。

image.png       将50kHz正弦信号输入FIR,输入信号代码修改如下:50kHz信号与常数8‘hff叠加后输入到FIR。

image.png  

    由于50kHz在滤波器带外,所以经过滤波器后幅度应该被衰减。仿真波形如下图,FIR输出信号FIR_M_AXIS_tdata被衰减,符合预期。

image.png      将150kHz正弦信号输入FIR,输入信号代码修改如下:150kHz信号与常数8‘hff叠加后输入到FIR。

image.png  

    由于150kHz在滤波器带内,所以经过滤波器后幅度不变。仿真波形如下图,FIR输出信号FIR_M_AXIS_tdata幅度正常,符合预期。

image.png      将350kHz正弦信号输入FIR,输入信号代码修改如下:350kHz信号与常数8‘hff叠加后输入到FIR。

image.png  

    由于350kHz在滤波器带内,所以经过滤波器后幅度不变。仿真波形如下图,FIR输出信号FIR_M_AXIS_tdata幅度正常,符合预期。

image.png      将450kHz正弦信号输入FIR,输入信号代码修改如下:450kHz信号与常数8‘hff叠加后输入到FIR。

image.png  

    由于450kHz在滤波器带外,所以经过滤波器后幅度应该被衰减。仿真波形如下图,FIR输出信号FIR_M_AXIS_tdata被衰减,符合预期。

image.png  

6、结论

     从仿真结果可知输入信号不管是单频信号还是叠加后的双频信号,结果都符合预期。

工程源码:

fir.rar (43.79 MB)
(下载次数: 0, 4 小时前 上传)
本帖最后由 1nnocent 于 2024-11-18 11:13 编辑

回复评论 (2)

酷!!!!!给你一个超大的赞!!

玩板看这里: https://bbs.eeworld.com.cn/elecplay.html EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!
点赞  2024-11-18 11:42
引用: okhxyyo 发表于 2024-11-18 11:42 酷!!!!!给你一个超大的赞!!

点赞  2024-11-18 14:24
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复