基於FPGA的多級CIC濾波器實現四倍插值

  • 2019 年 12 月 5 日
  • 筆記

基於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.1khz的1khz 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設計:FPGA由i2s輸入44.1khz的1khz 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)     );      //divide  assign 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--4  if(i == (LAST_CYCLE*2-1)) dout_pcm<=32'b0;      //upsample(x,n)--n--4  if(i == (LAST_CYCLE*3-1)) dout_pcm<=32'b0;      //upsample(x,n)--n--4  if(i == (LAST_CYCLE*4-1)) dout_pcm<=32'b0;      //upsample(x,n)--n--4    end  end    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    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

FPGA模擬:

模擬輸入1khz sine輸出依然為1khz sine,設計成功。

至此我們可以去完成3倍抽取5倍插值等取樣率轉化演算法。