- FIR 数字滤波器设计

串行FIR数字滤波器
- 信号说明
- data_in15:0 :输入信号为0.5MHz叠加1.8MHz信号,采样时钟为4MHz(系统处理时钟/滤波器阶数)16bit量化;
- h0-h8 :滤波器系数8bit量化,4MHz抽样,低通滤波器(Low Pass Filter,LPF),截止频率为1MHz,窗函数设计。
- data_out15:0:输出信号为0.5MHz信号,16bit。
- 使用**MATLAB** 获取滤波器系数h0-h7
-
模拟低通滤波器设计
%设计https://zhida.zhihu.com/search?content_id=250365265&content_type=Article&match_order=1&q=巴特沃斯模拟滤波器&zd_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ6aGlkYV9zZXJ2ZXIiLCJleHAiOjE3ODMwNjA2NTgsInEiOiLlt7TnibnmsoPmlq_mqKHmi5_mu6Tms6LlmagiLCJ6aGlkYV9zb3VyY2UiOiJlbnRpdHkiLCJjb250ZW50X2lkIjoyNTAzNjUyNjUsImNvbnRlbnRfdHlwZSI6IkFydGljbGUiLCJtYXRjaF9vcmRlciI6MSwiemRfdG9rZW4iOm51bGx9.P0xjU5sl7gYZXciqbXWEhmurQtdP-UVqKFiRPSoii0Q&zhida_source=entity
%通带截止频率: fp(单位Hz)
%通带衰减: Rp(单位dB)
%阻带截止频率: fs(单位Hz)
%阻带衰减: Rs(单位dB)%技术指标要求设置,按自己的需求更改即可。
fp=900;fs=1100; %低通滤波器,理想截止频率在1000Hz左右
%fp=5100;fs=4800; %高通滤波器,理想截止频率在5000Hz左右
%fp=[1100,1900];fs=[900,2100]; %带通实例,理想上限截止频率2000Hz,下限截止频率1000Hz
%fp=[900,2100];fs=[1100,1900]; %带阻实例,理想上限截止频率2000Hz,下限截止频率1000Hz
Rp=1; %通带衰减1dB
Rs=40; %阻带衰减40dB
filter_type=1; %1低通,2高通,3带通,4带阻
Wp=2pifp; %转换为角频率,单位rad/s
Ws=2pifs;
[N,Wc]=buttord(Wp,Ws,Rp,Rs,'s'); %计算巴特沃斯模拟滤波器参数,'s'表示WP WS都是模拟角频率;
switch filter_type
case 1
[b,a]=butter(N,Wc,'low','s'); %低通
case 2
[b,a]=butter(N,Wc,'high','s'); %高通
case 3
[b,a]=butter(N,Wc,'bandpass','s'); %带通
case 4
[b,a]=butter(N,Wc,'stop','s'); %带阻
end
[H,W]=freqs(b,a); %w:模拟角频率,H模拟滤波器的系统函数
mag=abs(H); %幅度
pha=angle(H); %相位
db=20log10((mag+eps)/max(mag)); %转换为分贝
f=W/(2pi); %将模拟角频率转换为Hz
subplot(2,1,1);plot(f,db);
title('模拟滤波器幅频曲线');xlabel('频率(Hz)');ylabel('幅度(dB)');
subplot(2,1,2);plot(f,pha);
title('模拟滤波器相频曲线');xlabel('频率(Hz)');ylabel('相位(rad)');
-

-
-
数字滤波器系数设计--利用filterDesigner工具设计数字滤波器
-
在matlab中输入 filterDesigner 打开滤波器设计工具
filterDesigner
-

- 参数配置
- 选择低通滤波器
- FIR 滤波器 -窗函数
- 指定阶 -7阶
- blackman窗函数
- 频率设定:采样率Fs = 4MHz ,滤波器截至频率Fc = 1MHz;

- 参数量化:
- 选择左下第三个框
- 选择定点数
- 选择8bit
- 点击应用

- 导出参数
- 点击File- Export
- 点击导出系数
- 在点击目标-xinlinx系数(coe文件)

- 生成的coe文件包含h0-h7 ,7阶低通滤波器系数8bit。

- Verilog代码实现

