并行FIR滤波器

这篇具有很好参考价值的文章主要介绍了并行FIR滤波器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

FIR 滤波器原理

FIR 滤波器是有限长单位冲击响应滤波器,又称为非递归型滤波器。FIR 滤波器具有严格的线性相频特性,同时其单位响应是有限长的,因而是稳定的系统。

FIR 滤波器本质上就是输入信号与单位冲击响应函数的卷积,表达式如下:

并行FIR滤波器,农夫笔记,fpga开发

直接型结构如下:

并行FIR滤波器,农夫笔记,fpga开发
FIR 滤波器有如下几个特性:

  • (1) 响应是有限长序列。
  • (2) 系统函数在 |z| > 0 处收敛,极点全部在 z=0 处,属于因果系统。
  • (3) 结构上是非递归的,没有输出到输入的反馈。
  • (4) 输入信号相位响应是线性的,因为响应函数 h(n) 系数是对称的。
  • (5) 输入信号的各频率之间,相对相位差也是固定不变的。
  • (6) 时域卷积等于频域相乘,因此该卷积相当于筛选频谱中各频率分量的增益倍数。某些频率分量保留,某些频率分量衰减,从而实现滤波的效果。

并行 FIR 滤波器设计

设计说明

输入频率为 7.5 MHz 和 250 KHz 的正弦波混合信号,经过 FIR 滤波器后,高频信号 7.5MHz 被滤除,只保留 250KHz 的信号。设计参数如下:

输入频率:       7.5MHz 和 250KHz
采样频率:       50MHz
阻带:           1MHz ~ 6MHz
阶数:           15(N-1=15)

由 FIR 滤波器结构可知,阶数为 15 时,FIR 的实现需要 16 个乘法器,15 个加法器和 15 组延时寄存器。为了稳定第一拍的数据,可以再多用一组延时寄存器,即共用 16 组延时寄存器。由于 FIR 滤波器系数的对称性,乘法器可以少用一半,即共使用 8 个乘法器。类似下面结构:

并行FIR滤波器,农夫笔记,fpga开发

并行设计,就是在一个时钟周期内对 16 个延时数据同时进行乘法、加法运算,然后在时钟驱动下输出滤波值。这种方法的优点是滤波延时短,但是对时序要求比较高。

并行设计

FIR 滤波器系数由 matlab 生成。

代码以功能实现为目标

/***********************************************************
>> V : Fs:50Mhz, fstop:1Mhz-6Mhz, order: 15
************************************************************/
`define SAFE_DESIGN
 
module fir_parallel    (
    input                rstn,  //复位,低有效
    input                clk,   //工作频率,即采样频率
    input                en,    //输入数据有效信号
    input        [11:0]  xin,   //输入混合频率的信号数据
    output               valid, //输出数据有效信号
    output       [28:0]  yout   //输出数据,低频信号,即250KHz
    );
 
    //data en delay
    reg [3:0]            en_r ;
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            en_r[3:0]      <= 'b0 ;
        end
        else begin
            en_r[3:0]      <= {en_r[2:0], en} ;
        end
    end
 
   //(1) 16 组移位寄存器
    reg        [11:0]    xin_reg[15:0];
    reg [3:0]            i, j ;
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            for (i=0; i<15; i=i+1) begin
                xin_reg[i]  <= 12'b0;
            end
        end
        else if (en) begin
            xin_reg[0] <= xin ;
            for (j=0; j<15; j=j+1) begin
                xin_reg[j+1] <= xin_reg[j] ; //周期性移位操作
            end
        end
    end
 
   //Only 8 multipliers needed because of the symmetry of FIR filter coefficient
   //(2) 系数对称,16个移位寄存器数据进行首位相加
    reg        [12:0]    add_reg[7:0];
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            for (i=0; i<8; i=i+1) begin
                add_reg[i] <= 13'd0 ;
            end
        end
        else if (en_r[0]) begin
            for (i=0; i<8; i=i+1) begin
                add_reg[i] <= xin_reg[i] + xin_reg[15-i] ;
            end
        end
    end
 
    //(3) 8个乘法器
    // 滤波器系数,已经过一定倍数的放大
    wire        [11:0]   coe[7:0] ;
    assign coe[0]        = 12'd11 ;
    assign coe[1]        = 12'd31 ;
    assign coe[2]        = 12'd63 ;
    assign coe[3]        = 12'd104 ;
    assign coe[4]        = 12'd152 ;
    assign coe[5]        = 12'd198 ;
    assign coe[6]        = 12'd235 ;
    assign coe[7]        = 12'd255 ;
    wire        [24:0]   mout[7:0];
 
`ifdef SAFE_DESIGN
    //流水线式乘法器
    wire [7:0]          valid_mult ;
    genvar              k ;
    generate
        for (k=0; k<8; k=k+1) begin
            mult_man #(13, 12)
            u_mult_paral          (
              .clk        (clk),
              .rstn       (rstn),
              .data_rdy   (en_r[1]),
              .mult1      (add_reg[k]),
              .mult2      (coe[k]),
              .res_rdy    (valid_mult[k]), //所有输出使能完全一致  
              .res        (mout[k])
            );
        end
    endgenerate
    wire valid_mult7     = valid_mult[7] ;
 
