「学习笔记」带干货的数字滤波器设计(三)

和“无崖子”一起练“内功”

本次介绍基于FPGA的无限冲激响应滤波器IIR,理论不多介绍,说白了IIR滤波器是带反馈的FIR滤波器。

设计步骤如下:

一,利用matlab计算出滤波器系数。

1,利用有函数比如cheby1,cheby2,butter,ellip计算出滤波器系数

这里以cheby2为例:

N=7;%滤波器阶数
rp=60;%抑制dB
Wp=0.3;%归一化频率
[b,a]=cheby2(N,rp,Wp);

2,对b,a 进行16bit量化取整,

-a=2048 -8444 15752 -16938 11259 -4602 1067 -108
--b=7 -5 12 2 2 12 -5 7

3,取补码

--a=0800 DF04 3D88 BDD6 2BFB EE06 042B FF94
--b= 0007 FFFB 000C 0002 0002 000C FFFB 0007

二,FPGA实现

根据计算出的滤波器系数,对应直接型IIR滤波器原理框图如下:

上图中可以看出IIR滤波器,相当于Xn经过FIR滤波器和Yn经过FIR滤波器后相减除常系数,作为输出并反馈给Yn输入。

1,Xn经过FIR滤波器

-- Xn乘加和,与FIR相同
Library IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_arith.all;
USE IEEE.std_logic_signed.all;
Entity IIR_Xn is
port
(
Rst:in std_logic;--复位
Clk:in std_logic;--时钟
Xn_in:in std_logic_vector(11 downto 0);--信号输入
Xn_out:out std_logic_vector(30 downto 0)--滤波后信号输出

);
end IIR_Xn;
architecture behave of IIR_Xn is

-----------------------------------
--component声明

-----------------------------------

component multx0--LPM IP核乘法器(配置18个常数乘法器,会节省不少逻辑资源,但是灵活性较低)
PORT
(
dataa : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
datab : IN STD_LOGIC_VECTOR (12 DOWNTO 0);
result : OUT STD_LOGIC_VECTOR (28 DOWNTO 0)
);
end component;

-----------------------------------
--signal声明
type Xn_in_reg is array(7 downto 0)of STD_LOGIC_VECTOR (11 DOWNTO 0);--8个12bit的寄存器,输入信号先存入该寄存器阵列中相当于Z-1延迟。
type Xn_in_add_reg is array(3 downto 0)of STD_LOGIC_VECTOR (12 DOWNTO 0);--4个13bit的寄存器,对称相加后结果,先存入该寄存器阵列中。
type Xn_muADD_reg is array(3 downto 0)of STD_LOGIC_VECTOR (28 DOWNTO 0);--输入信号乘加系数后存入其中。

--定义三指针分别指向上面三个存储阵列
signal Xn_in_reg_point:Xn_in_reg;
signal
Xn_in_add_reg_point:Xn_in_add_reg;
signal
Xn_muADD_reg_point:Xn_muADD_reg;

--将滤波器系数声明成常量

constant b0:std_LOGIC_VECTOR(15 downto 0):=x'0007';
constant b1:std_LOGIC_VECTOR(15 downto 0):=x'FFFB';
constant b2:std_LOGIC_VECTOR(15 downto 0):=x'000C';
constant b3:std_LOGIC_VECTOR(15 downto 0):=x'0002';

begin
--数据装入移位寄存器,延迟
sig_in_shift:process(Clk,Rst)
begin
if Rst='0'then
for i in 0 to 7 loop
Xn_in_reg_point(i)<=(others=>'0');
end loop;
elsif rising_edge(Clk)then
for i in 0 to 6 loop--sig_in_reg_point(i+1)中是i+1,所以循环中最大为6,最后一位为传给Xn_in_reg_point(7).
Xn_in_reg_point(i+1)<=Xn_in_reg_point(i);
end loop;
Xn_in_reg_point(0)<=Xn_in;
end if;
end process;

