VIVADO IP核之FIR插值器多相滤波仿真

VIVADO IP核之FIR插值器多相滤波仿真(含有与MATLAB仿真数据的对比)

目录

前言

一、滤波器系数生成

二、用MATLAB生成仿真数据

三、VIVADO FIR插值多相滤波器使用

四、VIVADO FIR插值多相滤波器仿真

五、VIVADO工程下载

总结


前言

         网络上有许多文章介绍FIR低通滤波器的使用,包括仿真。关于FIR低通滤波器的使用,我之前的文章已经介绍过了,本文将继续深入介绍FIR插值器多相滤波的使用方法,并将FIR插值多相滤波的结果与MATLAB仿真计算的结果比较,验证了FIR插值器多相滤波使用正确


提示:以下是本篇文章正文内容,欢迎各位阅读,转载请附上链接。

一、滤波器系数生成

        仿真假设有一个幅值为1,频率为5MHz,初相为0的正弦波,用30MHz的采样率对其进行采样,那么可以得到一个信号速率为30MSPS,频率为5MHz的正弦波,接下来我们分别用MATLAB和FIR ip核对其进行2插值多相滤波,那么便可以得到一个信号速率为60MSPS,频率为5MHz的正弦波。

        滤波器设计如下,插值之后速率为60M,所以这里滤波器的采样频率是60MHz,而不是30MHz。设计的滤波器为49阶,那么有50个系数,便于2插值多相滤波。

        关于滤波器系数的量化成16bit以及生成coe文件可以参考我的另外一篇博客VIVADO IP核之FIR低通滤波仿真(含滤波器群延时仿真)_vivado fir滤波器-优快云博客,里面有详细的介绍,本文就不再赘述。

二、用MATLAB生成仿真数据

        运行以下代码即可生成vivado仿真所需要的仿真数据data_interpolation_real.txt。

rng default;
clc; 
clear;
close all;

fs =  30e6;     % 采样频率 30MHz
K = 1024;       % 快拍个数
t = 0:1/fs:(K-1)/fs;
f = 5e6;
x = cos(2*pi*f*t);

figure(1);
plot(x(1:30));
grid on;

I=2;
x_up=zeros(1,length(x)*I-I+1);
x_up(1:I:end)=x;

lowpass_Fs_up=30000000*I;    % 低通滤波器的采样频率
lowpass_Fpass_up=10000000;   % 低通滤波器的通带截止频率
lowpass_Fstop_up=14000000;   % 低通滤波器的阻带起始频率
% 下一行的lowpass是用fdatool设计的滤波器保存为matlab code自己修改了一下
[lowpass_b_up,~] = tf(lowpass_1(lowpass_Fs_up,lowpass_Fpass_up,lowpass_Fstop_up));% 得到滤波器系数

x_up_LPF=conv(x_up,lowpass_b_up);
figure(2);
plot(x_up_LPF(1:30*I));
grid on;

h = fopen('data_interpolation_real.txt','w');
for i=1:length(x)
    result= fi(x(i), 1, 16, 9).bin;
    fprintf(h,'%s\n',result);
end
fclose(h);



function Hd = lowpass_1(lowpass_Fs,lowpass_Fpass,lowpass_Fstop)
%LOWPASS_1 返回离散时间滤波器对象。

% MATLAB Code
% Generated by MATLAB(R) 23.2 and Signal Processing Toolbox 23.2.
% Generated on: 12-Sep-2024 16:14:34

% Equiripple Lowpass filter designed using the FIRPM function.

% All frequency values are in Hz.
Fs = lowpass_Fs;  % Sampling Frequency

Fpass = lowpass_Fpass;   % Passband Frequency
Fstop = lowpass_Fstop;   % Stopband Frequency
% Dpass = 0.057501127785;  % Passband Ripple 1dB
% Dpass = 0.028774368332;  % Passband Ripple 0.5dB
Dpass = 0.0063320243772;  % Passband Ripple 0.11dB
% Dpass = 0.0057563991496; % Passband Ripple 0.1dB
Dstop = 0.0001;          % Stopband Attenuation 80dB
% Dstop = 0.0031622776602;  % Stopband Attenuation 50dB
dens  = 20;              % Density Factor

