0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

CIC插值滤波器与直接频率合成器DDS的FPGA实现

Hack电子 来源:FPGA学习之旅 2023-04-12 10:26 次阅读

CIC滤波器无线通信中的常用模块,一般用于数字下变频(DDC)和数字上变频(DUC)系统。随着现代无线通信中数据速率的增加,它的应用变得尤为重要。CIC滤波器的结构简单,没有乘法器,只有加法器、积分器和寄存器,适合于工作在高采样率条件下,而且CIC滤波器是一种基于零点相消的FIR滤波器,已经被证明是在高速抽取或插值系统中非常有效的单元。 我们首先产生一个采样率Fs=0.78125Mhz,频率Fout=0.078125Mhz的样本信号,对其进行16倍插值。这就涉及到直接频率合成器DDS的知识:

69849da6-d8d8-11ed-bfe3-dac502259ad0.png

上图的RAM部分存放通过MATLAB生成一个周期完整正弦波的离散点。Fc采样时钟:本模块用一个50MHZ的采样时钟,即每隔20ns,从RAM中读出一个采样值。这里记住还有一种通过使能信号去读取ram的值,这个时候的Fc一定不能用时钟信号50M去算,而应该以使能信号频率去计算,下面会详细体现。

相位累加器:顾名思义,在这里完成相位累加的功能,相位累加器的溢出频率就是DDS输出的信号频率,位宽为N。


频率控制字M:决定输出频率,相当于相位累加器地址addr步进值。


目标频率:Fout=Fs*M/2^N,对于这个公式我们可以这么理解,一秒内相位累加器的累加值为Fs*M,而寄存器最大值为2^(N-1),溢出次数为Fs*M/2^N,因为寄存器中的值从0增加到2^(N-1),刚好输出一个周期的正弦波信号。所以,寄存器溢出的次数就是输出正弦波的周期数。


69add0e0-d8d8-11ed-bfe3-dac502259ad0.gif

接下来我们来实现它,首先用MATLAB产生一个完整周期的正弦波样本,将其存入ROM。具体实现方法参见这篇文章:如何用MATLAB产生FPGA设计中所需的coe xtmif文件

clc;
clear all;
N=2^8;
s_p=0:255;%正弦波一个周期的采样点数 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);%有符号数--得+
else
        fix_p_sin_data(i)=fix_p_sin_data(i);
end
end
fid = fopen('sin.coe','w');% 打开一个.coe文件
% 存放在ROM中的.coe文件第一行必须是这个字符串,10表示10进制,可以改成其他进制
fprintf(fid,'memory_initialization_radix = 10;
');
% 存放在ROM中的.coe文件第二行必须是这个字符串
fprintf(fid,'memory_initialization_vector = 
');
% 把前255个数据写入.coe文件中,并用逗号隔开,为了方便知道数据的个数,每行只写一个数据
fprintf(fid,'%d,
',fix_p_sin_data(1:end-1));
% 把最后一个数据写入.coe文件中,并用分号结尾
fprintf(fid,'%d;
',fix_p_sin_data(end)); 
fclose(fid);  % 关闭文件指针

6a6093ce-d8d8-11ed-bfe3-dac502259ad0.png

6a7e7858-d8d8-11ed-bfe3-dac502259ad0.png

在VIVADO中调用ROM IP核,存放一个周期正弦波的信息

6a9bf3f6-d8d8-11ed-bfe3-dac502259ad0.png

6acb5cea-d8d8-11ed-bfe3-dac502259ad0.png

6aef11c6-d8d8-11ed-bfe3-dac502259ad0.png

这一步加载我们用MATLAB生成的coe文件,如果加载的coe文件错误,箭头指的地方会报红。创建完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
);

仿真图如下:

6b1596ac-d8d8-11ed-bfe3-dac502259ad0.png

接下来我们首先产生一个采样率Fs=0.78125Mhz,频率Fout=0.078125Mhz的样本信号:

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信号频率
//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;


//分频产生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;
//梳状滤波器驱动脉冲                                                 
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
数字信号的频谱是周期性的,且周期等于数据的采样频率。整数倍零值内插当然不能简单地等同于提高了数据采样频率,在插值过程中,频谱会以采样频率进行压缩,可能会引起频谱混叠,通过内插、低通滤波处理后,即可得到正确的经高速采样后的数字信号。如下图所示: 6b2f2eaa-d8d8-11ed-bfe3-dac502259ad0.png

所以多速率信号处理过程的关键是设计满足要求的抗混叠滤波器。即抽取或内插处理后,在有用信号频段内不产生频谱混叠。同时要求滤波器占用硬件资源少且运算速度快,一般只要有效增加滤波器的阶数,可以设计出满足指标要求的各种抗混叠滤波器。CIC(积分梳状)滤波器及半带滤波器因为具有运算速度快、占用资源少等特点,在多速率信号处理中得到了广泛的应用。其冲激响应为:

6b4ee650-d8d8-11ed-bfe3-dac502259ad0.png

它的抽头系数只有1或者0。 直接用MATLAB仿真观察,分析一下 CIC 滤波器的频谱特性,可得到其幅频特性。

6b67364c-d8d8-11ed-bfe3-dac502259ad0.png

根据上述公式在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]);

6b93e35e-d8d8-11ed-bfe3-dac502259ad0.png

由上图可知,对带外信号有很好的抑制效果。

在进行Verilog实现时,首先要把具体电路结构映射出来,CIC滤波器具体实现框图如下,系数为1:

6bae50ea-d8d8-11ed-bfe3-dac502259ad0.png

6bd28096-d8d8-11ed-bfe3-dac502259ad0.png

按照上述框图进行编码,对上述生成的样本信号(采样率Fs=0.78125Mhz,频率Fout=0.078125Mhz的样本信号)进行16倍插值滤波处理(FS采样率提高,信号频率Fout不变),涉及代码均参考V3学社尤老师,读者可访问文后提供的网址学习参考:

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;


//此计数器用于控制分频,为梳状滤波器和积分滤波器提供驱动脉冲
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;
//梳状滤波器驱动脉冲                                                 
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)
    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;
