目录

  • Matlab仿真IIR巴特沃斯低通滤波器并使用FPGA实现
    • (1)IIR实现原理分析
    • (2)IIR滤波器的设计
      • ①采用Matlab中的FDA设计软件进行参数设计
      • ②zero零点模块书写:
      • ③pole极点模块书写:
      • ④顶层模块书写:
      • ⑤testbench测试文件的书写:
      • ⑥Matlab生成待滤波的wave数据:
      • ⑦使用Modelsim仿真波形
Written by @hzj
//JinXing Project
#2021.10.24 V1.0
#2021.10.25 V1.1
#2021.10.27 V1.2
#2021.10.28 V1.3

Matlab仿真IIR巴特沃斯低通滤波器并使用FPGA实现

(1)IIR实现原理分析

  1. IIR滤波器:IIR滤波器的系统函数和差分方程如下所示:

H(z)=∑i=0Mbiz−i/(1−∑l=1Nalz−l)H(z)= \sum_{i=0}^Mb_iz^{-i} /(1-\sum_{l=1}^Na_lz^{-l})H(z)=∑i=0M​bi​z−i/(1−∑l=1N​al​z−l)

y(n)=∑i=0Mx(n−i)b(i)+∑l=1Ny(n−l)a(l)y(n)= \sum_{i=0}^Mx(n-i)b(i)+ \sum_{l=1}^Ny(n-l)a(l)y(n)=∑i=0M​x(n−i)b(i)+∑l=1N​y(n−l)a(l)

  1. 这里进行设计一个直接Ⅱ型的IIR滤波器 。还是以设计一个低通滤波器为目的,选择巴特沃斯滤波器为设计的主要目的。下午的为结构显示图,右边为零点部分,左边为极点部分。相对于直接Ⅰ型的滤波器,消耗的资源相对较小。根据我们上述的理论分析,其实IIR实质之上就是两个FIR进行一个叠加。零点部分的模块进行一个N位的移位,极点部分的模块进行一个N-1位的移位。
  2. 由上述的理论分析可以知道,由于IIR的模块设计,那么可以使用一个顶层设计的方案,分别设计两个子模块进行调用。最终达到滤波的效果,下面开始进行设计IIR滤波器。

(2)IIR滤波器的设计

①采用Matlab中的FDA设计软件进行参数设计

设计一个低通滤波器,滤波器的采样频率为3000Hz,截至频率Fc为1000Hz,采用的IIR设计方法为巴特沃斯滤波器(Butterworth),指定阶数为7阶。由此构建的滤波器如下图所示。

下面开始导出系数:

选择Direct-Form Ⅰ, SOS


使用Ctrl +e快捷键进行导出系数

在命令行窗口进行输出,如下所示

>> NumNum =列 1 至 60.0817953182464095         0.572567227724866           1.7177016831746          2.86283613862433          2.86283613862433           1.7177016831746列 7 至 80.572567227724866        0.0817953182464095>> DenDen =列 1 至 61          2.31746027736733          3.02835285045499          2.39176248790061          1.24027554135094         0.407050515894209列 7 至 80.0782116476869789       0.00668741488534553

进行8bit的放大,放大后的结果如下,format long g这个参数就是可是让原来科学技术法的结果不按照科学计数法显示。

因此整理之后,可以获得:

>> round(Den * 2^6)ans =64   148   194   153    79    26     5     0>> round(Num * 2^6)ans =5    37   110   183   183   110    37     5

②zero零点模块书写:

根据前面仿真得出的量化系数 5 37 110 183 183 110 37 5,可以推断出,由于系数有对称性,那么这里只需使用到8/2=4个乘法器,现将data_reg[m]与data_reg[n-m]求和之后,再进行乘积。例如(data_reg[0] + data_reg[7]) * 5 = mul_reg[0]。因此只需要再在程序中进行二级制乘法转换即可。

