跳转到主要内容

基于FPGA的多级CIC滤波器实现四倍插值

demi 提交于

<font color="#F30">作者:OpenSLee</font>

在《基于FPGA的多级CIC滤波器实现四倍抽取一》和《基于FPGA的多级CIC滤波器实现四倍抽取二》中我们先来了解滑动平均滤波器、微分器、积分器以及梳状滤波器原理以及它们的幅频响应。此篇我们将用verilog实现基于FPGA的多级CIC滤波器实现四倍插值。

<font style="line-height: 40px;" color="red"><strong>1 CIC滤波器的基本概述</strong></font>

CIC(积分梳状)滤波器是无线通信中的常用模块,一般用于数字下变频(DDC)和数字上变频(DUC)系统。CIC滤波器结构简单,只有加法器、积分器和寄存器,适合于工作在搞采样率条件下,而且CIC滤波器是一种基于零点相消的FIR滤波器,已经被证明是在高速抽取或插值系统中非常有效的单元。

整数倍内插是先在已知抽样序列的相邻两个抽样点之间等间隔地插入(I-1)个零值点,然后进行低通滤波器,即可求得I倍内插的结果。

此篇我们采用多级CIC滤波器实现整数倍内插提升采样率。

<font style="line-height: 40px;" color="red"><strong>2 matlab实现CIC滤波器的四倍插值</strong></font>

设计目标:将载波频率44.1khz的1khz sine升采样率到176.4khz。

<pre>close all
clear all
clc

%set system parameter
fs = 1000; %The frequency of the local oscillator signal
Fs = 44100; %sampling frequency
Fs1 = 176400;
N = 24; %Quantitative bits
L = 81920;

%Generating an input signal
t =0:1/Fs:(1/Fs)*(L-1); %Generating the time series of sampling frequencies
sc =sin(2*pi*fs*t); %a sinusoidal input signal that produces a random starting phase

b =[1,-1];%comb
a =[1,-1];%integerator

%comb
c1=filter(b,1,sc);
c2=filter(b,1,c1);
c3=filter(b,1,c2);

y = upsample(c3,4);

%integerater
i1 =filter(1,a,y);
i2 =filter(1,a,i1);
i3 =filter(1,a,i2);
sf = i3./16;

f_osc =fft(sc,L);
f_osc=20*log(abs(f_osc))/log(10); %换算成dBW单位
ft1=[0:(Fs/L):Fs/2]; %转换横坐标以Hz为单位
f_osc=f_osc(1:length(ft1));

f_o =fft(sf,L);
f_o=20*log(abs(f_o))/log(10); %换算成dBW单位
ft2=[0:(Fs1/L):Fs1/8]; %转换横坐标以Hz为单位
f_o=f_o(1:length(ft2));

figure(1),
subplot(211),stem(t(1:32),sc(1:32));
xlabel('时间(t)','fontsize',8);
ylabel('幅度(dB)','fontsize',8);
title('sc','fontsize',8);
subplot(212),stem(t(1:128),sf(1:128));
xlabel('时间(t)','fontsize',8);
ylabel('幅度(dB)','fontsize',8);
title('sf','fontsize',8);

figure(2),
subplot(211),plot(ft1,f_osc);
xlabel('频率(Hz)','fontsize',8); ylabel('功率(dBW)','fontsize',8);
title('原始信号信号频谱图','fontsize',8);legend('sc');
subplot(212),plot(ft2,f_o);
xlabel('频率(Hz)','fontsize',8); ylabel('功率(dBW)','fontsize',8);
title('滤波后信号频谱图','fontsize',8);legend('sf');</pre>

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-11/wen_zhang_/100046232-85277-1.pn…; alt=""></center>
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-11/wen_zhang_/100046232-85278-2.pn…; alt=""></center><br>

<font style="line-height: 40px;" color="red"><strong>3 FPGA实现CIC滤波器的四倍插值</strong></font>

FPGA设计:FPGA由i2s输入44.1khz的1khz sine(当然也可以是歌曲44.1khz采样率),经过i2s串转并后经过mult_cic模块进行采样率提升处理(变成176.4khz 1khz sine或者歌曲),再通过i2s_tx_master并转串送到DAC 。

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-11/wen_zhang_/100046232-85279-3.pn…; alt=""></center><br>

多级CIC滤波器的结构主要由梳状滤波器+插值+积分器构成。

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-11/wen_zhang_/100046232-85280-4.pn…; alt=""></center><br>

