Vivado的FIR IP核实现低通滤波器

  本文介绍如何使用Vivado的FIR IP核实现低通滤波器。我们将设计一个采样频率为10MHz,通带0~1MHz,阻带高于2MHz的FIR低通滤波器。测试时,滤波器的输入信号为1MHz和3MHz的正弦波的叠加信号,期望滤波器能输出失真较小的1MHz的正弦信号。

1、用MATLAB的firpm函数设计FIR低通滤波器

  MATLAB的firpm函数能够设计最优FIR滤波器,详细用法可以参考MATLAB的help文档。这里,我们先用采用kaiserord函数获取满足要求的最小滤波器阶数,再用firpm设计滤波器。滤波器的系数采用12bit有符号量化,并输出.coe文件,方便Vivado导入到FIR IP核。下面给出完整MATLAB代码。

%设计一个低通滤波器。
%采样频率fs=10MHz,过渡带fc=[1MHz 2MHz],通带容限0.1,阻带容限0.01。
fs=10*10^6;           %采样频率
qm=12;               %滤波器系数量化位数
fc=[1*10^6 2*10^6];  %过渡带
mag=[1 0];           %窗函数的理想滤波器幅度
%设置通带容限a1及阻带容限a2
%通带衰减ap=-20*log10(1-a1)=0.915dB,阻带衰减为as=-20*log10(a2)=40dB
a1=0.1;a2=0.01;
dev=[a1 a2];
%采用凯塞窗函数获取满足要求的最小滤波器阶数
[n,~,~,~] = kaiserord(fc,mag,dev,fs);
%采用firpm函数设计最优滤波器
fpm=[0 fc(1)*2/fs fc(2)*2/fs 1];  %firpm函数的频段向量
magpm=[1 1 0 0];                  %firpm函数的幅值向量
h_pm=firpm(n,fpm,magpm);          %设计最优滤波器
h_pm = h_pm/max(abs(h_pm));
%量化滤波系数
q_pm=round(h_pm*(2^(qm-1)-1));%12bit有符号整数
%将生成的滤波器系数数据写入FPGA所需的coe文件中
fid=fopen('.\fir_coe.coe','w');
fprintf(fid, "RADIX=10;\n");%生成索引
fprintf(fid, "COEFDATA = \n");
for i = 1:n+1
    if i == n+1
        fprintf(fid,'%d;', q_pm(i));
    else
        fprintf(fid,'%d,', q_pm(i));
    end
end
fclose(fid);
%获取量化前后滤波器的幅频响应数据
m_pm=20*log10(abs(fft(h_pm,1024)));
m_pm=m_pm-max(m_pm);
q_pm=20*log10(abs(fft(q_pm,1024)));
q_pm=q_pm-max(q_pm);
%设置幅频响应的横坐标单位为MHz
x_f = (0:(fs/length(m_pm)):fs/2)/10^6;
%只显示正频率部分的幅频响应
mf_pm=m_pm(1:length(x_f));
mf_qm=q_pm(1:length(x_f));
%绘制幅频响应曲线
plot(x_f,mf_pm,'--',x_f,mf_qm,'-');
xlabel('频率(MHz)');ylabel('幅度(dB)');
legend('未量化','12位量化');
grid;

  下图展示了FIR低通滤波器量化前后的归一化幅频响应,可以看到没有明显的量化误差。
FIR幅频响应

2、配置Vivado的FIR IP核

  2.1 新建一个Vivado工程,点击Flow Navigator中的IP Catalog,选择FIR Compiler,打开FIR IP核的配置窗口。