module fir(
input wire clk, //系统时钟 32MHz
input wire rst_n, //系统复位信号
input wire data_clk, //数据时钟 4MHz
input signed[15:0] data_in, //输入数据16bit, 0.5MHz+1.8MHz信号叠加
output reg signed[15:0] data_out //输出数据16bit, 0.5MHz信号
);
//移位操作,输入数据寄存
reg signed[15:0] x1;
reg signed[15:0] x2;
reg signed[15:0] x3;
reg signed[15:0] x4;
reg signed[15:0] x5;
reg signed[15:0] x6;
reg signed[15:0] x7;
always @ (posedge data_clk or negedge rst_n)begin
if(!rst_n)begin
x1 <= 16'b0;
x2 <= 16'b0;
x3 <= 16'b0;
x4 <= 16'b0;
x5 <= 16'b0;
x6 <= 16'b0;
x7 <= 16'b0;
end
else begin
x1 <= data_in;
x2 <= x1;
x3 <= x2;
x4 <= x3;
x5 <= x4;
x6 <= x5;
x7 <= x6;
end
end
//滤波器系数h[7:0] 由matlab获得
wire signed[7:0] h0 = 8'h00;
wire signed[7:0] h1 = 8'hfe;
wire signed[7:0] h2 = 8'h13;
wire signed[7:0] h3 = 8'h70;
wire signed[7:0] h4 = 8'h70;
wire signed[7:0] h5 = 8'h13;
wire signed[7:0] h6 = 8'hfe;
wire signed[7:0] h7 = 8'h06;
//计数器实现延时,7阶滤波器,8拍延时
reg [2:0] counter;
always @ (posedge clk or negedge rst_n)begin
if(~rst_n)begin
counter <= 3'b0;
end
else begin
counter <= counter + 1'b1;
end
end
//数据与滤波器系数相乘
reg signed[15:0] mult_a; //寄存的输入数据
reg signed[7:0] mult_b; //滤波器系数
wire signed[23:0] mult_p; //data_in[15:0] * h[7:0]
assign mult_p = mult_a * mult_b;
always @ (posedge clk or negedge rst_n)begin
if(~rst_n)begin
mult_a <= 16'b0;
mult_b <= 8'b0;
end
else begin
case(counter)
3'b000:begin
mult_a <= data_in;
mult_b <= h0;
end
3'b001:begin
mult_a <= x1;
mult_b <= h1;
end
3'b010:begin
mult_a <= x2;
mult_b <= h2;
end
3'b011:begin
mult_a <= x3;
mult_b <= h3;
end
3'b100:begin
mult_a <= x4;
mult_b <= h4;
end
3'b101:begin
mult_a <= x5;
mult_b <= h5;
end
3'b110:begin
mult_a <= x6;
mult_b <= h6;
end
3'b111:begin
mult_a <= x7;
mult_b <= h7;
end
endcase
end
end
//累加求和32bit
reg signed[31:0] data_out_temp;
always @ (posedge clk or negedge rst_n)begin
if(~rst_n)begin
data_out_temp <= 32'b0;
data_out <= 16'b0;
end
else begin
data_out_temp <= data_out_temp + mult_p;
if(counter == 3'b111)begin
data_out <= data_out_temp[31:16]; //数据截断,取前16bit
data_out_temp <= 32'b0;
end
end
end
endmodule
- 仿真
-
波形数据产生--由matlab产生数据16bit 数据,4MHz刷新
%%清内存,关闭窗口 准备工作
clear
close all
clc%%signal
% f(x) = A1sin(w1t+p1) + A2sin(w2t+p2);
%三要素
A1 = 1; %幅度1
A2 = 0.5; %幅度2f1 = 0.5; %信号1频率为 0.5MHz
f2 = 1.8; %信号2频率为 1.8MHzFs = 4; %采样频率为 4MHz
N = 16; %量化位数 16bitw1 = 2pif1; %角频率1
w2 = 2pif2; %角频率2p1 = 0; %相位1
p2 = 0; %相位2%采样
T = 16;
%fs = 20*f;
d = 1/Fs;t = -T/2:d:T/2;
s1 = A1sin(w1t+p1);
s2 = A2sin(w2t+p2);
%s2 = A2sin(w2t+p);
s = s1 +s2;save sinwave.txt -ascii s;
fid= fopen('data_signed.txt','w'); %保存文本文档的文件名
% fprintf(fid,'%d',data_signed);fprintf(fid,'%04x\r\n',typecast(int16(s),'uint16'));
fclose(fid);figure(1)
subplot(3,1,1);
plot(t,s1);
xlabel('时间/s');
ylabel('幅度');subplot(3,1,2);
plot(t,s2);
xlabel('时间/s');
ylabel('幅度');subplot(3,1,3);
plot(t,s);
xlabel('时间/s');
ylabel('幅度');
-

-
-
testbench
module tb_fir_filter();
reg clk;
reg rst_n;
reg data_clk;
reg signed[15:0] data_in;
wire signed[15:0] data_out;initial begin
dumpfile("wave.vcd"); //生成的vcd文件名称 dumpvars(0,tb_fir_filter ); //tb模块名称
endinitial begin
clk = 1'b0;
data_clk = 1'b0;
rst_n = 1'b0;
#100 rst_n = 1'b1;
endalways #16 clk = ~clk; //32MHz
always #128 data_clk = ~data_clk; //4MHz//将matlab生成的数据导入到寄存器中
parameter data_num = 64; //4个周期
reg [5:0] addr;
reg [15:0] mem [0:data_num-1];initial begin
# 100;
$readmemh("data_signed.txt", mem);
addr = 6'b0;
endalways #10 begin
data_in = mem[addr][15:0];
addr = addr + 1'b1;
endfir uut(
.clk (clk),
.rst_n (rst_n),
.data_clk (data_clk),
.data_in (data_in),
.data_out (data_out)
);endmodule
-