--对称系数xn相加
Xn_in_add_reg_point(0)<=(Xn_in_reg_point(0)(11)&Xn_in_reg_point(0))+(Xn_in_reg_point(7)(11)&Xn_in_reg_point(7));
Xn_in_add_reg_point(1)<=(Xn_in_reg_point(1)(11)&Xn_in_reg_point(1))+(Xn_in_reg_point(6)(11)&Xn_in_reg_point(6));
Xn_in_add_reg_point(2)<=(Xn_in_reg_point(2)(11)&Xn_in_reg_point(2))+(Xn_in_reg_point(5)(11)&Xn_in_reg_point(5));
Xn_in_add_reg_point(3)<=(Xn_in_reg_point(3)(11)&Xn_in_reg_point(3))+(Xn_in_reg_point(4)(11)&Xn_in_reg_point(4));
--分子系数相乘
Umultx0:multx0--乘法器
port map(
dataa=>b0,
datab=>Xn_in_add_reg_point(0),
result=>Xn_muADD_reg_point(0)
);
Umultx1:multx0--乘法器
port map(
dataa=>b1,
datab=>Xn_in_add_reg_point(1),
result=>Xn_muADD_reg_point(1)
);
Umultx2:multx0--乘法器
port map(
dataa=>b2,
datab=>Xn_in_add_reg_point(2),
result=>Xn_muADD_reg_point(2)
);
Umultx3:multx0--乘法器
port map(
dataa=>b3,
datab=>Xn_in_add_reg_point(3),
result=>Xn_muADD_reg_point(3)
);
--计算传输函数中分子系数乘后累加
SUM_pro:process(Clk,Rst,Xn_muADD_reg_point)
variable SUM1:std_LOGIC_VECTOR(30 downto 0);
begin
if Rst='0'then
SUM1:=(others=>'0');
Xn_out<=(others=>'0');
elsif falling_edge(clk)then
Xn_out<=SUM1;
SUM1:=(others=>'0');
for i in 0 to 7 loop
SUM1:=SUM1+(Xn_muADD_reg_point(i)(28)&Xn_muADD_reg_point(i)(28)&Xn_muADD_reg_point(i));
end loop;
end if;
end process;
end behave;

2,Yn经过FIR 滤波器

Library IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_arith.all;
USE IEEE.std_logic_signed.all;
Entity IIR_Yn is
port
(
Rst:in std_logic;--复位
Clk:in std_logic;--时钟
Yn_in:in std_logic_vector(15 downto 0);--信号输入
Yn_out:out std_logic_vector(34 downto 0)--乘加后信号输出

);
end IIR_Yn;
architecture behave of IIR_Yn is

-----------------------------------
--component声明

-----------------------------------
component mult0--LPM IP核乘法器(配置18个常数乘法器,会节省不少逻辑资源,但是灵活性较低)
PORT
(
dataa : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
datab : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
result : OUT STD_LOGIC_VECTOR (31 DOWNTO 0)
);
end component;

-----------------------------------
--signal声明

type Yn_reg is array(6 downto 0)of STD_LOGIC_VECTOR (15 DOWNTO 0);--Y0除2048后存入其中(反馈信号)。
type Yn_mul_reg is array(6 downto 0)of STD_LOGIC_VECTOR (31 DOWNTO 0);--7个31bit的寄存器,对称信号相加后与滤波系数相乘结果存入其中。
--定义三指针分别指向上面三个存储阵列
signal Yn_reg_point:Yn_reg;
signal
Yn_mul_reg_point:Yn_mul_reg;
--将滤波器系数声明成常量
constant a0:std_LOGIC_VECTOR(15 downto 0):=x'0800';
constant a1:std_LOGIC_VECTOR(15 downto 0):=x'DF04';
constant a2:std_LOGIC_VECTOR(15 downto 0):=x'3D88';
constant a3:std_LOGIC_VECTOR(15 downto 0):=x'BDD6';
constant a4:std_LOGIC_VECTOR(15 downto 0):=x'2BFB';
constant a5:std_LOGIC_VECTOR(15 downto 0):=x'EE06';
constant a6:std_LOGIC_VECTOR(15 downto 0):=x'042B';
constant a7:std_LOGIC_VECTOR(15 downto 0):=x'FF94';

begin

--数据Yn数据装入移位寄存器
Yn_shift:process(Clk,Rst,Yn_reg_point,Yn_mul_reg_point)

begin
if Rst='0'then
for i in 0 to 6 loop
Yn_reg_point(i)<=(others=>'0');
end loop;