`else
    //如果对时序要求不高,可以直接用乘号
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            for (i=0 ; i<8; i=i+1) begin
                mout[i]     <= 25'b0 ;
            end
        end
        else if (en_r[1]) begin
            for (i=0 ; i<8; i=i+1) begin
                mout[i]     <= coe[i] * add_reg[i] ;
            end
        end
    end
    wire valid_mult7 = en_r[2];
`endif
 
    //(4) 积分累加,8组25bit数据 -> 1组 29bit 数据
    //数据有效延时
    reg [3:0]            valid_mult_r ;
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            valid_mult_r[3:0]  <= 'b0 ;
        end
        else begin
            valid_mult_r[3:0]  <= {valid_mult_r[2:0], valid_mult7} ;
        end
    end

`ifdef SAFE_DESIGN
    //加法运算时,分多个周期进行流水,优化时序
    reg        [28:0]    sum1 ;
    reg        [28:0]    sum2 ;
    reg        [28:0]    yout_t ;
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            sum1   <= 29'd0 ;
            sum2   <= 29'd0 ;
            yout_t <= 29'd0 ;
        end
        else if(valid_mult7) begin
            sum1   <= mout[0] + mout[1] + mout[2] + mout[3] ;
            sum2   <= mout[4] + mout[5] + mout[6] + mout[7] ;
            yout_t <= sum1 + sum2 ;
        end
    end
 
`else
    //一步计算累加结果,但是实际中时序非常危险
    reg signed [28:0]    sum ;
    reg signed [28:0]    yout_t ;
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            sum    <= 29'd0 ;
            yout_t <= 29'd0 ;
        end
        else if (valid_mult7) begin
            sum    <= mout[0] + mout[1] + mout[2] + mout[3] + mout[4] + mout[5] + mout[6] + mout[7];
            yout_t <= sum ;
        end
    end
`endif
    assign yout  = yout_t ;
    assign valid = valid_mult_r[0];

endmodule

testbench

testbench 如下,主要功能就是不间断连续的输入 250KHz 与 7.5MHz 的正弦波混合信号数据。输入的混合信号数据也由 matlab 生成。

`timescale 1ps/1ps
 
module test ;
   //input
    reg          clk ;
    reg          rst_n ;
    reg          en ;
    reg [11:0]   xin ;
    //output
    wire         valid ;
    wire [28:0]  yout ;
 
    parameter    SIMU_CYCLE   = 64'd2000 ;  //50MHz 采样频率
    parameter    SIN_DATA_NUM = 200 ;       //仿真周期

//=====================================
// 50MHz clk generating
    localparam   TCLK_HALF     = 10_000;
    initial begin
        clk = 1'b0 ;
        forever begin
            # TCLK_HALF ;
            clk = ~clk ;
        end
    end
 
//============================
//  reset and finish
    initial begin
        rst_n = 1'b0 ;
        # 30   rst_n = 1'b1 ;
        # (TCLK_HALF * 2 * SIMU_CYCLE) ;
        $finish ;
    end
 