`timescale 1ns/1ps
//-------------------------------------------------------
//   IIR滤波器零点系数模块
//-------------------------------------------------------//-------------------------------------------------------
//   引脚模块定义
//-------------------------------------------------------
module zero_module(input clk                         , //时钟信号clkinput rst_n                       , //定义一个复位信号,复位信号按照下降沿有效input signed [11:0] zero_input    , //零点模块的输入output signed [20:0] zero_output    //零点模块的输出
);//-------------------------------------------------------
//   IIR滤波器中进行移位的部分,按照clk时钟周期,依次输入波
//   形数据,同时也应该在rst_n为1'b0的时候进行置零
//-------------------------------------------------------
reg signed [11:0] data_reg [6:0];always@(posedge clk or negedge rst_n) beginif(rst_n == 1'b0) begin     //复位信号,系统进行置零操作,复位信号低电平有效data_reg[0] <= 12'b0   ;data_reg[1] <= 12'b0   ;data_reg[2] <= 12'b0   ;data_reg[3] <= 12'b0   ;data_reg[4] <= 12'b0   ;data_reg[5] <= 12'b0   ;data_reg[6] <= 12'b0   ;endelse begin                       //普通时钟周期信号,依次进行移位操作,将新的数据进行送入data_reg[6] <= data_reg[5]  ;data_reg[5] <= data_reg[4]  ; data_reg[4] <= data_reg[3]  ;data_reg[3] <= data_reg[2]  ;data_reg[2] <= data_reg[1]  ;data_reg[1] <= data_reg[0]  ;data_reg[0] <= zero_input   ;end
end
//-------------------------------------------------------
//   IIR滤波器的零点由于系数都是对称的,因此可以通过这样子减
//   少器件,先进行加法运算
//-------------------------------------------------------
wire signed [12:0] add_reg [3:0];assign add_reg[0] = {zero_input[11], zero_input} + {data_reg[6][11], data_reg[6]}    ;
assign add_reg[1] = {data_reg[0][11], data_reg[0]} + {data_reg[5][11], data_reg[5]}  ;
assign add_reg[2] = {data_reg[1][11], data_reg[1]} + {data_reg[4][11], data_reg[4]}  ;
assign add_reg[3] = {data_reg[2][11], data_reg[2]} + {data_reg[3][11], data_reg[3]}  ;//-------------------------------------------------------
//   IIR滤波器使用已经加好的数进行卷积
//-------------------------------------------------------wire signed [20:0] mult_reg [3:0];
assign mult_reg[0] = {{{6{add_reg[0][12]}}, add_reg[0], 2'b0}  + {{8{add_reg[0][12]}}, add_reg[0]}}        ;//*5_101
assign mult_reg[1] = {{{3{add_reg[1][12]}}, add_reg[1], 5'b0} + {{6{add_reg[1][12]}}, add_reg[1], 2'b0} + {{8{add_reg[1][12]}}, add_reg[1]}}        ;//*37_100101
assign mult_reg[2] = {{{2{add_reg[2][12]}}, add_reg[2], 6'b0} + {{3{add_reg[2][12]}}, add_reg[2], 5'b0} + {{5{add_reg[2][12]}}, add_reg[2], 3'b0} + {{6{add_reg[2][12]}}, add_reg[2], 2'b0} + {{7{add_reg[2][12]}}, add_reg[2], 1'b0}}  ;//*110_1101110
assign mult_reg[3] = {{{1{add_reg[3][12]}}, add_reg[3], 7'b0} + {{3{add_reg[3][12]}}, add_reg[3], 5'b0} + {{4{add_reg[3][12]}}, add_reg[3], 4'b0} + {{6{add_reg[3][12]}}, add_reg[3], 2'b0} + {{7{add_reg[3][12]}}, add_reg[3], 1'b0} + {{8{add_reg[3][12]}}, add_reg[3]}}        ;//*183_10110111    //-------------------------------------------------------
//   卷积运算之后进行求和输出
//-------------------------------------------------------
assign zero_output = mult_reg[0] + mult_reg[1] + mult_reg[2] + mult_reg[3];endmodule

③pole极点模块书写:

与零点一样,当成一个FIR滤波器进行操作,但是由于这里的系数不再具有对称性,因此,我们使用时就不能再进行相加再乘。不能偷懒就很烦…只能依次进行移位乘法(注意一下,若是这个里面有负数,我们可以先乘这个数的绝对值,在进行取补码的操作,但是一定要保证符号位多一位,不然可能会出现问题,解决方案也很简单,扩充一个符号位就可以了)。根据前文求出来的系数: 64 148 194 153 79 26 5 0,按照原理中的要求,从第一位开始(这里要舍弃第0位),依次进行与波形数据的乘法,如果有疑问,可以再在前文看看公式。

`timescale 1ns/1ps
//-------------------------------------------------------
//   IIR滤波器极点系数模块
//-------------------------------------------------------//-------------------------------------------------------
//   引脚模块定义
//-------------------------------------------------------module pole_module(input clk                          ,//时钟信号input rst_n                        ,//复位信号,使能高电平有效input signed [11:0] pole_input     ,//输入信号output signed [25:0] pole_output     //输出信号
);//-------------------------------------------------------
//   还是pole模块由于是N-1位,因此这个地方我们只需要8-1个寄存器进行存储
//   因此该处定义的是7位的reg信号,信号的带宽与输入的带宽相同,也就是即
//   12位。复位信号清零;clk信号进行移位;
//-------------------------------------------------------reg signed [11:0] data_reg [6:0];always@(posedge clk or negedge rst_n)if(rst_n == 1'b0) begin //复位信号,系统进行置零操作,复位信号低电平有效data_reg[0] <= 12'd0         ;data_reg[1] <= 12'd0         ;data_reg[2] <= 12'd0         ;data_reg[3] <= 12'd0         ;data_reg[4] <= 12'd0         ;data_reg[5] <= 12'd0         ;data_reg[6] <= 12'd0         ;end                                                                       else begin            //普通时钟周期信号,依次进行移位操作,将新的数据进行送入data_reg[6] <= data_reg[5]   ;data_reg[5] <= data_reg[4]   ;data_reg[4] <= data_reg[3]   ;data_reg[3] <= data_reg[2]   ;data_reg[2] <= data_reg[1]   ;data_reg[1] <= data_reg[0]   ;data_reg[0] <= pole_input    ;         end//-------------------------------------------------------
//   滤波器的系数,量化之后,量化2^6
//   使用组合逻辑进行乘法的操作。
//-------------------------------------------------------
wire [25:0] mult_pole [6:0];assign mult_pole[0] = {{{7{data_reg[1][11]}}, data_reg[1], 7'b0} + {{10{data_reg[1][11]}}, data_reg[1], 4'b0} + {{12{data_reg[1][11]}}, data_reg[1], 2'b0}};//*148_10010100assign mult_pole[1] = {{{7{data_reg[2][11]}}, data_reg[2], 7'b0} + {{8{data_reg[2][11]}}, data_reg[2], 6'b0} + {{13{data_reg[2][11]}}, data_reg[2], 1'b0}};//*194_11000010assign mult_pole[2] = {{{7{data_reg[3][11]}}, data_reg[3], 7'b0} + {{10{data_reg[3][11]}}, data_reg[3], 4'b0} + {{11{data_reg[3][11]}}, data_reg[3], 3'b0} + {{14{data_reg[3][11]}}, data_reg[3]}};//*153_10011001assign mult_pole[3] = {{{8{data_reg[4][11]}}, data_reg[4], 6'b0} + {{11{data_reg[4][11]}}, data_reg[4], 3'b0} + {{12{data_reg[4][11]}}, data_reg[4], 2'b0} + {{13{data_reg[4][11]}}, data_reg[4], 1'b0} + {{14{data_reg[4][11]}}, data_reg[4]}};//*79_1001111assign mult_pole[4] = {{{10{data_reg[5][11]}}, data_reg[5], 4'b0} + {{11{data_reg[5][11]}}, data_reg[5], 3'b0} + {{13{data_reg[5][11]}}, data_reg[5], 1'b0}};//*26_11010assign mult_pole[5] = {{{12{data_reg[6][11]}}, data_reg[6], 2'b0} + {{14{data_reg[6][11]}}, data_reg[6]}};//*5_101assign mult_pole[6] = 26'b0;//-------------------------------------------------------
//   求卷积和;将前面所有的乘积进行求和,并且输出置Yout
//   将前面7个已经完成乘法的寄存器中的数据进行加法运算
//-------------------------------------------------------
assign pole_output =    {mult_pole[0] + mult_pole[1] + mult_pole[2] + mult_pole[3] + mult_pole[4] + mult_pole[5] + mult_pole[6]};endmodule