elsif falling_edge(Clk)then
for i in 0 to 5 loop--sig_in_reg_point(i+1)中是i+1,所以循环中最大为5,最后一位为传给Yn_reg_point((6).
Yn_reg_point(i+1)<=Yn_reg_point(i);
end loop;
Yn_reg_point(0)<=Yn_in;

end if;
end process;

--计算传输函数分母输入数据乘加,并行计算方式
--例化7个乘法器
Umult1:mult0--乘法器
port map(
dataa=>a1,
datab=>Yn_reg_point(0),
result=>Yn_mul_reg_point(0)
);
Umult2:mult0--乘法器
port map(
dataa=>a2,
datab=>Yn_reg_point(1),
result=>Yn_mul_reg_point(1)
);
Umult3:mult0--乘法器
port map(
dataa=>a3,
datab=>Yn_reg_point(2),
result=>Yn_mul_reg_point(2)
);
Umult4:mult0--乘法器
port map(
dataa=>a4,
datab=>Yn_reg_point(3),
result=>Yn_mul_reg_point(3)
);
Umult5:mult0--乘法器
port map(
dataa=>a5,
datab=>Yn_reg_point(4),
result=>Yn_mul_reg_point(4)
);
Umult6:mult0--乘法器
port map(
dataa=>a6,
datab=>Yn_reg_point(5),
result=>Yn_mul_reg_point(5)
);
Umult7:mult0--乘法器
port map(
dataa=>a7,
datab=>Yn_reg_point(6),
result=>Yn_mul_reg_point(6)
);
--乘系数后累加
Yn_out<=(Yn_mul_reg_point(0)(31)&Yn_mul_reg_point(0)(31)&Yn_mul_reg_point(0)(31)&Yn_mul_reg_point(0))+
(Yn_mul_reg_point(1)(31)&Yn_mul_reg_point(1)(31)&Yn_mul_reg_point(1)(31)&Yn_mul_reg_point(1))+
(Yn_mul_reg_point(2)(31)&Yn_mul_reg_point(2)(31)&Yn_mul_reg_point(2)(31)&Yn_mul_reg_point(2))+
(Yn_mul_reg_point(3)(31)&Yn_mul_reg_point(3)(31)&Yn_mul_reg_point(3)(31)&Yn_mul_reg_point(3))+
(Yn_mul_reg_point(4)(31)&Yn_mul_reg_point(4)(31)&Yn_mul_reg_point(4)(31)&Yn_mul_reg_point(4))+
(Yn_mul_reg_point(5)(31)&Yn_mul_reg_point(5)(31)&Yn_mul_reg_point(5)(31)&Yn_mul_reg_point(5))+
(Yn_mul_reg_point(6)(31)&Yn_mul_reg_point(6)(31)&Yn_mul_reg_point(6)(31)&Yn_mul_reg_point(6));
end behave;

3,Xn-Yn除常系a0

Library IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_arith.all;
USE IEEE.std_logic_signed.all;
Entity IIR_Xn_Yn_sub_Div is
port
(

Xn_in:in std_logic_vector(30 downto 0);--信号输入
Yn_in:in std_logic_vector(34 downto 0);--信号输入
Xn_Yn_div:out std_logic_vector(34 downto 0)--信号输出

);
end IIR_Xn_Yn_sub_Div;
architecture behave of IIR_Xn_Yn_sub_Div is
signal
Xn_Yn_sub:std_logic_vector(34 downto 0);
begin

--test_Xn_Yn_sub<=Xn_Yn_sub;
Xn_Yn_sub<=Xn_in(30)&Xn_in(30)&Xn_in(30)&Xn_in(30)&Xn_in-Yn_in;--Xn-Yn
Xn_Yn_div<=to_stdlogicvector(to_bitvector(Xn_Yn_sub) sra 11);--除2048
end behave;

4,top层

--直接I型,低通
--N=7;%滤波器阶数
--rs=60;%衰减dB
--Wp=0.3;归一化通道
--IIR切比雪夫II,7阶
--分母系数2048 -8444 15752 -16938 11259 -4602 1067 -108
--分母系数补码0800 DF04 3D88 BDD6 2BFB EE06 042B FF94
--系数bit位数=16bit
--分子系数7 -5 12 2 2 12 -5 7
--分子系数补码 0007 FFFB 000C 0002 0002 000C FFFB 0007
--传递函数2048*y(n)-8444*y(n-1)+15725*y(n-2)-16938*y(n-3)+11259*y(n-4)-4602*y(n-5)+1067*y(n-6)-108*y(n-7)
-- =7*x(n)+x(n-7))-5*(x(n-1)+x(n-6))+12*(x(n-2)+x(n-5))+2*(x(n-3)+x(n-4));

Library IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_arith.all;
USE IEEE.std_logic_signed.all;
Entity IIR_comp_top is
port
(
Rst:in std_logic;--复位
Clk:in std_logic;--时钟
sig_in:in std_logic_vector(11 downto 0);--信号输入
sig_out:out std_logic_vector(15 downto 0)--滤波后信号输出
);
end IIR_comp_top;
architecture behave of IIR_comp_top is

-----------------------------------
--component声明

-----------------------------------
component IIR_Xn--例化 IIR_Xn
port
(
Rst:in std_logic;--复位
Clk:in std_logic;--时钟
Xn_in:in std_logic_vector(11 downto 0);--信号输入
Xn_out:out std_logic_vector(30 downto 0)--滤波后信号输出
);
end component;

component IIR_Yn--例化 IIR_Yn
port
(
Rst:in std_logic;--复位
Clk:in std_logic;--时钟
Yn_in:in std_logic_vector(15 downto 0);--信号输入
Yn_out:out std_logic_vector(34 downto 0)--滤波后信号输出
);
end component;

