前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于FPGA的多级CIC滤波器实现四倍抽取三

基于FPGA的多级CIC滤波器实现四倍抽取三

作者头像
FPGA开源工作室
修改2019-12-04 18:30:36
8600
修改2019-12-04 18:30:36
举报
文章被收录于专栏:FPGA开源工作室FPGA开源工作室

等你点关注都等的长毛了

基于FPGA的多级CIC滤波器实现四倍抽取三 原文链接:基于FPGA的多级CIC滤波器实现四倍抽取三

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

1 CIC滤波器的基本概述

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

2 matlab实现CIC滤波器的四倍抽取

设计目标:将载波频率352.8khz的1khz sine降采样率到88.2khz。

代码语言:matlab
复制
close all
clear all
clc
%set system parameter
fs = 1000;    %The frequency of the local oscillator signal
Fs = 352800;   %sampling frequency
Fs1 = 88200;
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
sc1 =sin(2*pi*fs*t);        %a sinusoidal input signal that produces a random starting phase
sc2 =sin(2*pi*Fs*t);        %a sinusoidal input signal that produces a random starting phase
sc = sc1 +sc2;
%滑动平均滤波器
b =[1,-1];%comb
a =[1,-1];%integerator
i1 =filter(1,a,sc);
i2 =filter(1,a,i1);
i3 =filter(1,a,i2);
y = downsample(i3,4);%decimate
c1=filter(b,1,y);
c2=filter(b,1,c1);
c3=filter(b,1,c2);
sf = c3./64;
f_osc =fft(sc,L);
f_osc=20*log(abs(f_osc))/log(10);        %换算成dBW单位
ft1=[0:(Fs/L):Fs/16];              %转换横坐标以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/4];              %转换横坐标以Hz为单位
f_o=f_o(1:length(ft2));
figure(1),
subplot(211),stem(t(1:512),sc(1:512));
xlabel('时间(t)','fontsize',8);
ylabel('幅度(dB)','fontsize',8);
title('sin_osc','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('sinosc');
subplot(212),plot(ft2,f_o);
xlabel('频率(Hz)','fontsize',8); ylabel('功率(dBW)','fontsize',8);
title('滤波后信号频谱图','fontsize',8);legend('sinosc');

3 FPGA实现CIC滤波器的四倍抽取

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

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

FPGA代码:

代码语言:text
复制
`timescale 1ps/1ps

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

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

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

decimate#(.DW(38))
        U_decimate(
       .mclk(mclk),
   .reset_n(reset_n),
   .din(integrator_temp),
   .dout(decimate_temp)
   );

comb#(.DW(38))
      U_comb(
     .mclk(mclk),
 .reset_n(reset_n),
 .din(decimate_temp),
 .dout(comb_temp)
     );

//divide
assign pcm_out = comb_temp[37:6];   
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 = 128;
reg [6: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 decimate#(parameter DW = 38)(
       input                mclk,
   input                reset_n,
   input  signed [DW-1:0] din,
   output signed [DW-1:0] dout
   );

localparam LAST_CYCLE = 512;
reg [8:0] i;//88.2

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)) begin
      dout_pcm<=din;      //downsmple(x,n)--n--4
end
  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 = 512;
reg [8: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,设计成功。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FPGA开源工作室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档