当前位置:首页 > > FPGA开源工作室

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

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

1 CIC滤波器的基本概述

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

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

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

2 matlab实现CIC滤波器的四倍插值

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

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');

 

 

3 FPGA实现CIC滤波器的四倍插值

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

 

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

 

 

FPGA代码:

`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)   );    //divideassign pcm_out = integrator_temp[35:4];   endmodule


 

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 <= 0;  else    i<= i+1;end always @(posedge mclk or negedge reset_n) begin //The first level integrator  if(reset_n == 1'b0)    temp_xin1 <= 0;  else if(i == (LAST_CYCLE-1))    temp_xin1 <= 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 <= 0;  else if(i == (LAST_CYCLE-1))    temp_xin2 <= 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 <= 0;  else if(i == (LAST_CYCLE-1))    temp_xin3 <= i3_temp;end assign i3_temp = (reset_n == 1'b0)?38'b0:( i2_temp + temp_xin3); assign dout = i3_temp;    endmodule


 

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 <= 0;dout_pcm<=0;  end  else begin    i<= i+1;if(i == (LAST_CYCLE-1)) dout_pcm<=din;      //upsample(x,n)--n--4if(i == (LAST_CYCLE*2-1)) dout_pcm<=32'b0;      //upsample(x,n)--n--4if(i == (LAST_CYCLE*3-1)) dout_pcm<=32'b0;      //upsample(x,n)--n--4if(i == (LAST_CYCLE*4-1)) dout_pcm<=32'b0;      //upsample(x,n)--n--4  endend endmodule


 

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 <= 0;d1 <=0;d2 <=0;d3 <=0;d4 <=0;  end  else begin    i<= i+1;if(i == (LAST_CYCLE-1)) begin      d1<=din;  d2<=d1;  d3<=c1;  d4<=c2;end  endend assign c1 = (reset_n ==1'b0)?38'b0:(d1-d2);//comb1assign c2 = (reset_n ==1'b0)?38'b0:(c1-d3);//comb2assign dout =(reset_n ==1'b0)?38'b0:(c2-d4);//comb3 endmodule

FPGA仿真:

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

 

 

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


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
关闭