component IIR_Xn_Yn_sub_Div----例化Xn-Yn除2048
port
(

Xn_in:in std_logic_vector(30 downto 0);--信号输入
Yn_in:in std_logic_vector(34 downto 0);--信号输入
Xn_Yn_div:out std_logic_vector(34 downto 0)--信号输入

);
end component;

-----------------------------------
--signal声明

signal Xn_out:std_LOGIC_VECTOR(30 downto 0);
signal Yn_out:std_LOGIC_VECTOR(34 downto 0);
signal
Xn_Yn_div:std_LOGIC_VECTOR(34 downto 0);

begin
sig_out<=Xn_Yn_div(15 downto 0);

Xn_sum:IIR_Xn--Xn端口映射
port map(
Rst=>Rst,--复位
Clk=>Clk,--时钟
Xn_in=>sig_in,--信号输入
Xn_out=>Xn_out--滤波后信号输出
);

Yn_sum:IIR_Yn--Yn端口映射
port map(
Rst=>Rst,--复位
Clk=>Clk,--时钟
Yn_in=>Xn_Yn_div(15 downto 0),--信号输入
Yn_out=>Yn_out--滤波后信号输出
);

Xn_Yn_sub:IIR_Xn_Yn_sub_Div--IIR_Xn_Yn_sub_Div端口映射

port map(
Xn_in=>Xn_out,--信号输入
Yn_in=>Yn_out,--信号输入
Xn_Yn_div=>Xn_Yn_div--信号输出
);

top层原理图

输出结果见上一篇《数字滤波器(三)》

参考:杜勇老师《数字滤波器的matlab与FPGA实现》

(0)

相关推荐

  • System Generator从入门到放弃(五)-Black Box调用HDL代码

    System Generator从入门到放弃(五)-Black Box调用HDL代码 文章目录 System Generator从入门到放弃(五)-Black Box调用HDL代码 一.Black B ...

  • 「学习笔记」从零自学DMIS三坐标测量系统_元素的构造

    原创公差帮APP2021-03-11 07:30:00 构造 该功能是用来构造那些不能直接在工件上测量的元素特征,比如孔的中心或两个元素的相交.因为构造的元素不能被探测,所以不能作为自动识别的元素,构 ...

  • 「学习笔记」从零自学DMIS三坐标测量系统_元素的定义及测量

    「学习笔记」从零自学DMIS三坐标测量系统_元素的定义及测量 原创公差帮APP2021-03-04 14:25:28 元素特征是一个测量程序中的最基本单元.通过对这些元素特征的定义及测量,在测量程序中 ...

  • 「学习笔记」从零自学DMIS三坐标测量系统:测头的选择

    原创公差帮APP2021-02-23 07:30:00 测针种类 1. 星形测针 用于测量各种不同的形体结构.这些测针的使用因为可进行多测尖检测,大大减少了将测头移动到工件的内部测量位置如孔的侧面和底 ...

  • 「学习笔记」从零自学DMIS三坐标测量系统(第一期)

    「学习笔记」从零自学DMIS三坐标测量系统(第一期) 原创公差帮APP2021-01-28 17:43:41 三坐标的测量是现在图纸检测的主要手段,是质量管控的直接途径,且与设计和工艺过程息息相关,本 ...

  • 「学习笔记」《证据新规》中的电子数据证据解读(下)

    本期我们将对电子证据的审查要素及当事人的应对建议进行探讨. 四 电子证据审查要素 01 常见的几种电子证据形式 下文中,笔者将结合几种常见的电子证据形式,对于举证.质证及具体审查的主要要素进行讨论. ...

  • 「学习笔记」HTML基础

    前言 勤做笔记不仅可以让自己学的扎实,更重要的是可以让自己少走弯路.有人说:"再次翻开笔记是什么感觉",我的回答是:"初恋般的感觉".或许笔记不一定十全十美,但 ...

  • 「学习笔记」JavaScript基础

    前言 最近一直在跟着黑马教程学习JavaScript内容,遂把这一阶段的学习内容整理成笔记,巩固所学知识,同时也会参考一些博客,书籍上的内容,查漏补缺,给自己充充电

  • 「学习笔记」CSS基础

    前言 拖延了一周的CSS学习笔记终于利用周末去补齐了,本篇文章着重梳理之前所学的CSS知识点,查漏补缺.同时,试着用git将重点案例存放到远程仓库中,更近一步贴近公司流程.

  • 色采&手帐 | 手把手带你制作超高效率的「子弹笔记」

    你是不是经常有这样的困惑 同样是一天24个小时 当你忙得一个头两个大时 为什么别人总是能有空闲的时间? 当你面对同样的任务焦虑时 为什么别人能轻松完美地完成所有工作? 当你结束工作无所事事时 为什么别 ...