關(guān)于FIR濾波器的設(shè)計,大多數(shù)文獻和資料都偏向于理論的介紹與闡述,使讀者在學習完這類文獻后只是明白了如何解決例題與習題,真正的動手設(shè)計FIR濾波器依然會覺得抽象很陌生,本文則是在理論的基礎(chǔ)上詳細闡述了如何基于Verilog HDL搭建的數(shù)字電路,來完成來完成FIR橫向濾波器的設(shè)計。
橫向FIR濾波器的設(shè)計
設(shè)經(jīng)過AD采集得到的輸入序列為x(n),其通過單位沖激響應(yīng)為h(n)的因果FIR濾波器后,輸出y(n)在時域可表示為線性卷積和的形式:
其中N-1為FIR濾波器階數(shù)(也稱抽頭數(shù)),可以明顯的看出h(n)是長度為抽頭數(shù)加一的有限長序列,不失一般性的設(shè)抽頭數(shù)為3的FIR單位沖激響應(yīng)h(n)為,
依卷積和畫出信號流程圖如下,
我們必須明確這里的自變量n表示的并非是連續(xù)時間,而是第N次AD采樣。
首先根據(jù)流程圖所示,我們需要設(shè)計一個關(guān)于x(n)的移位電路,其RTL視圖如下,
如圖所示的x(n)的移位功能在Verilog中可以通過如下代碼實現(xiàn),注意clk是與數(shù)據(jù)同步的AD的采樣率時鐘(AD當前數(shù)據(jù)建立后,采用一個脈沖標志可實現(xiàn))。
input clk;input signed[8:0] x_in;output reg signed [8:0] xn;output reg signed [8:0] xn_1;output reg signed [8:0] xn_2;output reg signed [8:0] xn_3;always@(posedge clk) begin xn <= x_in; //x(n) xn_1 <= xn; //x(n-1) xn_2 <= xn_1; //x(n-2) xn_3 <= xn_2; //x(n-3) end
其次,為了設(shè)計方便,需要將浮點數(shù)轉(zhuǎn)換為定點運算,注意,N位的數(shù)據(jù)完成N*N乘法后,其結(jié)果的長度為2N位,為了配合乘法運算,我們需要采用18位補碼表示有符號數(shù)據(jù)(MSB為符號位),并對浮點數(shù)進行8位的量化處理(乘以256轉(zhuǎn)換為定點數(shù)運算,運算結(jié)果除以256可得到相應(yīng)的浮點數(shù)),那么上述的系統(tǒng)的沖激響應(yīng)h(n)可表示為(這里不可避免的引入了量化誤差),
對應(yīng)的18位補碼有符號十進制數(shù)為,
電路RTL視圖如下,
如圖所示的x(n)移位后對應(yīng)的乘法功能在Verilog中可以通過如下代碼實現(xiàn)。
input clk;input signed[8:0] x_in;output signed [17:0] mult0;output signed [17:0] mult1;output signed [17:0] mult2;output signed [17:0] mult3;reg signed [8:0] xn;reg signed [8:0] xn_1;reg signed [8:0] xn_2;reg signed [8:0] xn_3;always@(posedge clk) begin xn <= x_in; //x(n) xn_1 <= xn; //x(n-1) xn_2 <= xn_1; //x(n-2) xn_3 <= xn_2; //x(n-3) endassign mult0 = xn * 18'd162; //x(n) *h(0)assign mult1 = xn_1 * 18'd134; //x(n-1)*h(1)assign mult2 = xn_2 * 18'd218; //x(n-2)*h(2)assign mult3 = xn_3 * 18'd262062;//x(n-3)*h(3)
最后,采用一級加法電路完成整個求卷積和的過程,需要注意的是,有符號的加法操作,需要對符合位進行保護,完成加法后數(shù)據(jù)的長度應(yīng)設(shè)為2*N+log2(Tap+1)-1(其中Tap表示抽頭數(shù)),則本文需要的加法寄存器的長度為為19位(2*9+log(4)-1),并且取其高11位作為y(n)輸出(該操作等于除以256)其電路RTL視圖如下,
該結(jié)構(gòu)的總體Verilog代碼如下。
module fir( input clk, input signed[8:0] x_in, output signed [10:0] y_out);reg signed [8:0] xn;reg signed [8:0] xn_1;reg signed [8:0] xn_2;reg signed [8:0] xn_3;wire signed [17:0] mult0;wire signed [17:0] mult1;wire signed [17:0] mult2;wire signed [17:0] mult3;wire signed [18:0] adder0;always@(posedge clk) begin xn <= x_in; //x(n) xn_1 <= xn; //x(n-1) xn_2 <= xn_1; //x(n-2) xn_3 <= xn_2; //x(n-3) endassign mult0 = xn * 18'd162; //x(n) *h(0)assign mult1 = xn_1 * 18'd134; //x(n-1)*h(1)assign mult2 = xn_2 * 18'd218; //x(n-2)*h(2)assign mult3 = xn_3 * 18'd262062;//x(n-3)*h(3) assign adder0 = mult0 + mult1 + mult2 + mult3; //adder0(n)=x(n)*h(0)+x(n-1)*h(1)+x(n-2)*h(2)+x(n-3)*h(3)assign y_out = adder0[18:8]; //y(n)=adder0(n)/256endmodule
基于ModelSim求系統(tǒng)沖激響應(yīng)與矩形脈沖響應(yīng)
列寫testbench如下,
`timescale 1ns/1ns`define ad_clk 20module fir_tb; reg clk; reg signed[8:0] x_in; wire signed [10:0] y_out; fir fir( .clk(clk), .x_in(x_in), .y_out(y_out) ); initial clk = 1; always#(`ad_clk/2) clk = ~clk; initial begin x_in = 9'd0; #(`ad_clk*20); #3; x_in = 9'd100; #(`ad_clk); x_in = 9'd0; #(`ad_clk*20); x_in = 9'd100; #(`ad_clk); x_in = 9'd100; #(`ad_clk); x_in = 9'd100; #(`ad_clk); x_in = 9'd100; #(`ad_clk); x_in = 9'd100; #(`ad_clk); x_in = 9'd0; #(`ad_clk*20); $stop; endendmodule
仿真求得對應(yīng)的響應(yīng)為
顯然,當輸入為x(n)=100δ(n)時,輸出為y(n)=100h(n)(存在著量化誤差),輸入為x(n)=100[u(n)-u(n-5)]時,輸出y(n)=[63δ(n) 115δ(n-1) 200δ(n-2) 168δ(n-3) 168δ(n-4) 105δ(n-5) 53δ(n-6) -33δ(n-7)]。
-
FPGA
+關(guān)注
關(guān)注
1629文章
21744瀏覽量
603657 -
fir濾波器
+關(guān)注
關(guān)注
1文章
95瀏覽量
19044
原文標題:基于FPGA的橫向FIR濾波器設(shè)計詳解——Bryan
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論