FIR 数字滤波器 --verilog设计实现
FIR数字滤波器设计在FPGA实现FIR滤波器时最常用的是直接型结构简单方便在实现直接型结构时可以选择串行结构/并行结构/分布式结构。串行结构即串行实现FIR滤波器的乘累加操作数据的处理速度较慢。N阶串行FIR滤波器数据的输入速率系统处理时钟速率/滤波器长度N1,本例程使用7阶串行系统时钟32MHz这样的数据输入速率采样率为4MHz。串行FIR数字滤波器信号说明data_in[15:0] 输入信号为0.5MHz叠加1.8MHz信号采样时钟为4MHz系统处理时钟/滤波器阶数16bit量化h0-h8 滤波器系数8bit量化4MHz抽样低通滤波器Low Pass FilterLPF截止频率为1MHz窗函数设计。data_out[15:0]输出信号为0.5MHz信号16bit。使用MATLAB获取滤波器系数h0-h7模拟低通滤波器设计%设计巴特沃斯模拟滤波器 %通带截止频率 fp单位Hz %通带衰减 Rp(单位dB) %阻带截止频率 fs(单位Hz) %阻带衰减 Rs单位dB %技术指标要求设置按自己的需求更改即可。 fp900;fs1100; %低通滤波器理想截止频率在1000Hz左右 %fp5100;fs4800; %高通滤波器理想截止频率在5000Hz左右 %fp[1100,1900];fs[900,2100]; %带通实例理想上限截止频率2000Hz下限截止频率1000Hz %fp[900,2100];fs[1100,1900]; %带阻实例理想上限截止频率2000Hz下限截止频率1000Hz Rp1; %通带衰减1dB Rs40; %阻带衰减40dB filter_type1; %1低通2高通3带通4带阻 Wp2*pi*fp; %转换为角频率单位rad/s Ws2*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模拟滤波器的系统函数 magabs(H); %幅度 phaangle(H); %相位 db20*log10((mageps)/max(mag)); %转换为分贝 fW/(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。Verilog代码实现module fir( input wire clk, //系统时钟 32MHz input wire rst_n, //系统复位信号 input wire data_clk, //数据时钟 4MHz input signed[15:0] data_in, //输入数据16bit 0.5MHz1.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 16b0; x2 16b0; x3 16b0; x4 16b0; x5 16b0; x6 16b0; x7 16b0; 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 8h00; wire signed[7:0] h1 8hfe; wire signed[7:0] h2 8h13; wire signed[7:0] h3 8h70; wire signed[7:0] h4 8h70; wire signed[7:0] h5 8h13; wire signed[7:0] h6 8hfe; wire signed[7:0] h7 8h06; //计数器实现延时7阶滤波器8拍延时 reg [2:0] counter; always (posedge clk or negedge rst_n)begin if(~rst_n)begin counter 3b0; end else begin counter counter 1b1; 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 16b0; mult_b 8b0; end else begin case(counter) 3b000:begin mult_a data_in; mult_b h0; end 3b001:begin mult_a x1; mult_b h1; end 3b010:begin mult_a x2; mult_b h2; end 3b011:begin mult_a x3; mult_b h3; end 3b100:begin mult_a x4; mult_b h4; end 3b101:begin mult_a x5; mult_b h5; end 3b110:begin mult_a x6; mult_b h6; end 3b111: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 32b0; data_out 16b0; end else begin data_out_temp data_out_temp mult_p; if(counter 3b111)begin data_out data_out_temp[31:16]; //数据截断取前16bit data_out_temp 32b0; end end end endmodule仿真波形数据产生--由matlab产生数据16bit数据4MHz刷新%%清内存关闭窗口 准备工作 clear close all clc %%signal % f(x) A1*sin(w1*tp1) A2*sin(w2*tp2); %三要素 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*tp1); s2 A2*sin(w2*tp2); %s2 A2*sin(w2*tp); 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(幅度);testbenchmodule 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 1b0; data_clk 1b0; rst_n 1b0; #100 rst_n 1b1; 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 6b0; end always #10 begin data_in mem[addr][15:0]; addr addr 1b1; end fir uut( .clk (clk), .rst_n (rst_n), .data_clk (data_clk), .data_in (data_in), .data_out (data_out) ); endmodule