//=======================================
// read signal data into register
    reg          [11:0] stimulus [0: SIN_DATA_NUM-1] ;
    integer      i ;
    initial begin
        $readmemh("cosx0p25m7p5m12bit.txt", stimulus) ;//windows下似乎只能使用绝对路径
        i = 0 ;
        en = 0 ;
        xin = 0 ;
        # 200 ;
        forever begin
            @(negedge clk) begin
                en          = 1'b1 ;
                xin         = stimulus[i] ;
                if (i == SIN_DATA_NUM-1) begin  //周期送入数据控制
                    i = 0 ;
                end
                else begin
                    i = i + 1 ;
                end
            end
        end
    end
 
    fir_parallel u_fir_paral (
      .xin         (xin),
      .clk         (clk),
      .en          (en),
      .rstn        (rst_n),
      .valid       (valid),
      .yout        (yout));
 
endmodule

仿真结果

由下图仿真结果可知,经过 FIR 滤波器后的信号只有一种低频率信号(250KHz),高频信号(7.5MHz)被滤除了。而且输出波形是连续的,能够持续输出。

并行FIR滤波器,农夫笔记,fpga开发

并行FIR滤波器,农夫笔记,fpga开发

matlab 使用

生成 FIR 滤波器系数

打开 matlab,在命令窗口输入命令: fdatool。

然后会打开如下窗口,按照 FIR 滤波器参数进行设置。

这里选择的 FIR 实现方法是最小二乘法(Least-squares),不同的实现方式滤波效果也不同,对应的滤波器系数也不同。

并行FIR滤波器,农夫笔记,fpga开发

点击 File -> Export

将滤波器参数输出,存到变量 coef 中,如下图所示。

并行FIR滤波器,农夫笔记,fpga开发

此时 coef 变量应该是浮点型数据。对其进行一定倍数的相乘扩大,然后取其近似的定点型数据作为设计中的 FIR 滤波器参数。这里取扩大倍数为 2048,结果如下所示。

并行FIR滤波器,农夫笔记,fpga开发

生成输入的混合信号

利用 matlab 生成混合的输入信号参考代码如下。

信号为无符号定点型数据,位宽宽度为 12bit,存于文件 cosx0p25m7p5m12bit.txt文章来源地址https://www.toymoban.com/news/detail-648035.html


