Vivado中的FFT IP核使用(含代码)

本文介绍了Vidado中FFT IP核的使用,具体内容为:调用IP核>>配置界面介绍>>IP核端口介绍>>MATLAB生成测试数据>>测试verilogHDL>>TestBench仿真>>结果验证>>FFT运算。

1、调用IP核

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

2、配置界面介绍

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

第1页:Configuration

图1

表1 Configuration界面介绍

Configuration

Number of Channels

变换通道,可以选择多通道,实现多帧数据同时进行FFT运算

Transform Length

FFT变换长度,如果选择了最下面的‘run time configurable transform length’,则该参数是FFT变化的最大长度,一般不选

Architecture

Configuration

Target Clock

Frequency(MHz)

配置系统时钟

Target Data

Throughput(MSPS)

数据吞吐量

Architecture

Choice

Automatically Select

自动选择所需要的,FFT变化架构

Pipelined,

Streaming I/O

流水线结构,处理速度最快,但消耗资源多(只要将数据组成长序列输入,核就会按照FFT点数连续输出变换结果)

Radix-4, Burst I/O

基4 I/O突发结构

Radix-2, Burst I/O

基2 I/O突发结构

Radix-2 lite, Burst I/O

基2 lite I/O突发结构

Run Time Configuration Transform Length

该选项可以在FFT变换中通过设置s_axis_config_tdata中

NFFT字段的长度来改变FFT变化的长度

第2页:Implementation

图2

表2 Implementation界面介绍

Implementation

Data Format

Fixed Point

定点全精度

Floating Point

定点缩减位宽

Scaling Options

Block Floating Point

不管输入的格式如何,FFT变化内部都采用浮点,会根据每一级的数据情况自动缩放。 这个模式的输入输出位宽一致,便于调用

Scaled

在s_axis_config_data中会有相应的字段配置缩放因子.每一级别包含2个stage ,2个bit 表示一级缩放,一般0-3可选,如果log(NFFT)不是2的倍数,则最高一级的缩放只能在0-1之间选取

Unscaled

不用担心变化过程中会出现溢出,但是输入是32bit的话,输出是64bit

Rounding Modes

Convergent

Rounding

采用四舍五入输出数据(会使用更多的位宽来实现,增加转换速度和使用资源)

Trancation

采用截位输出数据

Precision Options

Input Data Width

输入数据的位宽

Phase Factor Width

输入数据相位因子宽度

Control Signals

ACLKEN

时钟使能

ARESETn(active low)

复位信号

Output Ordering Options

输出位序选项

Output Ordering

Bit/Digit Reversed

Order

逆序输出

Natural Order

顺序输出

Optional Output Fields

XK_INDEX

勾选表示给出输出索引

OVFLO

变换中溢出的指示信号

Throttle Sheme

Non Real Time

输出不遵循真实时间

Real Time

输出遵循真实时间

第3页:Detailed Implementation

图3

表3 Detailed Implementation

Detailed Implementation

Memory Options

存储器选项

Data

Block RAM

突发I/O架构:块RAM或分布式RAM均可用于数据和相位因子存储;

流水线流I/O:数据部分存储在块RAM部分存储在分布式RAM上,因此这两项都无法配置

Distributed RAM

Phase Factors

Block RAM

Distributed RAM

Number of stages using Block RAM

for Data and Phase Factors

选择块RAM的级数,

一般用不到默认即可

Reorder Buffer

Block RAM

流水线模式可选则配置,一般默认即可

Distributed RAM

Optimize Block RAM Count Using Hybrid

Memories

一种优化存储的方式,一般不用

Optimize Options

优化选项

Complex Multipliers

Use 3-multiplier structure

使用更多的DSP切片优化运算

Use 4-multiplier structure

比“3-multiplier”运算更快,

使用资源更多

Use CLB Logic

一般用在性能要求较低的设计中

Butterfly Arithmetic

Use CLB Logic

切片逻辑构造蝶形运算

Use XtremeDsp Slices