在这里插入图片描述  2.2 在Filter Options页中向IP核导入MATLAB输出的.coe文件。
在这里插入图片描述  2.3 在Channel Specification页设置时钟频率为50MHz,采样频率为10MHz(与MATLAB中的设计一致)。
在这里插入图片描述  2.4 根据前面MATLAB的设计,Implementation页设置FIR滤波器的系数为12bit有符号整数。FIR输入数据设置为16bit有符号整数,FIR输出位宽被自动设置为30bit。其他保持默认设置。
在这里插入图片描述  2.5 介绍FIR IP核的主要接口。
FIR引脚图

  • aresetn:复位引脚,低电平复位FIR IP核;
  • aclk:时钟引脚,工程中输入50MHz时钟信号;
  • s_axis_data_tdata:输入采样数据;
  • s_axis_data_tready:1 表示IP核准备好接收采样数据;
  • s_axis_data_tvalid:1 表示s_axis_data_tdata输入的采样数据有效;
  • m_axis_data_tdata:输出滤波后的数据;
  • m_axis_data_tvalid:1 表示m_axis_data_tdata输出的数据有效。
    在这里插入图片描述
    在这里插入图片描述

3、编写Verilog代码例化FIR IP核

  代码例化一个FIR IP核,引出必要的控制和数据接口。

module project_fir(
    input clk,
    input reset_n,
    input s_axis_data_tvalid,
    output s_axis_data_tready,
    input [15:0] s_axis_data_tdata,
    output m_axis_data_tvalid,
    output [31:0] m_axis_data_tdata
    );
fir_compiler_0 your_instance_name (
      .aresetn(reset_n),                        // input wire aresetn
      .aclk(clk),                              // input wire aclk
      .s_axis_data_tvalid(s_axis_data_tvalid),  // input wire s_axis_data_tvalid
      .s_axis_data_tready(s_axis_data_tready),  // output wire s_axis_data_tready
      .s_axis_data_tdata(s_axis_data_tdata),    // input wire [15 : 0] s_axis_data_tdata
      .m_axis_data_tvalid(m_axis_data_tvalid),  // output wire m_axis_data_tvalid
      .m_axis_data_tdata(m_axis_data_tdata)    // output wire [31 : 0] m_axis_data_tdata
    );  
endmodule

4、编写test bench文件

  test bench文件的功能是生成复位信号、50MHz的时钟信号、s_axis_data_tvalid信号等,用于仿真。系统时钟频率为50MHz,采样频率为10MHz,s_axis_data_tvalid需要每五个时钟周期产生一个时钟周期的正脉冲驱动FIR IP核读入采样数据。

