MATLAB-Vivado FIR IP核低通滤波

标题: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)数的表示范围问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

embrace_the_sunhaha

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

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

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

打赏作者

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

抵扣说明:

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

余额充值