使用DSP切片的蝶形运算,强制使用DSP切片内部的加/减法器

3、IP核端口配置

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

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

Configuration

Number of Channels

1

Transform Length

64

Architecture

Configuration

Target Clock Frequency(MHz)

50

Target Data Throughput(MSPS)

50

Target

Pipelined, Streaming I/O

Implementation

Data Format

Fixed Point

Scaling Options

Scaled

Rounding Modes

Truncation

Precision Options

Input Data Width

16

Phase Factor Width

16

Control Signals

ACLKEN

勾选

Output Ordering Options

Output Ordering

Natural Order

Optional Output Fields

XK_INDEX

Throttle Sheme

Non Real Time

Detailed Implementation

该界面配置全部默认

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

图4 64点IFFT核端口图

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

图5

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

图6

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

表5 例化原语介绍

端口名称

IN/OUT

勾选

aclk

IN

系统时钟

aclken

IN

时钟使能

s_axis_config_tdata

IN

控制输入模式,进行fft/ifft以及衰减因子的设置,FWD_INV = 1做 fft,FWD_INV = 0做ifft

s_axis_config_tvalid

IN

拉高两个时钟周期之后,将端口s_axis_data_tvalid和s_axis_data_tready拉高

s_axis_config_tready

OUT

s_axis_config_tvalid拉高两个时钟周期后,该口给1输出;若干个时钟周期后,自动归零

s_axis_data_tdata

IN

将数据输入进行FFT运算结果

s_axis_data_tvalid

IN

当s_axis_data_tready高电平后,将s_axis_data_tvalid拉高L个周期,输入L个数据进行fft;L是FFT的点数

s_axis_data_tready

OUT

aresetn拉高两个时钟周期后,该口给1输出;此时ip核初始化完成,可进行数据输入

s_axis_data_tlast

IN

数据输入完毕后拉高,停止数据输入

m_axis_data_tdata

OUT

高位为虚部,低位为实部

m_axis_data_tuser

OUT

输出fft的地址值,输出值*fs/L为对应频点

m_axis_data_tvalid

OUT

当ifft结果输出时拉高,输出L个点的数据后拉低

m_axis_data_tready

IN

需保持高电平,保证FFT单元处在计算模式,并且能够输出结算结果

m_axis_data_tlast

OUT

当fft结果输出到最后一个结果时拉高,

紧接着下一个时钟就拉低

event_frame_started

OUT

当出现新的计算时给出

event_tlast_unexpected

OUT

当数据输入完毕而s_axis_data_tlast,没有拉高时给出

event_tlast_missing

OUT

但数据输入完毕之前s_axis_data_tlast,就拉高时给出

event_status_channel_halt

OUT

当核不能将数据正常输出给状态通道时给出

event_data_in_channel_halt

OUT

但核当前请求数据而数据没输入时给出

event_data_out_channel_halt

OUT

当核不能将数据正常输出给数据通道时给出

需要说明的是,需要配置的端口有,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 输出结果如下图:

图10

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

表6数据验证

MATLAB

序号

Modelsim

序号

0.0791+0.791i

1

0.0788+0.0788i

1

0.1504-0.1122i

2

0.1503-0.1122i

2

-0.0336+0.2315i

3

-0.0337+0.2314i

3

-0.1444-0.0422i

31

-0.1444-0.0422i

31

-0.1533+0.1128i

32

-0.1553+0.1128i

32

-0.0395+0.0791i

33

-0.0395+0.0790i

33

0.0992-0.1690i

62

0.0992-0.1689i

62

-0.1036+0.0314i

63

-0.1036+0.0314i

63

-0.1168-0.1773i

64

-0.1167-0.1773i

64

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

图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即可,其他无需变动。

参考:

https://blog.csdn.net/duanchangrenhit/article/details/109639454

版权声明:本文为博主作者:RICE研究笔记原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/RICEresearchNOTE/article/details/129098607

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2024年4月1日
下一篇 2024年4月1日

相关推荐