```matlab
clear all;close all;clc;
%=======================================================
% generating a cos wave data with txt hex format
%=======================================================

fc          = 0.25e6 ;      % 中心频率
fn          = 7.5e6 ;       % 杂波频率
Fs          = 50e6 ;        % 采样频率
T           = 1/fc ;        % 信号周期
Num         = Fs * T ;      % 周期内信号采样点数
t           = (0:Num-1)/Fs ;      % 离散时间
cosx        = cos(2*pi*fc*t) ;    % 中心频率正弦信号
cosn        = cos(2*pi*fn*t) ;    % 杂波信号
cosy        = mapminmax(cosx + cosn) ;     %幅值扩展到(-1,1) 之间
cosy_dig    = floor((2^11-1) * cosy + 2^11) ;     %幅值扩展到 0~4095
fid         = fopen('cosx0p25m7p5m12bit.txt', 'wt') ;  %写数据文件
fprintf(fid, '%x\n', cosy_dig) ;
fclose(fid) ;
 
%时域波形
figure(1);
subplot(121);plot(t,cosx);hold on ;
plot(t,cosn) ;
subplot(122);plot(t,cosy_dig) ;
 
%频域波形
fft_cosy    = fftshift(fft(cosy, Num)) ;
f_axis      = (-Num/2 : Num/2 - 1) * (Fs/Num) ;
figure(5) ;
plot(f_axis, abs(fft_cosy)) ;

到了这里,关于并行FIR滤波器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 利用FPGA实现全串行低通FIR滤波器

    设计一个15阶(长度为16)的具有线性相位低通FIR滤波器,采用布拉克曼窗函数设计,截止频率为500HZ,抽样频率为2000HZ;采用FPGA实现全串行FIR滤波器,系数的量化位数为12比特,输入数据位数为12比特,输出数据位数为29比特,系统时钟为16KHZ 设计思路 :首先采用MATLAB根据要

    2024年02月07日
    浏览(24)
  • FIR内插滤波器的FPGA实现(一)-matlab实现

    FIR内插滤波器是一种基本的插值方法,主要有两个步骤: 1)在输入的每一个初始采样中间插入L个零点; 2)插零后的数据经过低通滤波器。 运行结果如图(时域、频域): 我们的目标是把采样频率提升五十倍。 得到的频域图: 可以看出内插零点在频域会实现频谱扩展,因此

    2024年02月03日
    浏览(27)
  • FIR滤波器的FPGA实现【IP核实现版】

    本文使用FPGA来实现FIR滤波器设计,设计中使用的DDS、乘法器与FIR滤波器均采用IP core进行实现,实现效果是将3MHz和4MHz的正弦信号混频后使用FIR低通滤波器滤除7MHz信号得到1MHz的信号。 首先用两个DDS核生成3MHz以及4MHz的正弦波信号。 注意:此处的dds的命名要和代码中对应,系统

    2024年02月04日
    浏览(20)
  • FPGA 的 DSP:Verilog 中的简单 FIR 滤波器

    本项目介绍如何用 Verilog 实现一个带有预生成系数的简单 FIR 滤波器。 简陋的 FIR 滤波器是 FPGA 数字信号处理中最基本的构建模块之一,因此了解如何利用给定的抽头数和相应的系数值组装一个基本模块非常重要。因此,在这个关于在 FPGA 上入门 DSP 基础知识的实用方法迷你系

    2024年03月17日
    浏览(25)
  • 解析使用FPGA逻辑实现FIR滤波器的几种架构

    有限脉冲响应(finite impulse response,FIR)数字滤波器         FIR滤波器的实质就是输入序列与系统脉冲响应的卷积,即:         其中,N为滤波器的阶数,也即抽头数;x(n)为第n个输入序列;h(n)为FIR滤波器的第n级抽头系数。         FIR滤波器基本结构如下:      

    2024年02月08日
    浏览(20)
  • FPGA 的数字信号处理:Verilog 实现简单的 FIR 滤波器

    该项目介绍了如何使用 Verilog 实现具有预生成系数的简单 FIR 滤波器。 不起眼的 FIR 滤波器是 FPGA 数字信号处理中最基本的模块之一,因此了解如何将具有给定抽头数及其相应系数值的基本模块组合在一起非常重要。因此,在这个关于 FPGA 上 DSP 基础实用入门的教程中,将从一

    2024年02月09日
    浏览(26)
  • 基于FPGA的FIR数字滤波器设计(quartus和vivado程序都有)。

    基于FPGA的FIR数字滤波器设计(quartus和vivado程序都有)。 附: 1.配套quartus从MATLAB系数生成直到仿真成功说明文档。 2.配套仿真出波形(图1)的视频。      

    2024年02月10日
    浏览(27)
  • 基于FPGA的FIR低通滤波器实现(附工程源码),matlab+vivado19.2+simulation

    本文为FPGA实现FIR滤波器仿真过程,附源代码。 提示:以下是本篇文章正文内容,下面案例可供参考 打开MATLAB在命令行窗口输入: fadtool 回车后在滤波器设计界面设置滤波器参数如下 之后点击如图标志,设置定点,在菜单栏\\\"目标(R)\\\"出选择生成对应滤波器系数.COE文件 mat

    2024年02月11日
    浏览(23)
  • 【VHDL笔记】 FIR滤波器的设计(基于Quartus II软件)

    PS:此文章仅供参考 本文介绍了使用VHDL语言实现一个FIR滤波器的设计 以下是本篇文章正文内容,代码可供参考 通常数字滤波器常用于修正或改变时域中信号的属性。学过信号与系统的同学应该知道,最为普通的数字滤波器就是 线性时不变量(LTI)滤波器,线性时不变量滤波

    2023年04月13日
    浏览(26)
  • 数字信号处理音频FIR去噪滤波器(基于MATLAB GUI的开发)

    利用MATLAB GUI设计平台,用窗函数法设计FIR数字滤波器,对所给出的含有噪声的声音信号进行数字滤波处理,得到降噪的声音信号,进行时域频域分析,同时分析不同窗函数的效果。将文件解压至一个目录下,运行m文件即可使用。 读取.wav音频文件函数 :audioread();(老版

    2024年02月08日
    浏览(22)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包