Vivado中的FFT IP核使用

点击蓝字关注我们

关注、星标公众号,精彩内容每日送达
来源:网络素材

1、调用IP核

该IP核对应手册pg109_xfft.pdf,首先按照图片找到IP核:

68bbc690db2da84336b7929280d4b775.png d20003d69a7f60b788165ab908166f93.png

2、配置界面介绍

本小节主要介绍Fast Fourier Transform9.1这个IP核配置界面的一些选项:

第1页:Configuration

c9e822002462379a4d8dc198959245bf.png

图1

表1 Configuration界面介绍

1b362a43666ffb77533f079e5f228586.jpeg97f97be632dec62ec969aee0780fae40.jpeg

第2页:Implementation919615a60b10becb8b7d90e6521e6a86.png

图2

表2 Implementation界面介绍

2024a69b4a6867b8e3fdb7fb9515f94a.jpeg 2c3e1df42132bb77d42d67b2b3f33546.jpeg 4c6717a094a403a7d8eba03b4a219bf2.jpeg

第3页:Detailed Implementation71198b3332d2b853af87679e47355adf.png

图3

表3 Detailed Implementation

9a32161d5c30e78b6287a49eb532bd7a.jpeg 62dbc14b622dd550f733f20d7500ffc3.jpeg

3、IP核端口配置

根据上述配置界面的介绍,下面以64点IFFT为例子,总结了使用IP核时所需的端口配置,如表4所示,需要注意的是表4中没有涉及的部分按照IP核的默认配置即可:

表4 64点IFFT运算IP核的设置表汇总

4ad193aa8bad42f1752e251ae8309d0a.jpeg 6f4e09adaa5a6b26c9cec29f6cd024f1.jpeg

配置完成之后IP核的端口图如下:

7f28bbcc2cbf9c646128385c0fdd6367.png

图4 64点IFFT核端口图

按照下面图找到例化原语:

b7ed9f789697d8c271c930b85ac2982a.png

图5

打开.veo后缀的文件找到例化原语:

7a2c1e827f498592f743155a5fd9a170.png

图6

对例化语句的介绍见表5,其中L表示IFFT/FFT的点数。

表5 例化原语介绍

1c5270e0948f07514d083dc3e68e9ec7.jpeg7a05c7d4a214258d778bc24f066d2763.jpeg

60a55ee6438e324e2af356c4e6466a3e.jpeg

需要说明的是,需要配置的端口有,1)aclk;2)aclken;3)s_axis_config_tdata ;4)s_axis_config_tvalid ;5)s_axis_config_tready;6)s_axis_data_tdata;7)s_axis_data_tvalid;8)s_axis_data_tready;9)m_axis_data_tdata;10)m_axis_data_tuser;11)m_axis_data_tready;12)m_axis_data_tlast

4、MATLAB生成测试数据

本次测试只需要使用TestBench验证即可,需要生成.txt后缀的文件,产生IFFT核的输入数据,主要程序为:

%% 该.m文件用来生成介绍IFFT核的数据,具体为64点的IFFT  16QAM
clear
close all
clc
rng default  %产生固定数值的随机数据
%% 基于符号算法的目标距离和速度探测
%% 定义基本参数
Ns=1;                                                   %符号数
Nc=64;                                                  %子载波数
M=16;                                                   %调制方式
bit_num=log2(M);                                        %一个码组中的码元个数
bit=randi([0 1],Nc*Ns*bit_num,1);                       %产生比特
norm=1/sqrt(10);                                        %16qam 归一化因子
%% 16qam
bit_convert=(reshape(bit,bit_num,length(bit)/bit_num))';%二进制数据流按照调制的方式分成不同码元
data_2_to_10=bi2de(bit_convert,'left-msb');             %将每四位数据转换为十进制数
maxtix=reshape(data_2_to_10,Nc,Ns);
bit_mo=norm*qammod(data_2_to_10,M);
a_nm=reshape(bit_mo,Nc,Ns);
%% 发送端IFFT调制
IFFT_OUT=ifft(a_nm,64);
%%  数据保存为.txt文件
    echo_real=real(a_nm);
    echo_imag=imag(a_nm);
    echo1_real=quantizer([16 11]);
    echo1_imag=quantizer([16 11]);
    fid_echo=fopen('C:\Users\15865\Desktop\FFT_IP_core_64point\IFFT_IP_core_64point_exam.txt','wt');
    for j=1:Ns
        echo2_real=num2bin(echo1_real,echo_real(:,j));
        echo2_imag=num2bin(echo1_imag,echo_imag(:,j));
        for i=1:Nc
            imag_real_echo=[echo2_imag(i,:),echo2_real(i,:)];
            fwrite(fid_echo,imag_real_echo);
            fprintf(fid_echo,'\n');
        end
    end
fclose(fid_echo);

图中程序功能是生成了一段包含64个复数数据的数组,并将每个复数数据用16表示实部16位表示虚部共生成32位二进制数,最后将这组数据保存为.txt后缀文件。

5、测试verilog HDL

根据前文的配置编写一个简单的测试.v文件测试64点数据的IFFT运行结果,主要程序如下:

`timescale 1ns / 1ps
module IFFT_introduction(
        input        clk,
        input        rst_n,
        input        ifft_valid,
        input [31:0] data_in,
//        input        last,
        
        output        s_config_tready,
        output [31:0] m_data_tdata,
        output        s_data_tready,
        output [7:0]  m_data_tuser,
        output        m_data_tvalid,
        output        m_data_tlast
    );
 FFT_IP_core_64point ifft_u0(
  .aclk(clk),                                      // input wire aclk
  .aclken(rst_n),                                  // input wire aclken
  .s_axis_config_tdata(8'd0),                      // input wire [7 : 0] s_axis_config_tdata
  .s_axis_config_tvalid(1'b1),                     // input wire s_axis_config_tvalid
  .s_axis_config_tready(s_config_tready),          // output wire s_axis_config_tready
  .s_axis_data_tdata(data_in),                     // input wire [31 : 0] s_axis_data_tdata
  .s_axis_data_tvalid(ifft_valid),                 // input wire s_axis_data_tvalid
  .s_axis_data_tready(s_data_tready),              // output wire s_axis_data_tready
//  .s_axis_data_tlast(s_axis_data_tlast),         // input wire s_axis_data_tlast
  .m_axis_data_tdata(m_data_tdata),                // output wire [31 : 0] m_axis_data_tdata
  .m_axis_data_tuser(m_data_tuser),                // output wire [7 : 0] m_axis_data_tuser
  .m_axis_data_tvalid(m_data_tvalid),              // output wire m_axis_data_tvalid
  .m_axis_data_tready(1'b1),                       // input wire m_axis_data_tready
  .m_axis_data_tlast(m_data_tlast)                 // output wire m_axis_data_tlast
);

  
  wire [15:0] ifft_64point_out_RE,ifft_64point_out_IM;
//  assign RE={{4{m_data_tdata[15]}},m_data_tdata[15:4]};//IFFT归一化处理,除Nfft
//  assign IM={{4{m_data_tdata[39]}},m_data_tdata[39:28]};
  assign ifft_64point_out_IM=m_data_tdata[31:16]; //虚部
  assign ifft_64point_out_RE=m_data_tdata[15:0];  //实部 
  
endmodule

这段程序调用了FFT IP核的例化原语,并将部分接口作为函数的输入和输出,方便TestBench调用。

6、TestBench仿真

主要程序如下:

`timescale 1ns / 1ps
module ifft_tb();
reg        clk;             //系统时钟
reg        rst_n;           //复位信号,低有效
reg        ifft_valid;      //数据有效位,指示输入数据有效
reg [31:0] data_in;         //输入数据
 
wire s_config_tready;       
wire [31:0] m_data_tdata;   
wire s_data_tready;         
wire [7:0] m_data_tuser;    
wire m_data_tvalid;         
wire m_data_tlast;

IFFT_introduction u0(    //例化.v文件
   .clk(clk),
   .rst_n(rst_n),
   .ifft_valid(ifft_valid),
   .data_in(data_in),
   .s_config_tready(s_config_tready),
   .m_data_tdata(m_data_tdata),
   .s_data_tready(s_data_tready), 
   .m_data_tuser(m_data_tuser),
   .m_data_tvalid(m_data_tvalid),
   .m_data_tlast(m_data_tlast)
);
reg [31:0] mem [63:0];
initial begin       //$readmemb Vivado内置函数调用.txt文件
    $readmemb("C:/Users/15865/Desktop/FFT_IP_core_64point/IFFT_IP_core_64point_exam.txt",mem);
    clk=0;
    rst_n=0;
    #1000;
    rst_n=1;
    #10_000;
    $stop;
end
always #10 clk<=~clk;    //50MHz
reg [6:0] count;        
//计数
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) 
        count<='d0;
    else if(count<='d63)
        count<=count+1'b1;
    else
        count<='dz;
end
// 产生信号和数据
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        ifft_valid<='d0;
        data_in<='d0;
    end
    else if(count>='d0 && count<='d63) begin
            ifft_valid<=1;
            data_in<=mem[count];
    end
    else begin
            ifft_valid<=1'b0;
            data_in<='d0;
    end
end
endmodule

7、Modelsim结果与MATLAB输出结果验证

本节将验证Modelsim和MATLAB输出结果的一致性,并简单介绍Modelsim输出结果向MATLAB数据的转换。

Modelsim 输出结果如下图:

dff15a3a5a8fd4392eacd8d542bb2d93.png

图10

由于数据有64个而这里验证前三个中间三个和后三个的方式验证Modelsim数据和MATLAB数据正确性:

表6数据验证0335b2573df2af32f8511f0bdea2feb7.jpeg

需要注意的是,Modelsim输出的结果并不是小数,而是忽略了小数点的整数,要想获得和MATLAB类似的浮点数,需要我们将输出结果变换,这里以Modelsim输出的最后一个数为例(即表6中序号64),可见图11。

d34dacccfb08c8be934e215e4dcaeda6.png

图11

对于该结果需要我们将输出结果除以2^(a+ b),a为用以表示小数的位宽数,本文中为11,b为FFT点数的2次幂幂值,本文为6,因此对于每一个Modelsim的输出结果都需要除以2^17,这里实部-15302/2^17=-0.1167,虚部-23234/2^17=-0.1773。

从表6中数据可以看出,IFFT 核执行的运算和MATLAB的运算结果十分接近,验证成功。

8、FFT运算

与IFFT运算类似,配置不用更改只需将第5小节程序中,s_axis_config_tdata端口配置改为8’d1即可,其他无需变动。

94b304fa6e5fb9125617bb8ad65c41e9.jpeg

想要了解FPGA吗?这里有实例分享,ZYNQ设计,关注我们的公众号,探索

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值