FPGA数字信号处理(二)并行FIR滤波器Verilog设计

该篇是FPGA数字信号处理的第二篇,选题为DSP系统中极其常用的FIR滤波器。本文将简单介绍FIR滤波器的原理,详细介绍使用Verilog HDL设计并行FIR滤波器的流程和方法。接下来几篇会介绍串行结构FIR的Verilog设计、使用Quartus和Vivado的IP核设计FIR的方法。

数字滤波器

数字滤波器从实现结构上划分,有FIR和IIR两种。FIR的特点是:线性相位、消耗资源多;IIR的特点是:非线性相位、消耗资源少。由于FIR系统的线性相位特点,设计中绝大多数情况都采用FIR滤波器。

线性相位系统的意义,这里的线性相位指的是在设计者关心的通带范围内,LTI系统满足线性相位要求:
1. 从延时的角度看:保证了输入信号的相位响应是线性的,即保证了输入信号的延时特性。
2. 从相位的角度看:输入的各频率成分的信号之间,相对相位是固定的。通过线性相位系统后,相对相位关系保持不变。

对于关心相位的系统,比如调制解调系统,需要使用FIR滤波器;对于只关心频率成分的系统,比如只是提取某一频率分量,为了节省资源,使用IIR滤波器即可。

FIR滤波器

FIR的最大特点就是其系统响应 h(n)是一个N点的有限长序列,FIR的输出y(n)本质上就是输入信号x(n)和h(n)的卷积(根据傅里叶变换性质,时域卷积等于频域相乘,因此卷积相当于筛选频谱中的各频率分量的增益倍数,某些频率分量保留,某些频率分量衰减,从而实现滤波效果)。FIR在实现上的本质是带抽头延迟的加法器和乘法器的组合,每一个乘法器对应一个系数。

由理论知识可知,只有当FIR的h(n)对称时,FIR滤波器才具有线性相位特性。使用MATLAB等工具设计FIR时,得到的h(n)也都是具有对称性的。

FIR滤波器的实现结构主要有直接型、级联型、频率取样型、格型四种。其中最适合FPGA实现的是直接型。“直接”是指直接由卷积公式得到:
这里写图片描述
由上图可知,n阶FIR滤波器就需要n个乘法器。如果设计的是线性相位FIR,则h(n)是对称的,利用对称性可以节省一半的乘法器。

FIR滤波器的设计方法有窗函数法、频率取样法、等波纹切比雪夫逼近法(也叫最优设计法)等等。以上所有的理论知识点在任意一本数字信号处理课本中都有详细的推论,本文节省篇幅不再赘述。

MATLAB设计

虽然Quartus和Vivado的FIR IP核中都提供了设计FIR滤波器的功能,但远没有MATLAB设计便捷和强大。设计中通常都是在MATLAB中设计好FIR的单位脉冲响应h(n),或者说滤波器系数,量化后应用到FPGA设计中。

MATLAB提供了基于窗函数设计法的fir1函数、设计任意响应滤波器的fir2函数、最优设计法的firpm函数,以及两个应用程序包“Filter Builder”和“Filter Design&Analysis”,后者通常也被称作FDATOOL。现在最受欢迎的设计方式恐怕就是使用FDATOOL工具,功能强大、界面便捷,且可以直接导出xilinx公司IP核所需的coe文件。

本系列主要是讲述FPGA设计,不详细讨论上述函数及工具的使用,具体情况可以的MATLAB的help中查询。(Ps:博主目前的几个系列都处于开篇阶段,篇幅不多,暂未成体系,目前不再开新坑,等后期应该会出一个“MATLAB数字信号处理系列”)

FPGA设计

从MATLAB到FPGA最重要的工作便是滤波器系数的量化。现在的计算机大多都是64位的,然而为了节省资源,FPGA中进行如此高位宽的运算步进浪费资源而且也没有必要。在MATLAB中将滤波器系数量化为指定位宽,会改变滤波器的频率特性,因此需要做好仿真,确定量化后的系数也能满足FIR的设计需求。