% Calculate the order from the parameters using FIRPMORD.
[N, Fo, Ao, W] = firpmord([Fpass, Fstop]/(Fs/2), [1 0], [Dpass, Dstop]);

% Calculate the coefficients using the FIRPM function.
b  = firpm(N, Fo, Ao, W, {dens});
Hd = dfilt.dffir(b);

% [EOF]

MATLAB原始信号如下图所示:

2插值低通滤波后的信号为(可见FIR滤波器有群延时):

三、VIVADO FIR插值多相滤波器使用

在vivado中搜索FIR滤波器IP核并点进去设置它。滤波器命名为FIIR_polyphase_interpolation_LPF(多打了一个I,自己可以去掉),导入第一步MATLAB生成的滤波器系数文件。Filter type 选择插值,插值因子设置为2。

 输入信号采样速率设置为30MHz,时钟频率设置为60MHz,这样插值前每个输入持续两个时钟周期,2插值后就变成了每个时钟出一个数据

 滤波器系数设置为16位有符号数,输入数据也为16位有符号数,输入数据的小数位数设置为9,这是因为第二步中MATLAB量化的输入数据含有9位小数。然后点击左边的Freq.Response就能看见滤波器的幅度响应。

插值时调用FIR 插值滤波比我们自己给数据插0后再调用FIR低通滤波更节约资源。 

四、VIVADO FIR插值多相滤波器仿真

 在工程中建立一个名为FIR_polyphase_interpolation_LPF_test的tb.v文件。其中$readmemb("data_interpolation_real.txt", signal_real)用于从文本中读取二进制数据赋值给signal_real。