`timescale 1ns / 1ps
module tb_fir();
parameter LEN = 1000;
reg clk;
reg reset_n;
reg [15:0] signal[LEN-1:0];
reg [15:0] data_tdata;
reg data_tvalid;
reg [3:0] cnt;
wire s_axis_data_tvalid;
wire s_axis_data_tready;
wire [15:0] s_axis_data_tdata;
wire m_axis_data_tvalid;
wire [31:0] m_axis_data_tdata;
initial begin
    clk = 1'b0;
    reset_n = 1'b0;
    data_tvalid = 1'b0;
    $readmemh("signal.txt", signal);//从signal.txt中读入采样数据
    #200
    reset_n = 1'b1;
    #100
    repeat(5) begin //filter task重复执行5次
        filter;
    end
end
always #10 clk = ~clk; // 50MHz
always @(posedge clk or negedge reset_n) begin
    if(!reset_n) begin
        cnt <= 4'd0;
        data_tvalid <= 1'b0;
    end
    else begin
        cnt <= cnt +4'd1;
        if(cnt == 4) begin
            cnt <= 4'd0;
            data_tvalid <= 1'b1;
        end
        else
            data_tvalid <= 1'b0;
    end
end
assign s_axis_data_tvalid = data_tvalid; //生成 s_axis_data_tvalid 脉冲信号
assign s_axis_data_tdata = data_tdata;
integer k;
task filter;
    begin
        for(k = 0; k < LEN; k = k+1)
            #100 data_tdata = signal[k]; //间隔100ns(10MHz)读入一个采样数据
    end
endtask
project_fir fir( //例化第3节写的模块
    .clk(clk),
    .reset_n(reset_n),
    .s_axis_data_tvalid(s_axis_data_tvalid),
    .s_axis_data_tready(s_axis_data_tready),
    .s_axis_data_tdata(s_axis_data_tdata),
    .m_axis_data_tvalid(m_axis_data_tvalid),
    .m_axis_data_tdata(m_axis_data_tdata)
    );
endmodule

  $readmemh(“signal.txt”, signal);该行代码从signal.txt文件中读取16进制表示的采样数据序列到signal存储器中。signal.txt文件用MATLAB生成,并将signal.txt放到工程的".\project_fir.sim\sim_1\behav\xsim"路径下才能被正确读取。
在这里插入图片描述  生成signal.txt的MATLAB代码如下:

qm=16;%16bit量化
fs = 10000000;%采样频率10MHz
ts = 1/fs;
len = 1000;
t = (0:len-1)*ts;
y = sin(2*pi*1000000*t)+cos(2*pi*3000000*t);%1MHz和3MHz正弦信号叠加
plot(t,y);
y = y/max(abs(y));
q_y=round(y*(2^(qm-1)-1));
fid=fopen('.\signal.txt','w');
for i = 1:len
    if q_y(i) >= 0
        fprintf(fid,'%X\n', q_y(i));
    else
        fprintf(fid,'%X\n', q_y(i)+2^qm);
    end
end
fclose(fid);

5、功能仿真

  编写好FPGA的文件和test bench文件后,进行Behavioral Simulation。点击SIMULATION->Run Simulation->Run Behavioral Simulation,等待一会儿就能看到仿真波形。将s_axis_data_tdata和m_axis_data_tdata波形设置为有符号数、模拟量显示,就可以看到输入的叠加正弦信号和输出的1MHz正弦信号。
在这里插入图片描述  从上图可以看到两个tvalid信号以10MHz的频率产生脉冲,复位结束后tready信号一直有效,FIR低通滤波器滤除了3MHz的正弦信号,输出了1MHz的正弦信号。
  QuartusII的FIR IP核使用方法可以参考杜勇的《数字调制解调技术的MATLAB与FPGA实现 Altera Verilog版》。
完整Vivado工程下载:Vivado的FIR IP核实现低通滤波器工程

  • 35
    点赞
  • 366
    收藏
    觉得还不错? 一键收藏
  • 30
    评论
DDS Compiler IP核是用于生成数字直接合成(DDS)信号的Xilinx IP核。它可以根据配置参数生成一个带有指定频率、幅度和相位的DDS信号。您可以使用DDS Compiler IP核来生成各种应用,如通信系统、音频处理和测量设备等。 您提供的引用是DDS Compiler IP核的官方文档,其中包含了IP核的详细配置和使用说明。您可以通过阅读该文档来了解如何正确配置和使用DDS Compiler IP核。 DDS Compiler IP核的配置主要包括以下几个方面: 1. 时钟和复位:您需要为DDS Compiler IP核提供一个时钟信号和复位信号,以确保IP核正常工作。 2. 输入控制信号:您可以使用控制信号来配置DDS Compiler IP核的工作模式、频率、幅度和相位等参数。 3. 输出数据信号:DDS Compiler IP核会生成一个或多个DDS信号作为输出。您可以根据应用需求选择使用。 根据您提供的引用中的代码示例,您可以看到如何实例化DDS Compiler IP核。在该示例中,DDS Compiler IP核被命名为"dds_compiler_0",并与其他模块一起实例化在一个模块中。您可以根据自己的设计需求修改代码中的参数和接口。 下面是一个简单的使用DDS Compiler IP核的示例: 1. 实例化DDS Compiler IP核并连接时钟和复位信号; 2. 根据需要配置控制信号,如输入频率、幅度和相位等; 3. 连接输出数据信号,并根据需要使用生成的DDS信号。 请注意,DDS Compiler IP核的具体使用方法可能与您的应用需求有关。因此,建议您参考官方文档中的详细说明,并根据您的具体设计需求进行配置和使用。 https://www.xilinx.com/support/documentation/ip_documentation/dds_compiler/v6_0/pg141-dds-compiler.pdf [引用自DDS Compiler IP核官方文档] 个人学习笔记[引用自CSDN网页] 代码示例[引用自用户提供的代码]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值