串行 FIR 濾波器設(shè)計(jì)
◆設(shè)計(jì)說(shuō)明
設(shè)計(jì)參數(shù)不變,與并行 FIR 濾波器參數(shù)一致。即,輸入頻率為 7.5 MHz 和 250 KHz 的正弦波混合信號(hào),經(jīng)過(guò) FIR 濾波器后,高頻信號(hào) 7.5MHz 被濾除,只保留 250KMHz 的信號(hào)。
輸入頻率: 7.5MHz 和 250KHz
采樣頻率: 50MHz
阻帶: 1MHz-6MHz
階數(shù): 15 (N=15)
串行設(shè)計(jì),就是在 16 個(gè)時(shí)鐘周期內(nèi)對(duì) 16 個(gè)延時(shí)數(shù)據(jù)分時(shí)依次進(jìn)行乘法、加法運(yùn)算,然后在時(shí)鐘驅(qū)動(dòng)下輸出濾波值。考慮到 FIR 濾波器系數(shù)的對(duì)稱性,計(jì)算一個(gè)濾波輸出值的周期可以減少到 8 個(gè)。串行設(shè)計(jì)時(shí)每個(gè)周期只進(jìn)行一次乘法運(yùn)算,所以設(shè)計(jì)中只需一個(gè)乘法器即可。此時(shí)數(shù)據(jù)需要每 8 個(gè)時(shí)鐘周期有效輸入一次,但是為了保證輸出信號(hào)頻率的正確性,工作時(shí)鐘需要為采樣頻率的 8 倍,即 400MHz。這種方法的優(yōu)點(diǎn)是資源耗費(fèi)少,但是工作頻率要求高,數(shù)據(jù)不能持續(xù)輸出。
◆串行設(shè)計(jì)
設(shè)計(jì)中使用到的乘法器模塊代碼,可參考之前流水線式設(shè)計(jì)的乘法器。
為方便快速仿真,也可以直接使用乘號(hào) “*” 完成乘法運(yùn)算,設(shè)計(jì)中加入宏定義 SAFE_DESIGN 來(lái)選擇使用哪種乘法器。
FIR 濾波器系數(shù)可由 matlab 生成,具體見(jiàn)附錄。
/**********************************************************
>> Description : fir study with serial tech
>> V190403 : Fs:50Mhz, fstop:1-6Mhz, order:16, sys clk:400MHz
***********************************************************/
`define SAFE_DESIGN
module fir_serial_low(
input rstn,
input clk, // 系統(tǒng)工作時(shí)鐘,400MHz
input en , // 輸入數(shù)據(jù)有效信號(hào)
input [11:0] xin, // 輸入混合頻率的信號(hào)數(shù)據(jù)
output valid, // 輸出數(shù)據(jù)有效信號(hào)
output [28:0] yout // 輸出數(shù)據(jù)
);
//delay of input data enable
reg [11:0] en_r ;
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
en_r[11:0] <= 'b0 ;
end
else begin
en_r[11:0] <= {en_r[10:0], en} ;
end
end
//fir coeficient
wire [11:0] coe[7:0] ;
assign coe[0] = 12'd11 ;
assign coe[1] = 12'd31 ;
assign coe[2] = 12'd63 ;
assign coe[3] = 12'd104 ;
assign coe[4] = 12'd152 ;
assign coe[5] = 12'd198 ;
assign coe[6] = 12'd235 ;
assign coe[7] = 12'd255 ;
//(1) 輸入數(shù)據(jù)移位部分
reg [2:0] cnt ;
integer i, j ;
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
cnt <= 3'b0 ;
end
else if (en || cnt != 0) begin
cnt <= cnt + 1'b1 ; //8個(gè)周期計(jì)數(shù)
end
end
reg [11:0] xin_reg[15:0];
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
for (i=0; i16; i=i+1) begin
xin_reg[i] <= 12'b0;
end
end
else if (cnt == 3'd0 && en) begin //每8個(gè)周期讀入一次有效數(shù)據(jù)
xin_reg[0] <= xin ;
for (j=0; j15; j=j+1) begin
xin_reg[j+1] <= xin_reg[j] ; // 數(shù)據(jù)移位
end
end
end
//(2) 系數(shù)對(duì)稱,16個(gè)移位寄存器數(shù)據(jù)進(jìn)行首位相加
reg [11:0] add_a, add_b ;
reg [11:0] coe_s ;
wire [12:0] add_s ;
wire [2:0] xin_index = cnt>=1