//插值后的结果输出
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

对上述模块进行仿真:红框为插值前,绿框为插值后效果,直观的看到输出信号更加平滑细腻:

6bf12fa0-d8d8-11ed-bfe3-dac502259ad0.png

6c099522-d8d8-11ed-bfe3-dac502259ad0.png

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1603

    文章

    21328

    浏览量

    593275
  • 滤波器
    +关注

    关注

    158

    文章

    7334

    浏览量

    174828
  • 频率合成器
    +关注

    关注

    5

    文章

    199

    浏览量

    32156
  • 无线通信
    +关注

    关注

    56

    文章

    4202

    浏览量

    142353
  • DDS
    DDS
    +关注

    关注

    21

    文章

    614

    浏览量

    151736

原文标题:CIC插值滤波器与直接频率合成器DDS的FPGA实现

文章出处:【微信号:Hack电子,微信公众号:Hack电子】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    多环锁相频率合成器的设计

    本文设计了一种多环锁相频率合成器。多环锁相环路有直接数字频率合成(DDS)环路和锁相
    发表于 05-13 09:09

    AD9164BBCZ 直接数字频率合成器

    AD9164BBCZ 16位、12 GSPS、RF DAC和直接数字频率合成器订货***黄小姐微信同号 AD9164是一款高性能16位数模转换(DAC)和
    发表于 07-29 12:11

    基于ADF4156频率合成器芯片的环路滤波器设计

    的应用。环路滤波器是锁相环频率合成器的关键部分,是频率合成器设计中的一个最重要的环节,其参数的合理设计
    发表于 06-25 05:00

    详解频率合成器高性能架构的实现

    )可以极大地促进高性能架构的实现。大部分高频系统都使用传统的基于整数分频的设计(图1)或基于分数N分频的设计。不管是使用哪种设计,联合使用单个通用频率
    发表于 07-08 06:10

    基于DDS频率合成器设计介绍

    直接数字频率合成DDS)在过去十年受到了频率合成器设计工程师极大的欢迎,它被认为是一种具有低相
    发表于 07-08 07:26

    什么是频率合成器

    和相位来生成被调制信号,因此对于数字通信系统来说可以产生任意的波形。软件无线电系统中的数字上下变频、本地载波的产生以及压控震荡等重要环节都可以用DDS技术实现。  采用DDS技术的
    发表于 08-19 19:18

    如何采用DDS实现频率合成器的设计?

    本文将介绍DDS和PLL的工作原理,并结合一电台(工作频率2 MHz~500 MHz)的设计,给出DDS做参考的PLL频率合成器的设计方案。
    发表于 04-20 06:42

    CIC抽取滤波器MATLAB仿真和FPGA实现

    文章主要讲CIC理论基础,下个文章讲FPGA实现。级联积分梳状滤波器又称CIC。这是多速率信号处理中一种结构简单的
    发表于 08-17 08:27

    DAC模拟乘法器、DDS频率合成器)、信号发生

    DAC模拟乘法器、DDS频率合成器)、信号发生1.DAC模拟乘法器构成的混频是否可以和DDS
    发表于 03-24 17:24

    DDS直接数字频率合成器、信号发生、函数发生

    DDS直接数字频率合成器、信号发生、函数发生1.DDS
    发表于 03-24 18:10

    AD9850 DDS 频率合成器的原理及应用

    AD9850 是AD I 公司采用先进的DDS 技术, 1996年推出的高集成度DDS 频率合成器, 它内部包括可编程DDS 系统、高性能D
    发表于 04-10 13:14 83次下载

    基于FPGA直接数字频率合成器的设计

    直接数字频率合成是一种新的频率合成技术,介绍了利用Altera的FPGA器件
    发表于 08-09 15:02 61次下载

    FPGA实现直接数字频率合成器

     【摘 要】 描述了直接数字频率合成器DDS)的原理和特点,并给出了用FPGA实现
    发表于 05-11 19:52 869次阅读
    <b class='flag-5'>FPGA</b><b class='flag-5'>实现</b>的<b class='flag-5'>直接</b>数字<b class='flag-5'>频率</b><b class='flag-5'>合成器</b>

    频率合成器环路滤波器的设计

    频率合成器环路滤波器的设计,又需要的下来看看
    发表于 12-16 22:23 22次下载

    基于DDS驱动PLL结构的宽带频率合成器的设计与实现

    结合数字式频率合成器DDs)和集成锁相环(PLL)各自的优点,研制并设计了以DDS芯片AD9954和集成锁相芯片ADF4113构成的高分 辨率、低杂散、宽频段
    发表于 10-27 17:54 8次下载
    基于<b class='flag-5'>DDS</b>驱动PLL结构的宽带<b class='flag-5'>频率</b><b class='flag-5'>合成器</b>的设计与<b class='flag-5'>实现</b>