④顶层模块书写:

顶层模块的目的就是要构造成为一个IIR,前文相当于可以看成是两个FIR模块。因此,程序中调用前面的两个子模块module_zero以及module_pole。然后将零极点的输出值进行相减,除法的操作,最终输出我们滤波后的波形数据。输入波形的数据位数位12位,输出波形数据的数据位也为12位。

`timescale 1ns/1ps
//-------------------------------------------------------
//   IIR滤波器顶层模块
//-------------------------------------------------------
module IIR_top(input clk                           ,input rst_n                         ,input signed [11:0] IIR_input       ,output reg signed [11:0] IIR_output
);//-------------------------------------------------------
//   调用零点模块
//-------------------------------------------------------
wire signed [20:0] zero_out  ;
wire signed [11:0] pole_in   ;
wire signed [25:0] feedback  ;//-------------------------------------------------------
//   根据时钟信号,来控制波形的输入值wave_in;
//-------------------------------------------------------
always@(posedge clk or negedge rst_n)if(rst_n == 1'b0)beginIIR_output <= 12'b0;    //复位信号,下降沿有效endelse beginIIR_output <= pole_in;  //正常周期信号clk状态下依次进行输入波形数据endzero_module zero
(.rst_n (rst_n)             ,.clk (clk)                 ,.zero_input (IIR_input)    ,.zero_output(zero_out)
);//-------------------------------------------------------
//   调用极点模块
//-------------------------------------------------------pole_module pole
(.clk (clk)                  ,.rst_n (rst_n)              ,.pole_input (pole_in)       ,.pole_output(feedback)
);//-------------------------------------------------------
//   顶层模块进行求差值以及乘积的工作,构成IIR模块
//-------------------------------------------------------
wire signed [25:0] sub_module;
wire signed [25:0] div_module;assign sub_module = {{5{zero_out[20]}}, zero_out} - feedback ;//零点的输出与极点的输出进行相减
assign div_module = {{9{sub_module[25]}}, sub_module[25:9]}  ;//求出的差值进行移位除法assign pole_in = div_module[11:0]                            ;//输入信号的位数是12位。输出信号的位数也是12位endmodule

⑤testbench测试文件的书写:

//~ `New testbench
`timescale  1ns / 1psmodule tb_IIR_top;// IIR_top Parameters
parameter PERIOD  = 10;// IIR_top Inputs
reg   clk                             ;
reg   rst_n                           ;
reg   [11:0]  wave_in                 ;// IIR_top Outputs
wire  [11:0]  wave_out                ;
integer  i                            ;initial beginclk                  = 0          ;rst_n                = 0          ;wave_in              = 0          ;i                    = 0          ;
endinitial
beginforever #(PERIOD/2)  clk=~clk;
endinitial
begin#(PERIOD*2) rst_n  =  1;
endparameter DATA_NUM = 32'd10000;
reg [11:0]  data_men[DATA_NUM:1];initial begin$readmemb("绝对路径/tb/sin.txt",data_men);   //注意斜杠的方向,不能反<<<<<<<
endalways @(posedge clk or negedge rst_n) begin //每1个clk信号来临后,进行一次数据输入,将新的一个波形数据输入Din中。wave_in <= data_men[i];i <= i+1;
endIIR_top  u_IIR_top (.clk                     ( clk              ),.rst_n                   ( rst_n            ),.IIR_input               ( wave_in   [11:0] ),.IIR_output              ( wave_out  [11:0] )
);endmodule

⑥Matlab生成待滤波的wave数据:

所有准备工作完成之后,就应该准备输入信号,因为这里是做的一个低通滤波器,因此,我们的输入信号中,有一个较高频率的信号,一个在通带里面的信号。根据采样频率为3000Hz,那么据采样定理最多可以采到的波形频率为1500Hz,这样的话,便设置一个杂波信号的频率为1400Hz的正弦波,源信号为500Hz,Fs采样频率为3000Hz,量化位数与Verilog代码相匹配,采用的是12位的量化。生成一组十进制采样的正弦信号以及一个二进制化的正弦信号。Matlab波形生成程序的名称命名为IIR_IN_DES.m

f1 = 500;
f2 = 1400;
Fs = 3000;
N = 12;End = 100;t = 0:1/Fs:End-1/Fs;c1 = 2*pi*f1*t;
c2 = 2*pi*f2*t;s1 = sin(c1);
s2 = 0.5*sin(c2);
s = s1+s2;s = s/max(abs(s));Q_s = round(s*(2^(N-1) - 1));fid = fopen('..\tb\sin_ten.txt','w');
fprintf(fid, '%12d\r\n',Q_s);
fprintf(fid, ';');
fclose(fid);fid = fopen('..\tb\sin.txt','w');
for k=1:length(Q_s)%二进制变换
B_s=dec2bin(Q_s(k)+((Q_s(k))<0)*2^N,N);
for j=1:N
if B_s(j)=='1'
tb=1;
else
tb=0;
end
fprintf(fid,'%d',tb);
end
fprintf(fid,'\r\n');
end
fprintf(fid,';');
fclose(fid);

⑦使用Modelsim仿真波形

书写sim.do文件,如下所示,同时加入modelsim_run.bat批处理文件,进行一键执行仿真。do文件如下所示。

vlib work
vmap work workvlog -work work "../src/*.v"
vlog -work work "../tb/*.v"vsim -voptargs=+acc work.tb_IIR_top
add wave -position insertpoint  \
sim:/tb_IIR_top/*do wave.dorun 10000ns

点击批处理文件进行一键执行,仿真后的波形如下所示

FPGA学习记录(7)<巴特沃斯低通IIR滤波器FPGA实现>相关推荐

  1. matlab常见的图像增强技术(包括基于幂次变换,对图像进行均衡化处理,巴特沃斯低通,理想低通,梯形低通滤波, 均值滤波,中值滤波,最大,最小值滤波,修正后的阿尔法滤波器)

    1.基于幂次变换中的r值,比较不同r 值下图像增强的效果 代码 : I = imread('D:\图片\TH.JFIF');subplot (1,4,1);imshow(I);title('原始图像' ...

  2. MATLAB巴特沃斯低通滤波图像

    clc,clear,close all % 清理命令区.清理工作区.关闭显示图形 warning off % 消除警告 feature jit off % 加速代码运行 D0 = 20; % 阻止的频 ...

  3. c++ opencv数字图像处理:频率域滤波--低通滤波--巴特沃斯低通滤波

    文章目录 前言 一.巴特沃斯低通滤波器(BLPF) 二.代码 三.说明 前言 数字图像处理c++ opencv(VS2019 opencv4.53)持续更新 一.巴特沃斯低通滤波器(BLPF) D2( ...

  4. Matlab实现 理想低通、巴特沃斯低通、高斯低通、理想高通、巴特沃斯高通、高斯高通(d=10,50,150)

    数字图像处理第二次编程课后作业 理想低通(d=10,50,150): close all; clear all;%% ---------Ideal Lowpass Filters (Fre. Doma ...

  5. 用matlab编程实现数字图像理想低通滤波、高斯低通滤波和巴特沃斯低通滤波去噪算法

    1 理想低通滤波 %理想低通 I = imread('fig.png'); I=rgb2gray(I); figure(1); subplot(221),imshow(I); title('原图像') ...

  6. python理想低通滤波、巴特沃斯低通滤波、高斯低通滤波实现

    代码 代码如下(示例): import numpy as np import cv2 as cv image = cv.imread('2.PNG') # print(image.shape) ima ...

  7. PX4中的二阶巴特沃斯低通滤波

    源码 const float fr = sample_freq/_cuttof_freq; const float ohm = tanf(M_PI_F, fr); const float c = 1. ...

  8. 变换判断滤波器类型_7.4 低通IIR滤波器的频率变换

    本文将会介绍,怎样将一个离散型低通滤波器转换为其他的选频滤波器. 设计连续时间选频滤波器的传统方法都是首先设计一个频率归一化的原型低通滤波器,然后用一个袋鼠变换,从原型低通滤波器推出期望的滤波器. 一 ...

  9. OpenCV-巴特沃斯低通高通滤波器(C++)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 场景需求 做图像处理,滤波是家常便饭,今天给大家分享巴特沃斯滤波器实现. 众所周知,在频谱中,低 ...

  10. [就酱的新征程]数字处理仿真与应用实验二:模拟低通 Butterworth 滤波器 IIR 滤波器(Matlab)

    @数字处理仿真与应用实验二:模拟低通 Butterworth 滤波器 IIR 滤波器(Matlab) 这学期数字处理仿真与应用实验的记录 不多说,进入正题吧~ 实验要求 利用模拟滤波器原型设计 IIR ...

最新文章

  1. python安装教程mac-Mac安装python3的方法步骤
  2. 如何写好产品需求文档?
  3. 智慧环保综合解决方案
  4. 开始学习ruby,对此语言的简介
  5. 前端开发实习生第一天都在做什么?需要准备什么东西
  6. 【视频编码】【Vue】【明星开源项目】| Chat · 预告
  7. 接口授权时已经有access_token了为啥还需要refresh_token
  8. excel的一些常用技巧
  9. python 等值线图_如何用Python绘出三值等值线图?
  10. 每日一讲:C语言getchar函数的用法
  11. Java 翻转字符串 将字符串逆序
  12. error Command failed with exit code 1.
  13. 怎么在Word中制作表格?简单的Word表格制作方法分享
  14. WLAN室内、室外无线信号覆盖解决方案
  15. 【Proteus仿真】uln2003驱动二相四线制步进电机正转
  16. ACM 长方体体积求解
  17. 面对初学者的CAN总线入门教程(三)_CAN通信中帧、优先级、位填充、错误、位时序以及同步的介绍
  18. Lazarus crack,功能丰富的 Delphi 开发环境
  19. 「qqChan」qq的消息推送bot,server酱的qq版。
  20. Ardupilot源码编译(二)

热门文章

  1. java去除对象属性空格_JAVA 对象中去除空格
  2. IDEA 使用Tomcat热部署
  3. excel填充序列_EXCEL工资表制作后导入工资条方法,实现1秒搞定,万人群发
  4. 老男孩 linux 2014 360下载,360安全卫士2014旧版
  5. 勒索病毒免费解密工具都在这里!
  6. el-select 默认选中值
  7. 中间件——《中间件技术原理及应用》考试复习重点
  8. 17、【易混淆概念集】第十一章1 项目风险 风险临界值 VS 风险承受力 风险管理流程 风险管理及变更流程 规划风险管理 识别风险
  9. 华为u2000 olt 添加成功,同步网元失败 提示 服务器不可达 解决办法
  10. 使用PHP来获取客户端和服务端IP