标题:MATLAB-Vivado FIR IP核低通滤波
学习目标:
MATLAB中产生有两个频率信号数据的txt文本=>vivado在testbench中读取txt文本=>调用FIR低通滤波器IP核(32bits_to_32bits)滤去信号的高频分量=>将IP核输出信号通过txt文本输出=>用MATLAB对输出信号处理,观察时域频域波形
学习内容:
1、MATLAB中产生有两个频率信号数据的txt文本
FIR_data_in_32bits.m
clc
clear all
close all
f1 = 0.5; %信号1频率为500kHz
f2 = 5; %信号2频率为5MHz
Fs = 32; %采样频率为32MHz
N = 16;%量化位数
%产生信号
t = 0:1/Fs:5;
c1 = 2*pi*f1*t;
c2 = 2*pi*f2*t;
s1 = sin(c1); %产生正弦波
s2 = sin(c2); %产生正弦波
s = s1 + s2; %产生两个单载波合成后的信号
s = s/max(abs(s));
figure(1)
plot(s);
xlabel('时域(采样点)');
ylabel('幅度');
s_fft=fft(s,161*5); %对回波信号进行快速傅里叶变换到频域
figure(2)
plot(abs(s_fft));
xlabel('频域(采样点)');
ylabel('幅度');
figure(3)
plot(20*log10(abs(s_fft)));
% 量化取整
lfm=round(2147483647*s); %最大为2147483647,量化为32位
lfm(find(lfm<0))=lfm(find(lfm<0))+4294967296; %为何加4294967296,把负数转化为其补码对应的数
gen_data_file_bin(lfm,'D:\Desktop\FIR_32bits_to_32bits\MATLAB\in_data.txt');
gen_data_file_bin.m
function gen_data_file_bin(data,fileName)
%% Introduction
% 功能:用于产生ModelSim仿真时,可被Verilog程序读取的数据文件
%
% 说明:data 为输入数据的一维矩阵
%
%% Code
num_data = numel(data);
fid = fopen(fileName,'w');
for i = 1:num_data
fprintf(fid,'%s\r\n',dec2bin(data(i),32));%x\r\n',data(i));
end
fclose(fid);
end
vivado中FIR滤波器核设置
https://blog.youkuaiyun.com/DengFengLai123/article/details/103916036
https://blog.youkuaiyun.com/m0_66360845/article/details/140936464
重要或需要更改的内容如下
2、
利用MATLAB中的FDAtools设置FIR低通滤波器(主要为了得到滤波器的参数,及最后生成的coe文件,供上一步滤波器核设置里面要用到)
https://blog.youkuaiyun.com/DengFengLai123/article/details/103890404
在MATLAB的命令行窗口输入filterDesigner,接着界面就会跳出滤波器设计工具的界面。如下图所示,我们选择低通,FIR滤波器
重要或需要更改的内容如下
1、
低通(Lowpass),FIR滤波器,窗函数设计(Window),采用布莱克曼窗(Blackman),99阶(会有100个系数,这个是固定的,N阶FIR需要N+1个系数),抽样频率32MHz,通带频率1.5MHz,使用窗函数时截止频率不需要设定,选定的窗函数和阶数已经限定了截止频率。
2、
使用32位的滤波器参数,定点数表示。
点击左侧第三个框,进行参数量化,在FPGA中计算浮点数是很麻烦的事情,并且浮点数的操作在射频输出时会影响功放性能,此处设置为定点数(一般都是设为定点数处理,设成浮点数可以试一下,是无法导出为Xilinx设计所需的.coe文件)。这里进行量化时就会引入量化误差,位数越少误差越大,但是位数越多在FPGA硬件中所需的资源也越多,设计中也是需要综合考虑,此处选择32位定点数量化(Fixed-point)。
如上图所示,量化为32位后滤波器的幅频响应要好很多
3、导出参数
(1)导出参数到matlab
回到设计界面(不回去也不影响导出参数,此处为了更方便观看滤波器的参数),再点击 Export,即可导出参数到 matlab,导出一个名为 Num 的数组,名字可以自己修改,在命令行输入 Num 再回车即可观察系数。
(2)导出参数到Xilinx的存储文件(.coe文件)
点击 Targets -> XILINX Coeffient(.coe) File,
导出的参数共有 100 个,可以发现这样设计出来的时对称结构的FIR滤波器,第一个参数和第 100 个参数一样,第 2 个和第 99 个一样,依次对应。
FIR_BPF_99_1_5M.coe
vivado_testbench编写(一定注意在读txt文本和写txt文本时用斜杠,不是反斜杠,直接复制windows的路径是反斜杠,所以要改,否则造成的最直接的问题就是数据读不进去,vivado软仿后输入数据是红×)
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/09/01 17:27:05
// Design Name:
// Module Name: fir_ip_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module fir_ip_tb();
reg clk;
wire data_in_ready;
reg [31:0] data_in;
wire data_out_valid;
wire [31:0] data_out;
FIR_32bits_to_32bits_wrapper U1_FIR_32bits_to_32bits_wrapper
(
.aclk_0(clk),
.S_AXIS_DATA_0_tdata(data_in),
.S_AXIS_DATA_0_tready(data_in_ready),
.S_AXIS_DATA_0_tvalid(1'b1),
.M_AXIS_DATA_0_tdata(data_out),
.M_AXIS_DATA_0_tvalid(data_out_valid)
);
initial begin
clk = 0;
end
always #16 clk = ~clk;
//从外部txt文件读入数据作为测试激励
parameter data_num = 64;
integer Pattern;
reg [31:0] stimulus[1:data_num];
initial
begin
$readmemb("D:/Desktop/FIR_32bits_to_32bits/MATLAB/in_data.txt",stimulus,1,data_num);//读取txt文本数据,注意斜杠方向
Pattern = 0;
repeat(30) begin
repeat(data_num) begin
Pattern = Pattern + 1;
data_in = stimulus[Pattern];
#32;
end
Pattern = 0;
end
#500;
$stop;
end
integer file_out;
initial
begin
file_out = $fopen("D:/Desktop/FIR_32bits_to_32bits/MATLAB/FIR_out.txt");//写txt文本数据,注意斜杠
if (!file_out) begin
$display("can't open file");
$finish;
end
end
wire signed [31:0] dout_s = data_out;
wire rst_write = clk & data_out_valid; //data_out_valid有效时写入数据
always @ (posedge rst_write)
$fdisplay(file_out, "%d", dout_s);
`define dump_level 10
//module dump_task;
initial begin#1; //延迟1ns记录,方便与其他仿真动作协调
`ifdef VCS_DUMP //Synopsys VCD+格式存储
$display("Start Recording Waveform in VPD format!");
$vcdpluson();
$vcdplustraceon;
`endif
`ifdef FSDB_DUMP //Synopsys fsdb格式存储
$display("Start Recording Waveform in FSDB format!");
$fsdbDumpfile("dump.fsdb");
$fsdbDumpvars('dump_level);
`endif
`ifdef NC_DUMP//cadence 格式存储
$recordsetup("dump","version=1","run=1","directory=.");
$recordvars("depth=6");
`endif
`ifdef VCD_DUMP//工业标准VCD格式存储
$display("Start Recording Waveform in VCD format!");
$dumpfile("dump.vcd");
$dumpvars('dump_level);
`endif
end
endmodule
MATLAB读取FIR IP核出来的数据并做时域频域分析FIR_out_read_32bits.m
clc
clear all
close all
fid=fopen('D:\Desktop\FIR\FIR_out.txt','r'); %以读的方式打开
read_data = fscanf(fid,'%ld\n'); %以10进制的方式读进来
fclose(fid); %关闭文件
read_data = double(read_data);
read_data1 = read_data/2147483647.0; %max(abs(read_data))
figure(1)
plot(read_data1);
xlabel('时域(采样点)');
ylabel('幅度');
xlabel('频域(采样点)');
ylabel('幅度');
read_data_fft=fft(read_data1,1878*2); %对回波信号进行快速傅里叶变换到频域
figure(2)
plot(abs(read_data_fft));
figure(3)
plot(20*log10(abs(read_data_fft)));
Vivado代码:
//FIR_32bits_to_32bits_wrapper.v
//Copyright 1986-2018 Xilinx, Inc. All Rights Reserved.
//--------------------------------------------------------------------------------
//Tool Version: Vivado v.2018.2 (win64) Build 2258646 Thu Jun 14 20:03:12 MDT 2018
//Date : Fri Sep 4 12:12:59 2020
//Host : LAPTOP-DDB3CLJA running 64-bit major release (build 9200)
//Command : generate_target FIR_32bits_to_32bits_wrapper.bd
//Design : FIR_32bits_to_32bits_wrapper
//Purpose : IP block netlist
//--------------------------------------------------------------------------------
`timescale 1 ns / 1 ps
module FIR_32bits_to_32bits_wrapper
(M_AXIS_DATA_0_tdata,
M_AXIS_DATA_0_tvalid,
S_AXIS_DATA_0_tdata,
S_AXIS_DATA_0_tready,
S_AXIS_DATA_0_tvalid,
aclk_0);
output [31:0]M_AXIS_DATA_0_tdata;
output M_AXIS_DATA_0_tvalid;
input [31:0]S_AXIS_DATA_0_tdata;
output S_AXIS_DATA_0_tready;
input S_AXIS_DATA_0_tvalid;
input aclk_0;
wire [31:0]M_AXIS_DATA_0_tdata;
wire M_AXIS_DATA_0_tvalid;
wire [31:0]S_AXIS_DATA_0_tdata;
wire S_AXIS_DATA_0_tready;
wire S_AXIS_DATA_0_tvalid;
wire aclk_0;
FIR_32bits_to_32bits FIR_32bits_to_32bits_i
(.M_AXIS_DATA_0_tdata(M_AXIS_DATA_0_tdata),
.M_AXIS_DATA_0_tvalid(M_AXIS_DATA_0_tvalid),
.S_AXIS_DATA_0_tdata(S_AXIS_DATA_0_tdata),
.S_AXIS_DATA_0_tready(S_AXIS_DATA_0_tready),
.S_AXIS_DATA_0_tvalid(S_AXIS_DATA_0_tvalid),
.aclk_0(aclk_0));
endmodule
// FIR_32bits_to_32bits.v
//Copyright 1986-2018 Xilinx, Inc. All Rights Reserved.
//--------------------------------------------------------------------------------
//Tool Version: Vivado v.2018.2 (win64) Build 2258646 Thu Jun 14 20:03:12 MDT 2018
//Date : Fri Sep 4 12:12:58 2020
//Host : LAPTOP-DDB3CLJA running 64-bit major release (build 9200)
//Command : generate_target FIR_32bits_to_32bits.bd
//Design : FIR_32bits_to_32bits
//Purpose : IP block netlist
//--------------------------------------------------------------------------------
`timescale 1 ps / 1 ps
(* CORE_GENERATION_INFO = “FIR_32bits_to_32bits,IP_Integrator,{x_ipVendor=xilinx.com,x_ipLibrary=BlockDiagram,x_ipName=FIR_32bits_to_32bits,x_ipVersion=1.00.a,x_ipLanguage=VERILOG,numBlks=1,numReposBlks=1,numNonXlnxBlks=0,numHierBlks=0,maxHierDepth=0,numSysgenBlks=0,numHlsBlks=0,numHdlrefBlks=0,numPkgbdBlks=0,bdsource=USER,synth_mode=OOC_per_IP}” ) ( HW_HANDOFF = “FIR_32bits_to_32bits.hwdef” )
module FIR_32bits_to_32bits
(M_AXIS_DATA_0_tdata,
M_AXIS_DATA_0_tvalid,
S_AXIS_DATA_0_tdata,
S_AXIS_DATA_0_tready,
S_AXIS_DATA_0_tvalid,
aclk_0);
( X_INTERFACE_INFO = “xilinx.com:interface:axis:1.0 M_AXIS_DATA_0 TDATA” ) ( X_INTERFACE_PARAMETER = “XIL_INTERFACENAME M_AXIS_DATA_0, CLK_DOMAIN FIR_32bits_to_32bits_aclk_0, FREQ_HZ 100000000, HAS_TKEEP 0, HAS_TLAST 0, HAS_TREADY 0, HAS_TSTRB 0, LAYERED_METADATA xilinx.com:interface:datatypes:1.0 {TDATA {datatype {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value {}} bitwidth {attribs {resolve_type automatic dependency {} format long minimum {} maximum {}} value 32} bitoffset {attribs {resolve_type immediate dependency {} format long minimum {} maximum {}} value 0} array_type {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value vect} size {attribs {resolve_type generated dependency vect_size format long minimum {} maximum {}} value 1} stride {attribs {resolve_type generated dependency vect_stride format long minimum {} maximum {}} value 32} datatype {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value {}} bitwidth {attribs {resolve_type automatic dependency {} format long minimum {} maximum {}} value 32} bitoffset {attribs {resolve_type immediate dependency {} format long minimum {} maximum {}} value 0} array_type {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value chan} size {attribs {resolve_type generated dependency chan_size format long minimum {} maximum {}} value 1} stride {attribs {resolve_type generated dependency chan_stride format long minimum {} maximum {}} value 32} datatype {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value {}} bitwidth {attribs {resolve_type automatic dependency {} format long minimum {} maximum {}} value 32} bitoffset {attribs {resolve_type immediate dependency {} format long minimum {} maximum {}} value 0} array_type {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value path} size {attribs {resolve_type generated dependency path_size format long minimum {} maximum {}} value 1} stride {attribs {resolve_type generated dependency path_stride format long minimum {} maximum {}} value 32} datatype {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value {}} bitwidth {attribs {resolve_type generated dependency out_width format long minimum {} maximum {}} value 32} bitoffset {attribs {resolve_type immediate dependency {} format long minimum {} maximum {}} value 0} real {fixed {fractwidth {attribs {resolve_type generated dependency out_fractwidth format long minimum {} maximum {}} value 0} signed {attribs {resolve_type generated dependency out_signed format bool minimum {} maximum {}} value true}}}}}}}}}}} TDATA_WIDTH 32 TUSER {datatype {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value {}} bitwidth {attribs {resolve_type automatic dependency {} format long minimum {} maximum {}} value 0} bitoffset {attribs {resolve_type immediate dependency {} format long minimum {} maximum {}} value 0} struct {field_data_valid {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value data_valid} enabled {attribs {resolve_type generated dependency data_valid_enabled format bool minimum {} maximum {}} value false} datatype {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value {}} bitwidth {attribs {resolve_type generated dependency data_valid_bitwidth format long minimum {} maximum {}} value 0} bitoffset {attribs {resolve_type immediate dependency {} format long minimum {} maximum {}} value 0}}} field_chanid {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value chanid} enabled {attribs {resolve_type generated dependency chanid_enabled format bool minimum {} maximum {}} value false} datatype {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value {}} bitwidth {attribs {resolve_type generated dependency chanid_bitwidth format long minimum {} maximum {}} value 0} bitoffset {attribs {resolve_type generated dependency chanid_bitoffset format long minimum {} maximum {}} value 0} integer {signed {attribs {resolve_type immediate dependency {} format bool minimum {} maximum {}} value false}}}} field_user {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value user} enabled {attribs {resolve_type generated dependency user_enabled format bool minimum {} maximum {}} value false} datatype {name {attribs {resolve_type immediate dependency {} format string minimum {} maximum {}} value {}} bitwidth {attribs {resolve_type generated dependency user_bitwidth format long minimum {} maximum {}} value 0} bitoffset {attribs {resolve_type generated dependency user_bitoffset format long minimum {} maximum {}} value 0}}}}}} TUSER_WIDTH 0}, PHASE 0.000, TDATA_NUM_BYTES 4, TDEST_WIDTH 0, TID_WIDTH 0, TUSER_WIDTH 0” ) output [31:0]M_AXIS_DATA_0_tdata;
( X_INTERFACE_INFO = “xilinx.com:interface:axis:1.0 M_AXIS_DATA_0 TVALID” ) output M_AXIS_DATA_0_tvalid;
( X_INTERFACE_INFO = “xilinx.com:interface:axis:1.0 S_AXIS_DATA_0 TDATA” ) ( X_INTERFACE_PARAMETER = “XIL_INTERFACENAME S_AXIS_DATA_0, CLK_DOMAIN FIR_32bits_to_32bits_aclk_0, FREQ_HZ 100000000, HAS_TKEEP 0, HAS_TLAST 0, HAS_TREADY 1, HAS_TSTRB 0, LAYERED_METADATA undef, PHASE 0.000, TDATA_NUM_BYTES 4, TDEST_WIDTH 0, TID_WIDTH 0, TUSER_WIDTH 0” ) input [31:0]S_AXIS_DATA_0_tdata;
( X_INTERFACE_INFO = “xilinx.com:interface:axis:1.0 S_AXIS_DATA_0 TREADY” ) output S_AXIS_DATA_0_tready;
( X_INTERFACE_INFO = “xilinx.com:interface:axis:1.0 S_AXIS_DATA_0 TVALID” ) input S_AXIS_DATA_0_tvalid;
( X_INTERFACE_INFO = “xilinx.com:signal:clock:1.0 CLK.ACLK_0 CLK” ) ( X_INTERFACE_PARAMETER = “XIL_INTERFACENAME CLK.ACLK_0, ASSOCIATED_BUSIF S_AXIS_DATA_0:M_AXIS_DATA_0, CLK_DOMAIN FIR_32bits_to_32bits_aclk_0, FREQ_HZ 100000000, PHASE 0.000” *) input aclk_0;
wire [31:0]S_AXIS_DATA_0_1_TDATA;
wire S_AXIS_DATA_0_1_TREADY;
wire S_AXIS_DATA_0_1_TVALID;
wire aclk_0_1;
wire [31:0]fir_compiler_0_M_AXIS_DATA_TDATA;
wire fir_compiler_0_M_AXIS_DATA_TVALID;
assign M_AXIS_DATA_0_tdata[31:0] = fir_compiler_0_M_AXIS_DATA_TDATA;
assign M_AXIS_DATA_0_tvalid = fir_compiler_0_M_AXIS_DATA_TVALID;
assign S_AXIS_DATA_0_1_TDATA = S_AXIS_DATA_0_tdata[31:0];
assign S_AXIS_DATA_0_1_TVALID = S_AXIS_DATA_0_tvalid;
assign S_AXIS_DATA_0_tready = S_AXIS_DATA_0_1_TREADY;
assign aclk_0_1 = aclk_0;
FIR_32bits_to_32bits_fir_compiler_0_0 fir_compiler_0
(.aclk(aclk_0_1),
.m_axis_data_tdata(fir_compiler_0_M_AXIS_DATA_TDATA),
.m_axis_data_tvalid(fir_compiler_0_M_AXIS_DATA_TVALID),
.s_axis_data_tdata(S_AXIS_DATA_0_1_TDATA),
.s_axis_data_tready(S_AXIS_DATA_0_1_TREADY),
.s_axis_data_tvalid(S_AXIS_DATA_0_1_TVALID));
endmodule
学习时间:
2020/9/4 上午
学习产出:
完成了FIR IP核32bits到32bits的设计,以及从txt文本读入信号,在输出信号写入到txt文本中
FIR_data_in_32bits.m生成的图
两个正弦信号相加的时域波形图
两个正弦信号相加的频域波形图
两个正弦信号相加的频域dB图
vivado中编写testbench软仿得出来的导入信号图以及滤波后的单频信号图
vivado输出信号导出后经matlab分析后的信号图
经滤波器滤波后剩余的信号时域图
经滤波器滤波后剩余的信号频域图
经滤波器滤波后剩余的信号频域dB图
学习重要点总结
(1)当导出的信号出现顶部失真时,但vivado软仿的信号图形没问题,则可推断问题出在txt文本数据写入或者MATALAB读取txt文本时会出现问题,信号表示位数及范围,数据精度,输入输入的数据格式都会产生数据不一致到时图形不对的情况。**
发现的问题
**输入信号的量化到底该怎么做,从原理上分析下,按道理来说输出信号除以2147483647.0后应该小于1,但信号有大于2的值,应详细分析下(1)信号值的量化原理,以及(2)数的表示范围问题