`timescale 1ns / 1ps
//
// Company: cq university
// Engineer: clg
// 
// Create Date: 2024/09/12 21:05:57
// Design Name: 
// Module Name: FIIR_polyphase_interpolation_LPF_test
// Project Name: 
// Target Devices: 
// Tool Versions: 2018.3
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module FIR_polyphase_interpolation_LPF_test();

reg clk=1;
parameter PERIOD=2;
initial
begin
    forever #(PERIOD/2)  clk=~clk;
end
 
reg s_axis_data_tvalid=0;
wire s_axis_data_tready;
reg [15:0] s_axis_data_tdata_real=0;
wire m_axis_data_tvalid;
wire [31:0] m_axis_data_tdata_real;
reg [15:0] s_axis_data_tdata_imag=0;
wire [31:0] m_axis_data_tdata_imag;

integer i=0;
reg [15:0] signal_real[1023:0];
reg [15:0] signal_imag[1023:0];

reg clk_divide2=1;
always @(posedge clk)
begin
    clk_divide2=!clk_divide2;
end
 
initial
begin
    $readmemb("data_interpolation_real.txt", signal_real);//读入采样数据
    $readmemb("data_interpolation_imag.txt", signal_imag);//读入采样数据
    #(PERIOD*5)
    forever 
    begin
        @(posedge clk) 
        begin
            if(i<1024&&clk_divide2==1) 
                begin
                    s_axis_data_tvalid<=1;
                    s_axis_data_tdata_real <= signal_real[i];
                    s_axis_data_tdata_imag <= signal_imag[i];
                    i <= i + 1;
                end
            else
                begin
                    s_axis_data_tvalid<=0;
                    s_axis_data_tdata_real <= s_axis_data_tdata_real;
                    s_axis_data_tdata_imag <= s_axis_data_tdata_imag;
                end
        end
    end 
end

integer dout_file_real;
integer dout_file_imag;
initial 
begin
    dout_file_real=$fopen("E:/play_vivado/FIR_polyphase_interpolation_test/Readme/m_axis_data_tdata_real.txt"); //打开所创建的文件,修改为自己想存储的位置
    dout_file_imag=$fopen("E:/play_vivado/FIR_polyphase_interpolation_test/Readme/m_axis_data_tdata_imag.txt"); //打开所创建的文件,修改为自己想存储的位置
    if(dout_file_real == 0 || dout_file_imag == 0)
    begin 
        $display ("can not open the file!"); //创建文件失败,显示can not open the file!
        $stop;
    end
end

initial
begin
    #(PERIOD*33)
    forever
    begin
        @(posedge clk) 
        begin
            $fdisplay(dout_file_real,"%d",$signed(m_axis_data_tdata_real)); //保存有符号数据
            $fdisplay(dout_file_imag,"%d",$signed(m_axis_data_tdata_imag)); //保存有符号数据
        end
    end
end

FIIR_polyphase_interpolation_LPF u_FIIR_polyphase_interpolation_LPF_real (
  .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_real),    // 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_real)    // output wire [31 : 0] m_axis_data_tdata
);

FIIR_polyphase_interpolation_LPF u_FIIR_polyphase_interpolation_LPF_imag (
  .aclk(clk),                              // input wire aclk
  .s_axis_data_tvalid(s_axis_data_tvalid),  // input wire s_axis_data_tvalid
  .s_axis_data_tready( ),  // output wire s_axis_data_tready
  .s_axis_data_tdata(s_axis_data_tdata_imag),    // input wire [15 : 0] s_axis_data_tdata
  .m_axis_data_tvalid( ),  // output wire m_axis_data_tvalid
  .m_axis_data_tdata(m_axis_data_tdata_imag)    // output wire [31 : 0] m_axis_data_tdata
);

endmodule

然后点击run simulation。将s_axis_data_tdata_real的数据格式设置为定点有符号数,小数位数为9位。将m_axis_data_tdata_real的数据格式设置为定点有符号数,小数位数为25位。然后就能看见输入的数据依次为1,0.5,-0.5...,和MATLAB生成的信号数据是对的上的。滤波后的数据依次为-0.000396,0.001586,...,和MATLAB滤波后的信号数据也是对的上的。

将输入输出设置为波形显示如下:

 分析下图,可知输入原本一个周期的正弦波只有6个点,但经过2插值后一个周期输出便有了12个点。

五、VIVADO工程下载

https://download.youkuaiyun.com/download/m0_66360845/89774826icon-default.png?t=O83Ahttps://download.youkuaiyun.com/download/m0_66360845/89774826


总结

         本文讲解了VIVADO中FIR插值多相滤波器IP核的使用,通过仿真,与MATLAB计算的数据相比较,验证了VIVADO中FIR插值多相滤波器本身是没有考虑滤波器的群延时的,以上的仿真结果很好的说明了如何使用VIIVADO FIR插值多相滤波器。

<think>好的,我现在需要帮用户解决如何在Vivado中实现FIR滤波器并与MATLAB进行对比或联合使用的问题。首先,我应该先理解用户的需求。用户可能是在做数字信号处理的项目,需要同时使用VivadoMATLAB来设计和验证FIR滤波器,可能是在硬件实现和仿真测试方面需要结合两者。 用户提到了引用1、2、3,这些引用内容涉及VivadoFIR IPMATLAB滤波器设计工具以及两者的联合使用。因此,我需要结合这些资料来构建答案。首先,我需要回忆Vivado中如何使用FIR IP,包括步骤如创建工程、添加IP、配置参数、生成COE文件等。然后,在MATLAB部分,用户可能需要设计滤波器并生成测试信号,比如使用FDATool或者Filter Design & Analysis Tools,导出系数到COE文件,以及进行仿真验证。 接下来是如何将两者集成或对比。可能需要比较两者的设计流程、性能指标如频率响应、资源使用情况,或者联合仿真的步骤,比如在MATLAB生成测试数据,导入Vivado进行仿真,再将结果导回MATLAB分析。同时,用户可能需要知道如何确保设计的一致性,比如系数精度、数据位宽等。 还需要考虑用户可能的疑问点,比如如何在Vivado中正确配置IP的参数,MATLAB中如何生成符合要求的COE文件,以及联合仿真时的数据格式转换问题。此外,性能对比可能涉及硬件资源消耗、滤波效果、处理速度等,需要给出具体的比较方法。 需要确保回答结构清晰,分步骤说明,同时引用提供的参考资料。例如,引用1提到VivadoFIR IP实现,引用2和3涉及MATLAB设计滤波器并生成COE文件,以及联合仿真的步骤。因此,在回答中需要分部分说明Vivado实现步骤、MATLAB设计步骤、对比方法和联合使用案例,并在适当的地方添加引用标记。 还需要生成相关问题,这些问题应该围绕用户可能的后续疑问,比如如何优化FIR滤波器的资源使用,如何处理不同数据位宽的问题,或者如何进行实时验证等。确保问题具有连贯性和逻辑性,帮助用户深入理解主题。 最后,检查是否符合系统级指令,如使用正确的中文表达,数学公式的格式是否正确,引用标记是否恰当,以及生成的三个相关问题是否相关且有意义。需要避免技术错误,比如步骤顺序是否正确,参数配置是否合理,以及数据处理的流程是否准确。</think>### VivadoMATLAB联合实现FIR滤波器的集成与对比方法 #### 一、Vivado中实现FIR滤波器的步骤 1. **创建IP工程** 在Vivado中新建工程后,通过`IP Catalog`搜索并添加`FIR Compiler` IP。配置参数时需注意: - **滤波器类型**:选择低通/高通等类型,与MATLAB设计一致[^3]。 - **系数来源**:导入MATLAB生成的COE文件(需16位定点量化)[^2]。 - **数据位宽**:设置为16位以匹配输入信号位宽。 2. **生成IP并集成到工程** 完成配置后生成IP,并在顶层模块中实例化。示例代码片段: ```verilog fir_filter u_fir ( .aclk(clk), .s_axis_data_tvalid(data_valid), .s_axis_data_tdata(input_signal), .m_axis_data_tvalid(output_valid), .m_axis_data_tdata(output_signal) ); ``` 3. **仿真与验证** 使用Vivado仿真工具验证滤波器功能,输入MATLAB生成的混合正弦波测试数据。 --- #### 二、MATLAB滤波器设计与联合验证 1. **滤波器系数生成** 使用`fdatool`或`filterDesigner`工具,设置参数: - 采样率:$20\ \text{MHz}$,通带截止频率:$F_{\text{pass}}=2\ \text{MHz}$,阻带截止频率:$F_{\text{stop}}=6\ \text{MHz}$。 - 导出系数为COE文件时选择`Xilinx Coefficient (.coe)`格式[^2]。 2. **信号生成与滤波验证** ```matlab % 生成3MHz和19MHz正弦波 t = 0:1/20e6:4096*(1/20e6)-1/20e6; sig1 = int16(32767*sin(2*pi*3e6*t)); sig2 = int16(32767*sin(2*pi*19e6*t)); mixed_sig = sig1 + sig2; % 应用滤波器 filtered_sig = filter(fir_coeff, 1, double(mixed_sig)); ``` --- #### 三、对比与联合使用方法 1. **性能对比维度** - **频率响应**:通过MATLAB的`freqz()`函数与Vivado仿真结果对比幅频特性曲线[^1]。 - **资源占用**:Vivado综合后查看LUT、DSP48E等硬件资源消耗。 - **实时性**:测量Vivado实现的流水线延迟(通常为$N+1$个周期,$N$为阶数)[^3]。 2. **数据闭环验证流程** ```mermaid graph LR A[MATLAB生成测试数据] --> B[Vivado仿真输出] B --> C[导出Vivado结果到MATLAB] C --> D[绘制时域/频域对比图] ``` --- #### 四、注意事项 1. **系数精度对齐** MATLAB导出的COE文件需与Vivado IP的系数位宽一致(例如16位定点),否则会导致频率响应偏差。 2. **数据接口处理** Vivado中输入信号需转换为补码格式,例如16位信号范围为$-32768$到$32767$,对应MATLAB的`int16`类型。 ---
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FPGA与信号处理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值