CIC濾波器是無線通信中的常用模塊,一般用于數(shù)字下變頻(DDC)和數(shù)字上變頻(DUC)系統(tǒng)。隨著現(xiàn)代無線通信中數(shù)據(jù)速率的增加,它的應(yīng)用變得尤為重要。CIC濾波器的結(jié)構(gòu)簡單,沒有乘法器,只有加法器、積分器和寄存器,適合于工作在高采樣率條件下,而且CIC濾波器是一種基于零點(diǎn)相消的FIR濾波器,已經(jīng)被證明是在高速抽取或插值系統(tǒng)中非常有效的單元。 我們首先產(chǎn)生一個(gè)采樣率Fs=0.78125Mhz,頻率Fout=0.078125Mhz的樣本信號(hào),對其進(jìn)行16倍插值。這就涉及到直接頻率合成器DDS的知識(shí):

上圖的RAM部分存放通過MATLAB生成一個(gè)周期完整正弦波的離散點(diǎn)。Fc采樣時(shí)鐘:本模塊用一個(gè)50MHZ的采樣時(shí)鐘,即每隔20ns,從RAM中讀出一個(gè)采樣值。這里記住還有一種通過使能信號(hào)去讀取ram的值,這個(gè)時(shí)候的Fc一定不能用時(shí)鐘信號(hào)50M去算,而應(yīng)該以使能信號(hào)頻率去計(jì)算,下面會(huì)詳細(xì)體現(xiàn)。
相位累加器:顧名思義,在這里完成相位累加的功能,相位累加器的溢出頻率就是DDS輸出的信號(hào)頻率,位寬為N。
頻率控制字M:決定輸出頻率,相當(dāng)于相位累加器地址addr步進(jìn)值。
目標(biāo)頻率:Fout=Fs*M/2^N,對于這個(gè)公式我們可以這么理解,一秒內(nèi)相位累加器的累加值為Fs*M,而寄存器最大值為2^(N-1),溢出次數(shù)為Fs*M/2^N,因?yàn)榧拇嫫髦械闹祻?增加到2^(N-1),剛好輸出一個(gè)周期的正弦波信號(hào)。所以,寄存器溢出的次數(shù)就是輸出正弦波的周期數(shù)。

接下來我們來實(shí)現(xiàn)它,首先用MATLAB產(chǎn)生一個(gè)完整周期的正弦波樣本,將其存入ROM。具體實(shí)現(xiàn)方法參見這篇文章:如何用MATLAB產(chǎn)生FPGA設(shè)計(jì)中所需的coe xtmif文件
clc; clear all; N=2^8; s_p=0:255;%正弦波一個(gè)周期的采樣點(diǎn)數(shù) ROM深度256,位寬8 sin_data=sin(2*pi*s_p/N); fix_p_sin_data=fix(sin_data*127); for i=1:N if fix_p_sin_data(i)<0 fix_p_sin_data(i)=N+fix_p_sin_data(i);%有符號(hào)數(shù)--得+ else fix_p_sin_data(i)=fix_p_sin_data(i); end end fid = fopen('sin.coe','w');% 打開一個(gè).coe文件 % 存放在ROM中的.coe文件第一行必須是這個(gè)字符串,10表示10進(jìn)制,可以改成其他進(jìn)制 fprintf(fid,'memory_initialization_radix = 10; '); % 存放在ROM中的.coe文件第二行必須是這個(gè)字符串 fprintf(fid,'memory_initialization_vector = '); % 把前255個(gè)數(shù)據(jù)寫入.coe文件中,并用逗號(hào)隔開,為了方便知道數(shù)據(jù)的個(gè)數(shù),每行只寫一個(gè)數(shù)據(jù) fprintf(fid,'%d, ',fix_p_sin_data(1:end-1)); % 把最后一個(gè)數(shù)據(jù)寫入.coe文件中,并用分號(hào)結(jié)尾 fprintf(fid,'%d; ',fix_p_sin_data(end)); fclose(fid);??%?關(guān)閉文件指針


在VIVADO中調(diào)用ROM IP核,存放一個(gè)周期正弦波的信息:



這一步加載我們用MATLAB生成的coe文件,如果加載的coe文件錯(cuò)誤,箭頭指的地方會(huì)報(bào)紅。創(chuàng)建完rom后例化仿真:
module dds( input wire clk, input wire rst_n, output wire [7:0] o_wave ); reg [7:0] addr; always @(posedge clk)begin if(!rst_n) addr <= 8'd0; else addr <= addr + 1'b1; end sp_ram_256x8 sp_ram_256x8 ( .clka(clk), // input wire clka .addra(addr ), // input wire [7 : 0] addra .douta(o_wave) // output wire [7 : 0] douta );
仿真圖如下:

接下來我們首先產(chǎn)生一個(gè)采樣率Fs=0.78125Mhz,頻率Fout=0.078125Mhz的樣本信號(hào):
module gen_sin(
input wire sclk,
input wire rst_n,
output wire [7:0] data_o,
output reg data_v
);
parameter DIV_NUM=6'd63;//50M/64=0.78125M采樣率
//FC = 0.078125Mhz信號(hào)頻率
//FS = 0.78125Mhz采樣頻率
parameter FRQ_W_1M=32'd429496730;
//2^32*(0.078125)/0.78125//fc=M*fs/2^32
reg [31:0] phase_sum_1m;
wire [7:0] addr_1m;
wire [7:0] o_wave_1m;
reg [5:0] div_cnt;
reg s_flag;
//分頻產(chǎn)生0.78125M采樣率
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
div_cnt <= 'd0;
else if(div_cnt == DIV_NUM)
div_cnt <= 'd0;
else
div_cnt <= div_cnt + 1'b1;
//梳狀濾波器驅(qū)動(dòng)脈沖
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
s_flag <= 1'b0;
else if(div_cnt == 6'd0)
s_flag <= 1'b1;
else s_flag <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
data_v <= 1'b0;
else
data_v <= 1'b1;
assign data_o = o_wave_1m;//0.78125
//
//相位累加器
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
phase_sum_1m<='d0;
else if(s_flag == 1'b1)
phase_sum_1m <= phase_sum_1m + FRQ_W_1M ;
//相位
assign addr_1m=phase_sum_1m[31:24];
sp_ram_256x8 sp_ram_256x8 (
.clka(sclk), // input wire clka
.addra(addr_1m), // input wire [7 : 0] addra
.douta(o_wave_1m) // output wire [7 : 0] douta
);
endmodule
數(shù)字信號(hào)的頻譜是周期性的,且周期等于數(shù)據(jù)的采樣頻率。整數(shù)倍零值內(nèi)插當(dāng)然不能簡單地等同于提高了數(shù)據(jù)采樣頻率,在插值過程中,頻譜會(huì)以采樣頻率進(jìn)行壓縮,可能會(huì)引起頻譜混疊,通過內(nèi)插、低通濾波處理后,即可得到正確的經(jīng)高速采樣后的數(shù)字信號(hào)。如下圖所示: 
所以多速率信號(hào)處理過程的關(guān)鍵是設(shè)計(jì)滿足要求的抗混疊濾波器。即抽取或內(nèi)插處理后,在有用信號(hào)頻段內(nèi)不產(chǎn)生頻譜混疊。同時(shí)要求濾波器占用硬件資源少且運(yùn)算速度快,一般只要有效增加濾波器的階數(shù),可以設(shè)計(jì)出滿足指標(biāo)要求的各種抗混疊濾波器。CIC(積分梳狀)濾波器及半帶濾波器因?yàn)榫哂羞\(yùn)算速度快、占用資源少等特點(diǎn),在多速率信號(hào)處理中得到了廣泛的應(yīng)用。其沖激響應(yīng)為:

它的抽頭系數(shù)只有1或者0。 直接用MATLAB仿真觀察,分析一下 CIC 濾波器的頻譜特性,可得到其幅頻特性。

根據(jù)上述公式在MATLAB中編寫如下代碼觀察濾波器抑制情況:
clc; clear all; R=16; M=1; N=3; n=0500-1; w=pi*n/(length(n)); num=sin(R*M*w/2); den=sin(w/2); H=(num./den).^N; ABS_H=abs(H); mag=20*log10(ABS_H/max(ABS_H)); plot(w/pi,mag); grid on; axis([0,1,-200,0]);

由上圖可知,對帶外信號(hào)有很好的抑制效果。
在進(jìn)行Verilog實(shí)現(xiàn)時(shí),首先要把具體電路結(jié)構(gòu)映射出來,CIC濾波器具體實(shí)現(xiàn)框圖如下,系數(shù)為1:


按照上述框圖進(jìn)行編碼,對上述生成的樣本信號(hào)(采樣率Fs=0.78125Mhz,頻率Fout=0.078125Mhz的樣本信號(hào))進(jìn)行16倍插值濾波處理(FS采樣率提高,信號(hào)頻率Fout不變),涉及代碼均參考V3學(xué)社尤老師,讀者可訪問文后提供的網(wǎng)址學(xué)習(xí)參考:
module cic_interpolate(
input wire sclk,//50M
input wire rst_n,
input wire [7:0] data_in,
input wire data_v,
output wire [19:0] data_out
);
parameter W=20;
parameter DIV_NUM=6'd63;//50M/64=0.78125M
parameter DIV_NUM_I=3'd3;
//BIN + N*log2(R)=8+3*4=20;
reg [W-1:0] comb1;
reg [W-1:0] comb2;
reg [W-1:0] comb3;
reg [W-1:0] integ1;
reg [W-1:0] integ2;
reg [W-1:0] integ3;
wire [W-1:0] comb1_w;
wire [W-1:0] comb2_w;
wire [W-1:0] comb3_w;
wire [W-1:0] integ1_w;
wire [W-1:0] integ2_w;
wire [W-1:0] integ3_w;
reg [5:0] div_cnt;
reg s_flag;
reg s_flag_i;
//此計(jì)數(shù)器用于控制分頻,為梳狀濾波器和積分濾波器提供驅(qū)動(dòng)脈沖
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
div_cnt <= 'd0;
else if(div_cnt == DIV_NUM)
div_cnt <= 'd0;
else
div_cnt <= div_cnt + 1'b1;
//梳狀濾波器驅(qū)動(dòng)脈沖
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
s_flag <= 1'b0;
else if(div_cnt == 6'd0)
s_flag <= 1'b1;
else s_flag <= 1'b0;
//積分濾波器驅(qū)動(dòng)脈沖
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
s_flag_i <= 1'b0;
else if(div_cnt[1:0] == 2'd0)
s_flag_i <= 1'b1;
else s_flag_i <= 1'b0;
//梳狀濾波器的寄存器
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
comb1<='d0;
else if(data_v == 1'b1 && s_flag == 1'b1)
comb1<= {{12{data_in[7]}},data_in};
else if(data_v == 1'b0)
comb1<='d0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
comb2<='d0;
else if(data_v == 1'b1 && s_flag == 1'b1)
comb2<= comb1_w;
else if(data_v == 1'b0)
comb2<='d0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
comb3<='d0;
else if(data_v == 1'b1 && s_flag == 1'b1)
comb3<= comb2_w;
else if(data_v == 1'b0)
comb3<='d0;
//寄存器間的組合邏輯
assign comb1_w= {{12{data_in[7]}},data_in}-comb1;
assign comb2_w= comb1_w-comb2;
assign comb3_w= comb2_w-comb3;
//積分濾波器間的組合邏輯
assign integ1_w=comb3_w + integ1;
assign integ2_w=integ1_w + integ2;
assign integ3_w=integ2_w + integ3;
//插值后的結(jié)果輸出
assign data_out = integ3_w;
//積分濾波器的寄存器
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0) begin
integ1<='d0;
integ2<='d0;
integ3<='d0;
end
else if(data_v == 1'b1 && s_flag_i == 1'b1)begin
integ1<=integ1_w;
integ2<=integ2_w;
integ3<=integ3_w;
??end
endmodule
對上述模塊進(jìn)行仿真:紅框?yàn)椴逯登?,綠框?yàn)椴逯岛笮Ч?,直觀的看到輸出信號(hào)更加平滑細(xì)膩:


-
FPGA
+關(guān)注
關(guān)注
1652文章
22228瀏覽量
628477 -
濾波器
+關(guān)注
關(guān)注
162文章
8255瀏覽量
184416 -
頻率合成器
+關(guān)注
關(guān)注
5文章
305瀏覽量
33352 -
無線通信
+關(guān)注
關(guān)注
58文章
4830瀏覽量
146347 -
DDS
+關(guān)注
關(guān)注
22文章
681瀏覽量
155918
原文標(biāo)題:CIC插值濾波器與直接頻率合成器DDS的FPGA實(shí)現(xiàn)
文章出處:【微信號(hào):Hack電子,微信公眾號(hào):Hack電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評(píng)論請先 登錄
AD9164BBCZ 直接數(shù)字頻率合成器
基于DDS的頻率合成器設(shè)計(jì)介紹
什么是頻率合成器
如何采用DDS實(shí)現(xiàn)頻率合成器的設(shè)計(jì)?
DAC模擬乘法器、DDS(頻率合成器)、信號(hào)發(fā)生器
DDS直接數(shù)字頻率合成器、信號(hào)發(fā)生器、函數(shù)發(fā)生器
AD9850 DDS 頻率合成器的原理及應(yīng)用
基于FPGA的直接數(shù)字頻率合成器的設(shè)計(jì)
FPGA實(shí)現(xiàn)的直接數(shù)字頻率合成器
基于FPGA的直接數(shù)字頻率合成器的設(shè)計(jì)和實(shí)現(xiàn)
基于FPGA的直接數(shù)字頻率合成器的設(shè)計(jì)和實(shí)現(xiàn)
時(shí)鐘應(yīng)用中的直接數(shù)字頻率合成器
基于DDS驅(qū)動(dòng)PLL結(jié)構(gòu)的寬帶頻率合成器的設(shè)計(jì)與實(shí)現(xiàn)

CIC插值濾波器與直接頻率合成器DDS的FPGA實(shí)現(xiàn)
評(píng)論