FPGA代码:
<pre>`timescale 1ps/1ps

module mult_cic#(parameter DW = 38)(
input mclk,//45.1584MHZ
input reset_n,
input signed[31:0] pcm_in,//44.1khz
output signed[31:0] pcm_out //176.4khz
);

wire signed [DW-1:0] temp;
wire signed [DW-1:0]integrator_temp;
wire signed [DW-1:0] interpolation_temp;
wire signed [DW-1:0] comb_temp;

assign temp = {{(DW-32){pcm_in[31]}},pcm_in};

comb#(.DW(DW))
U_comb(
.mclk(mclk),
.reset_n(reset_n),
.din(temp),
.dout(comb_temp)
);
interpolation#(.DW(DW))
U_interpolation(
.mclk(mclk),
.reset_n(reset_n),
.din(comb_temp),
.dout(interpolation_temp)
);

integrator#(.DW(DW))
U_integrator(
.mclk(mclk),
.reset_n(reset_n),
.din(interpolation_temp),
.dout(integrator_temp)
);

//divide
assign pcm_out = integrator_temp[35:4];
endmodule</pre>

<pre>module integrator#(parameter DW = 38)(
input mclk,
input reset_n,
input signed [DW-1:0] din,
output signed [DW-1:0] dout
);

localparam LAST_CYCLE = 256;
reg [7:0] i;

reg signed [DW-1:0] temp_xin1,temp_xin2,temp_xin3;
wire signed [DW-1:0] i1_temp,i2_temp,i3_temp;

always @(posedge mclk or negedge reset_n) begin
if(reset_n == 1'b0)
i &lt;= 0;
else
i &lt; = i+1;
end

always @(posedge mclk or negedge reset_n) begin //The first level integrator
if(reset_n == 1'b0)
temp_xin1 &lt;= 0;
else if(i == (LAST_CYCLE-1))
temp_xin1 &lt;= i1_temp;
end

assign i1_temp = (reset_n == 1'b0)?38'b0:( din + temp_xin1);

always @(posedge mclk or negedge reset_n) begin //The second level integrator
if(reset_n == 1'b0)
temp_xin2 &lt;= 0;
else if(i == (LAST_CYCLE-1))
temp_xin2 &lt;= i2_temp;
end

assign i2_temp = (reset_n == 1'b0)?38'b0:( i1_temp + temp_xin2);

always @(posedge mclk or negedge reset_n) begin //The third level integrator
if(reset_n == 1'b0)
temp_xin3 &lt;= 0;
else if(i == (LAST_CYCLE-1))
temp_xin3 &lt;= i3_temp;
end

assign i3_temp = (reset_n == 1'b0)?38'b0:( i2_temp + temp_xin3);

assign dout = i3_temp;

endmodule</pre>

<pre>module interpolation#(parameter DW = 38)(
input mclk,
input reset_n,
input signed [DW-1:0] din,
output signed [DW-1:0] dout
);

localparam LAST_CYCLE = 256;
reg [9:0] i;

reg signed [DW-1:0] dout_pcm;

assign dout = dout_pcm;

always @(posedge mclk or negedge reset_n) begin
if(reset_n == 1'b0) begin
i &lt;= 0;
dout_pcm&lt;=0;
end
else begin
i &lt;= i+1;
if(i == (LAST_CYCLE-1)) dout_pcm&lt;=din; //upsample(x,n)--n--4
if(i == (LAST_CYCLE*2-1)) dout_pcm&lt;=32'b0; //upsample(x,n)--n--4
if(i == (LAST_CYCLE*3-1)) dout_pcm&lt;=32'b0; //upsample(x,n)--n--4
if(i == (LAST_CYCLE*4-1)) dout_pcm&lt;=32'b0; //upsample(x,n)--n--4
end
end

endmodule</pre>

<pre>module comb#(parameter DW = 38)(
input mclk,
input reset_n,
input signed [DW-1:0] din,
output signed [DW-1:0] dout
);

localparam LAST_CYCLE = 1024;
reg [9:0] i;//88.2

reg signed [DW-1:0] d1,d2,d3,d4;
wire signed [DW-1:0] c1,c2;

always @(posedge mclk or negedge reset_n) begin
if(reset_n == 1'b0) begin
i &lt;= 0;
d1 &lt;=0;
d2 &lt;=0;
d3 &lt;=0;
d4 &lt;=0;
end
else begin
i &lt;= i+1;
if(i == (LAST_CYCLE-1)) begin
d1&lt;=din;
d2&lt;=d1;
d3&lt;=c1;
d4&lt;=c2;
end
end
end

assign c1 = (reset_n ==1'b0)?38'b0:(d1-d2);//comb1
assign c2 = (reset_n ==1'b0)?38'b0:(c1-d3);//comb2
assign dout =(reset_n ==1'b0)?38'b0:(c2-d4);//comb3

endmodule</pre>

<strong>FPGA仿真:</strong>

仿真输入1khz sine输出依然为1khz sine,设计成功。

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-11/wen_zhang_/100046232-85281-5.pn…; alt=""></center>
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-11/wen_zhang_/100046232-85282-6.pn…; alt=""></center><br>

至此我们可以去完成3倍抽取5倍插值等采样率转化算法。

文章转载自: <a href="https://mp.weixin.qq.com/s/_i4wMKIQ2GSm_WUXubEhSQ">FPGA开源工作室</a&gt;(leezym0317)
*本文由作者授权转发,如需转载请联系作者本人