由上节可知FPGA最方便实现的是直接型结构FIR,实现时可以采用并行结构、串行结构、分布式结构,也可以直接使用Quartus和Vivado提供的FIR IP核。本篇先介绍并行FIR滤波器的Verilog设计。设计参考自杜勇老师的《数字滤波器的MATLAB与FPGA实现》。本设计将在Vivado环境下进行仿真。

使用MATLAB设计一个2kHz采样,500Hz截止的15阶低通滤波器(h(n)长度为16),量化位数为12bit,输入信号位宽也为12bit。Verilog设计代码如下。

模块接口:

module Xilinx_FIR_Guide_liuqi
(
    input rst,                    //复位信号,高电平有效
    input clk,                    //FPGA系统时钟,频率为2kHz
    input signed [11:0] Xin,      //数据输入频率为2khZ
    output signed [28:0]Yout      //滤波后的输出数据
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

输出信号的29bit位宽是全分辨率输出,没有截位。“并行”FIR指的是多个乘法器并行地进行滤波器系数与输入数据之间的乘法计算,因此代码中我们需要缓存16个数据:

reg signed[11:0] Xin_Reg[15:0];   //[11:0]指单数据12bit位宽;[15:0]指共有16个数据
reg [3:0] i,j; 
always @(posedge clk or posedge rst)
    if (rst)
        //初始化寄存器值为0
        begin 
            for (i=0; i<15; i=i+1)
                Xin_Reg[i]=12'd0;
        end
    else
        begin
            for (j=0; j<15; j=j+1)  //每个时钟移位一个数据
                Xin_Reg[j+1] <= Xin_Reg[j];
            Xin_Reg[0] <= Xin;
        end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

由FIR系数的对称性可知,16个系数只需要8个乘法器即可,因此应该将对称系数多对应的输入数据相加:

reg signed [12:0] Add_Reg[7:0];
always @(posedge clk or posedge rst)
    if (rst)
        //初始化寄存器值为0
        begin 
            for (i=0; i<8; i=i+1)
                Add_Reg[i]=13'd0;
        end
    else
        begin
            for (i=0; i<8; i=i+1)   //对称系数相加
            Add_Reg[i]={Xin_Reg[i][11],Xin_Reg[i]}+{Xin_Reg[15-i][11],Xin_Reg[15-i]};
        end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

由于加法会增加一个bit位宽,因此相加结构扩充为13bit。由于输入数据为二进制补码带符号数,因此在相加前需要先使用Verilog中的拼接运算符{}扩展符号位到最高位。接下来例化8个乘法器IP核进行乘法运算:

wire signed [11:0] coe[7:0] ;    //滤波器为12比特量化数据
    wire signed [24:0] Mout[7:0];   //乘法器输出为25比特数据
    assign coe[0]=12'h000;
    assign coe[1]=12'hffd;
    assign coe[2]=12'h00f; 
    assign coe[3]=12'h02e;  
    assign coe[4]=12'hf8b;
    assign coe[5]=12'hef9;  
    assign coe[6]=12'h24e;
    assign coe[7]=12'h7ff; 
    mult_gen_0  Umult0 (
        .CLK (clk),
        .A (coe[0]),
        .B (Add_Reg[0]),
        .P (Mout[0]));          
    mult_gen_0  Umult1 (
        .CLK (clk),
        .A (coe[1]),
        .B (Add_Reg[1]),
        .P (Mout[1]));      
    mult_gen_0  Umult2 (
        .CLK (clk),
        .A (coe[2]),
        .B (Add_Reg[2]),
        .P (Mout[2]));      
    mult_gen_0  Umult3 (
        .CLK (clk),
        .A (coe[3]),
        .B (Add_Reg[3]),
        .P (Mout[3]));      
    mult_gen_0  Umult4 (
        .CLK (clk),
        .A (coe[4]),
        .B (Add_Reg[4]),
        .P (Mout[4]));      
    mult_gen_0  Umult5 (
        .CLK (clk),
        .A (coe[5]),
        .B (Add_Reg[5]),
        .P (Mout[5]));      
    mult_gen_0  Umult6 (
        .CLK (clk),
        .A (coe[6]),
        .B (Add_Reg[6]),
        .P (Mout[6]));              
    mult_gen_0  Umult7 (
        .CLK (clk),
        .A (coe[7]),
        .B (Add_Reg[7]),
        .P (Mout[7]));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

12bit的滤波器系数与13bit的输入信号数据相乘结果为25bit。乘法结果累加即为滤波器的输出结果:

    reg signed [28:0] sum;
    reg signed [28:0] yout;
    reg [3:0] k;
    always @(posedge clk or posedge rst)
        if (rst)
            begin 
                sum = 29'd0; 
                yout <= 29'd0;
            end
        else
            begin
               yout <= sum;
                sum = 29'd0;
                for (k=0; k<8; k=k+1)
                    sum = sum+Mout[k];  //相加输出结果
            end
    assign Yout = yout;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

8个25bit的数相加,结果可能扩展到29bit,这也是全分辨率输出的结果。可以看到并行结构的FIR乘法、加法运算都是在一个时钟内完成,因此每个时钟都能获得一个输出。

仿真与工程下载

使用MATLAB生成一个200khz+800kHz的混合频率信号,写入txt文件,再生成一个噪声信号写入txt文件。编写Testbench读取txt文件对信号滤波,文件操作方法参考“Testbench编写指南(一)文件的读写操作”https://blog.csdn.net/fpgadesigner/article/details/80470972

对正弦信号的滤波如下图所示:
这里写图片描述

明显看到经过500kHz低通滤波器滤波后,输入的200+800kHz信号只剩下200kHz的频率分量。

对噪声信号的滤波如下图所示:
这里写图片描述
可以看到噪声经过滤波后的频率分布情况明显少于滤波前。完整的Vivado工程(含testbench仿真)可以在这里下载:https://download.csdn.net/download/fpgadesigner/10462288。Quartus环境下的设计与仿真工程可以参考杜勇老师《数字滤波器的MATLAB与FPGA实现》书中所带光盘里的内容。很推荐大家购买这本书学习。

        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/markdown_views-ea0013b516.css">
            </div>

转载地址:https://blog.csdn.net/fpgadesigner/article/details/80594627

版权声明:本文为alangaixiaoxiao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/alangaixiaoxiao/article/details/81607928

智能推荐

matlab与FPGA无线通信、FPGA数字信号处理系列(5)—— 在 Vivado 中 使用 Verilog 实现串行 FIR 滤波器

在 FPGA 实现 FIR 滤波器时,最常用的是直接型结构,简单方便,在实现直接型结构时,可以选择串行结构/并行结构/分布式结构。 串行结构即串行实现 FIR 滤波器的乘累加操作,数据的处理速度较慢。N 阶串行 FIR 滤波器,数据的输入速率 = 系统处理时钟速率 / 滤波器长度(N+1),本例使用 7 阶串行,系统时钟 32 MHz,这样数据的输入速率(也是采样速率)为4 MHz; (3)Mat...

数字信号处理:FIR数字滤波器设计及软件实现

数字信号处理:FIR数字滤波器设计及软件实现 一、实验目的 (1)掌握用窗函数法设计FIR数字滤波器的原理和方法。 (2)掌握用等波纹最佳逼近法设计FIR数字滤波器的原理和方法。 (3)掌握FIR滤波器的快速卷积实现原理。 (4)学会调用MATLAB函数设计与实现FIR滤波器。 二、实验内容及步骤 (1)认真复习第七章中用窗函数法和等波纹最佳逼近法设计FIR数字滤波器的原理; (2)调用信号产生函...

并行FIR滤波器Verilog设计

版权声明:本文为CSDN博主「FPGADesigner」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/fpgadesigner/article/details/80594627 感谢博主FPGADesigner,本文在原文基础上做部分修改,添加个人理解。 另外附一篇参考博客:matlab与FPGA无线通...

FPGA数字信号处理(20)单级半带(HB)滤波器设计

本篇是FPGA数字信号处理的第20篇,前面介绍了多速率信号处理系统中用到的多速率FIR滤波器、CIC滤波器,本文将介绍另一种常用的半带滤波器(Half-Band Filter)的相关知识及设计方法。本文介绍的是单级半带滤波器,下一篇将介绍多级半带滤波器。 多速率信号处理的相关知识可以参考:“FPGA数字信号处理(十五)多速率FIR滤波器:https://blog.csdn.net/FP...

FPGA数字信号处理(21)多级半带(HB)滤波器设计

本篇是FPGA数字信号处理的第21篇,上一篇介绍了半带滤波器的相关知识以及单级半带滤波器的设计方法。单级半带滤波器只能实现2倍抽取,本文将介绍可实现2^N倍抽取的多级半带滤波器的设计方法。 多级半带滤波器 多级半带滤波器是一个级联系统,设计需要考虑的最大问题就是如何分配各级的参数以实现整体的性能指标要求。这里假设抽取滤波的总体要求为:通带截止频率fp,通带波纹δp,阻带截止频率fs,阻...

猜你喜欢

[数字信号处理学习篇] FIR 滤波器基础(一)

1.[数字信号处理] FIR 滤波器基础 2.[数字信号处理]使用窗函数设计 FIR 滤波器 3.[数字信号处理]单位冲击响应的频响与 FIR 的实现代码(C 语言) 4.[数字信号处理]相位特性解卷绕 5.[数字信号处理]IIR 滤波器基础 6.[数字信号处理]IIR 滤波器的间接设计 7.[数字信号处理]IIR 滤波器的直接设计 对于一个滤波器而言,其单位冲击响应是有限区间的数列的话,这个滤波...

linux上安装Qt4.8.6+QtCreator4.0.3

一、Qt简介 Qt是1991年奇趣科技开发的一个跨平台的C++图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界面所需的所有功能。Qt很容易扩展,并且允许真正地组件编程。 准备工作 操作系统:centos6.5 位数:64位 二、安装 1、获取源码Qt4.8.6 2、获取源码QtCreator4.0.3 2、安装QtCreator4.0.3 进入QtCreator安装界面,指定...

react-native metro 分析

文章目录 前言 概念 Resolution Transformation Serialization 打包方式 Moudles Plain bundle Indexed RAM bundle File RAM bundle 流程 前置流程 resolve流程 Transformer流程 序列化流程 缓存 为什么要缓存 缓存的请求与缓存 Metro配置 结构 前言 metro是一种支持ReactNa...

嵌入式Linux——应用调试:用户态打印段错误信息

简介:     很多时候我们会遇到段错误:segmentation fault,而段错误有时是由内核引起的,有时是由应用程序引起的。在内核态时,发生段错误时会打印oops信息,但是在用户态时,发生段错误却只会打印segmentation fault而并不会打印其他的信息。所以本文主要介绍在用户态时,通过修改内核设置和添加启动参数来打印引发segmentati...

springboot1.4.1整合logback 遇到的问题

springboot1.4.1整合logback 遇到的问题 项目使用了springboot1.4.1整合logback,然而设置的过期时间15 并没有生效, 2GB达到2G自动删除也没有生效,仅仅实现了按大小分割。 经过查看pom 父工程内的源码发现是默认的logback版本是1.1.7,而过期时间配置是在logback 1.1.8以后才支持的。 不得不说这是springboot1.4.1 的b...