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

串行FIR数字滤波器

  • 信号说明
    • data_in[15:0] :输入信号为0.5MHz叠加1.8MHz信号,采样时钟为4MHz(系统处理时钟/滤波器阶数)16bit量化;
    • h0-h8 :滤波器系数8bit量化,4MHz抽样,低通滤波器(Low Pass Filter,LPF),截止频率为1MHz,窗函数设计。
    • data_out[15:0]:输出信号为0.5MHz信号,16bit。

  • 使用MATLAB获取滤波器系数h0-h7
    • 模拟低通滤波器设计
%设计巴特沃斯模拟滤波器
%通带截止频率:    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=2*pi*fp;                                                                %转换为角频率,单位rad/s
Ws=2*pi*fs;
[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=20*log10((mag+eps)/max(mag));                                           %转换为分贝
f=W/(2*pi);                                                                %将模拟角频率转换为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。


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) = A1*sin(w1*t+p1) + A2*sin(w2*t+p2);
%三要素
A1 = 1;         %幅度1
A2 = 0.5;       %幅度2

f1 = 0.5;       %信号1频率为 0.5MHz
f2 = 1.8;       %信号2频率为 1.8MHz

Fs = 4;         %采样频率为 4MHz
N = 16;         %量化位数 16bit

w1 = 2*pi*f1;   %角频率1
w2 = 2*pi*f2;   %角频率2

p1 = 0;         %相位1
p2 = 0;         %相位2

%采样
T = 16;
%fs = 20*f;
d = 1/Fs;

t = -T/2:d:T/2;

s1 = A1*sin(w1*t+p1);
s2 = A2*sin(w2*t+p2);
%s2 = A2*sin(w2*t+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模块名称
end

initial begin
	clk 		= 1'b0;
	data_clk 	= 1'b0;
	rst_n 		= 1'b0;
	#100 rst_n 	= 1'b1;
end

always #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;
end

always #10 begin
	data_in  =  mem[addr][15:0];
	addr = addr + 1'b1;
end

fir uut(
	.clk			(clk),
	.rst_n			(rst_n),
	.data_clk		(data_clk),
	.data_in		(data_in),
	.data_out		(data_out)
);

endmodule

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