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滤波器-CSDN博客,里面有详细的介绍,本文就不再赘述。
二、用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.csdn.net/download/m0_66360845/89774826https://download.csdn.net/download/m0_66360845/89774826
总结
本文讲解了VIVADO中FIR插值多相滤波器IP核的使用,通过仿真,与MATLAB计算的数据相比较,验证了VIVADO中FIR插值多相滤波器本身是没有考虑滤波器的群延时的,以上的仿真结果很好的说明了如何使用VIIVADO FIR插值多相滤波器。