vivado FFT IP 学习及仿真笔记

目录

1.FFT的简介

[2. FFT IP核 驱动逻辑](#2. FFT IP核 驱动逻辑)

全局控制信号

aclk

aclk(可选)

aresetn(可选)

配置通道

s_axis_config_tdata

s_axis_config_tvalid

s_axis_config_tready

输入数据通道

s_axis_data_tdata[N-1:0]

s_axis_data_tvalid

s_axis_data_tready

s_axis_data_tlast

数据输出通道

m_axis_data_tuser

事件通道和配置通道

[3.FFT 仿真](#3.FFT 仿真)

[3.1FFT IP核配置](#3.1FFT IP核配置)

[configuration 界面](#configuration 界面)

Implementation界面

[Detailed Implementation 界面](#Detailed Implementation 界面)

[3.2 仿真](#3.2 仿真)

matlab

verilog

4.参考资料


1.FFT的简介

FFT是DFT的快速计算方法,其计算的结果和DFT的结果一致。离散傅里叶变换(DFT):对于长度为的信号,将其看成周期为的周期信号(这种做法是合理,结果会有误差,但不影响分析),其公式为:

正变换:

这里和常规的傅里叶变换相比少了系数,所以一般在matlab中做了FFT之后,会将结果除以点数N。如下:

Matlab 复制代码
%% fft
data = 1:1024 ;
data_fft = fft(data)./N; % 因为data是1024个点,所以一次的长度是1024
N_fft = length(data);
P_fft = abs(Y(1:N_fft/2)); %单边谱
plot(f_fft, 20*log10(P_fft));
xlabel('频率 (Hz)');
ylabel('幅度 (dB)');
title('FFT频谱分析 ');
grid on;

%fft的结果是0~pi,再从-pi到0,也就是先低频到最高频(0~fs/2),然后高频到低频(-fs/2~0),
%而stft的结果是(-fs/2~fs/2),在FFT IP中是对应fft的结果:0~pi,再从-pi到0。

逆变换:

其物理含义为:将信号分解为一系列简单的复指数序列(,...,)。

2. FFT IP核 驱动逻辑

FFT IP核使用很简单,只需要懂AXI4-Stream 协议格式即可。其通过 TREADY 和 TVALID 信号实现上下游模块之间的握手,其传输模型如下所示:

这个协议很好理解,ACLK是时钟驱动,TVALID和TDATA对应,当TVALID拉高时表示此时的数据是有效的;但是需要等待接受方拉高TREADY,即对方表示可以接受你的数据才可以一直输出有效数据,因为只有这样子对方才能接受到。

其引脚如下所示:

FFT IP核一共有五个通道,分别是配置通道,输入数据通道,输出数据通道,状态通道,事件通道。我们常用也是必须要选的是配置通道,数据输入通道,数据输出通道,事件通道(事件通道不一定要用,但他自带这个信号接口),如下:

全局控制信号

aclk

驱动时钟,FFT的时钟源。

aclk(可选)

时钟使能信号,如果勾选此引脚,将其置低电平可使IP核暂停当前运行状态,此时芯片内部所有逻辑功能均停止。将aclken引脚置高电平则可使IP核继续执行运算。该引脚还可降低芯片的最高运行频率。

aresetn(可选)

同步复位,将该引脚驱动至低电平会导致所有输出引脚、内部计数器和状态变量重置为其初始值。当上电时,无论IP核是否配置为aresetn,所有待处理的负载流程、变换计算及卸载流程均会停止并重新初始化。

配置通道

s_axis_config_tdata

这个使用设置FFT的配置信息的,包括CP_LEN、FWD/INV、 NFFT 和SCALE_SCH。常用的是后三个。

CP_LEN:位宽是,如下图所示。

循环前缀是将信号的尾部复制到头部,形成一个保护间隔,目的是抵抗多径干扰,保持子载波正交性。举个例子:

原始FFT输出 (N=8点):[S0, S1, S2, S3, S4, S5, S6, S7]

添加CP_LEN=2的循环前缀后:

S6, S7, \| S0, S1, S2, S3, S4, S5, S6, S7

↑________|

复制尾部2个样本

我目前还未在工程中使用过。

FWD/INV是标志做FFT正变换还是逆变换,1:正变换,0:逆变换;

NFFT是FFT的点数,点数 = 2^NFFT。如果没有勾选Run Time Configurable Transform Length则是固定点数,不能动态调整,点数是已经固定的,也就是代码里面不用设置这个参数。未勾选时,配置数据形式是这样子的:

勾选之后可以动态的选择做FFT的点数:

SCALE_SCH是放缩因子,位宽是2bit*或者2bit*。因为DFT前面没有1/N,所以每次都会放大N倍。缩放因子的目的是防止在FFT计算过程中数据溢出,同时尽量保持数据的精度。每个阶段的缩放调度由两位二进制位指定,首阶段的缩放值由最低两位(LSB)决定。缩放值可设为3、2、1或0,代表需要移位的位数。然后阶段数是根据或者决定的,比如以N=1024的四进制突发I/O为例,其阶段数是5,缩放调度方案可为[1 0 2 3 2](按从末到首阶段的顺序排列)。当N=128时,二进制突发I/O或二进制轻量版突发I/O的缩放方案可为[1 1 1 1 0 1 2](按从末到首阶段的顺序排列)。

参数设置的规律,基2运算的每一级最多放大两倍(N=2),但是会累积,从第一阶段累积到最后一个阶段,总的所谓位数最大是N;基4运算的每一级最多放大两倍(N=4),但是会累积,从第一阶段累积到最后一个阶段,总的所谓位数最大也是N。

s_axis_config_tvalid

输入数据有效标志,由发送方给出,也就是我们在写代码的时候将有效数据输入的时候需要手动拉高该信号。

s_axis_config_tready

s_axis_config_tready为高电平时表示接收方可以接收数据。

输入数据通道

s_axis_data_tdata[N-1:0]

输入数据,由实部和虚部组成 ,实部和虚部的位宽可以自己设置,配置完之后,可以在配置界面中看到其组成方式,如下:

多通道组织方式: FFT IP核可以选多通道来进行FFT运算,其实就是多个通道的数据合起来输入,然后在FFT IP 核分开同时计算,计算出结果之后合并输出。只能计算相同点数的。数据组织形式如下:

**填充组织方式:**当实部或者虚部的位宽不是8或8的倍数时,需要把实部单独填充成8或8的倍数,虚部也要单独填充成8或8的倍数。例子如下:

反正写代码的时候注意一下组织的形式就可以了。

s_axis_data_tvalid

输入数据有效标志,由发送方给出,也就是我们在写代码的时候将有效数据输入的时候需要手动拉高该信号。如下:

仿真输入数据的时候可以一直拉高。这个和ram的写入一样,拉高的同一周期的数据是有效的。如下:

s_axis_data_tready

接收方表示可以接收的信号,发送发需要等待这个信号才可以切换数据输入。拉高的同一周期的数据已经输入FFT中,所以检测到信号拉高后就可以切换数据了。如下:

s_axis_data_tlast

用来指示这一帧的最后一个数据,在最后输入的同一个周期拉高该信号。如下:

数据输出通道

m_axis_data_tdata 、m_axis_data_tvalid、m_axis_data_tready、m_axis_data_tlast 这四个信号的原理和数据输入通道的是一样的。 所以数据输出是检测m_axis_data_tvalid信号,有效就存储起来,而一般用不到指示一帧最后的一个数据m_axis_data_tlast。

m_axis_data_tuser

m_axis_data_tuser携带XK_INDEX、BLK_EXP和 OVFLO信息。

XK_INDEX:位宽为,是输出数据的下标:从0开始。

BLK_EXP:位宽为8,块指数(无符号2的补码),应用的缩放量(即未缩放输出值被下移的位数)。核心每个 FFT 通道都有一个单独的BLK_EXP字段。仅在使用块浮点时可用。(目前我还未使用过)。

OVFLO:位宽为1,算术溢出指示器(单比特,高电平有效),当数据帧中的任何值溢出时,结果卸载期间 OVFLO 信号为高电平。 OVFLO 信号在新数据帧开始时复位。核心每个 FFT 通道都有一个独立的 OVFLO 字段。此端口是可选的,仅适用于缩放算术或单精度浮点输入输出。(目前我还未使用过)。

事件通道和配置通道

这两个 通道目前还未使用过,所以就不介绍了。

3.FFT 仿真

3.1FFT IP核配置

configuration 界面

最上面的"Component Name"一栏设置该 IP 元件的名称,这里我们保持默认命名,当然也可以命名为其 它方便自己一眼看出其功能的名称。

在第一个"Configuration"选项卡中,各参数含义如下:

(1)"Number of Channels"用来选择 fft 运算的通道数,可选范围为 1~12 通道。这里需要注意的是 多通道配置只有在 Burst I/O 才能选。本次实验我们将通道数设为 1。

(2)"Transform Length"用来选择 fft 运算的采样点个数,这里根据所选架构的不同,采样点的范围也不一样。当架构选为 Pipelined Streaming I/O、 Radix-2 Burst I/O 和 Radix-2 Lite Burst I/O 时,其可选范 围为 8~65536 通道。当架构选为 Radix-4 Burst I/O 时,其可选范围为 64~65536 通道。这里需要注意的是采 样点个数只能是 2 的次幂。本次实验我们将采样点个数设为 1024。

(3)"Target Clock Frequency"用来选择 fft 运算的时钟,可选范围为 1MHz~1000 MHz。本次实验 将时钟设置为 100 MHz。

(4)、"Target Data Throughput"用来选择 fft 运算的数据速率,可选范围为 1MSPS~1000 MSPS。这 个选项只有在 Automatically Select 模式下才可配置。
( 5 )、" Architecture Choice "用来选择 fft 运算的架构,总共有 5 种架构选择,分别是 Automatically Select(自动选择模式)、 Pipelined Streaming I/O (并行流水线架构)、 Radix-4 Burst I/O (基 4 型 I/O 突发 架构)、Radix-2 Burst I/O (基 2 型 I/O 突发架构)和 Radix-2 Lite Burst I/O (基 2 型 I/O 简化突发架构)。
下面对这 5 种架构做个简单介绍:
Automatically Select(自动选择模式):自动选择所需要的 FFT 变化架构;
Pipelined Streaming I/O(并行流水线架构):这个架构下允许数据连续处理;
Radix-4 Burst I/O(基 4 型 I/O 突发架构):这个架构下 采用迭代方法分别加载和处理数据,它比 并行 流水线架构下 消耗资源更少,但变换时间更长;
Radix-2 Burst I/O(基 2 型 I/O 突发架构):这个架构下 采用 Radix-4 Burst I/O 相同的迭代方法,但蝶形 运算更小。这意味着它比 Radix-4 Burst I/O 消耗资源更少,但转换时间比 Radix-4 Burst I/O 更长;
Radix-2 Lite Burst I/O(基 2 型 I/O 简化突发架构):这个架构是 Radix-2 Burst I/O 的一种简化,这种架 构采用分时复用的方法来进行更小的蝶型运算,但代价是 变换时间比 Radix-2 Burst I/O 更长。本次实验采用 Radix-2 Burst I/O 架构。

(6)、"Run Time Configurable Transform Length"用来选择采样点个数是否动态配置,当勾选了这个选项后,上面的 Transform Length 选项将变为最大位数MAX,然后可以在代码中配置NFFT的点数,设置范围在[8,MAX]之间。本次实验我们不勾选该选项。

Implementation界面


(1 )" Data Format "用来选择 fft 运算的输入输出数据格式,这个选项有 2 种数据格式可选,分别是
Fixed-Point (定点数据格式)和 Floating-Point (浮点数据格式)。 本次实验采用 Fixed-Point (定点数据格式)。
Fixed-Point(定点数据格式):对于定点输入,输入数据为 N 个复数向量,表示双路 bx-bit 二进制补码, 即实部和虚部都为 bx-bit 二进制补码, bx = 8~34 ,相应地,相位因子 bw 也为 8~34bit 位宽;
Floating-Point(浮点数据格式):对于单精度浮点输入,输入 N 个复数向量,表示双路 32-bit 浮点数 据,相位因子为 24 或者 25bit 定点数。这里有个地方大家注意下,当 fft 运算的通道数为多通道时,浮点数 据格式是不可用的。
( 2 )" Scaling Options "用来选择 fft 运算的缩放格式,这个选项有 3 种缩放格式可选,分别是 Unscaled (全精度不缩放算法)、Block Floating-Point (块浮点)和 Scaled ( 定点缩减位宽)。 本次实验采用Scaled( 定点缩减位宽) 。
Unscaled(全精度不缩放算法):选择这种模式不用担心变化过程中会出现溢出,因为 ip 会将所有的进位都拉到了输出端口。假设输入是 32bit 的话,那么输出是 64bit 。
Scaled( 定点缩减位宽):在这种模式下, fft 运算的缩放因子由用户自己来配置,在 s_axis_config_data 中会有相应的字段来配置缩放因子;
Block Floating-Point(块浮点):在这种模式下,不管输入的格式如何, FFT 变化内部都采用浮点,会 根据每一级的的数据情况自动缩放,使数据不出现溢出的情况。
( 3 )" Rounding Modes "用来选择 fft 运算输出数据的舍入模式,这种模式是对输出数据的低位进行 截断。这个选项有 2 种格式可选,分别是 Truncation (截断模式)和 Convergent Rounding (收敛舍入模式)。 本次实验采用 Truncation(截断模式)。
Truncation(截断模式):这种模式是直接对累加器位宽与输出位宽之差进行舍弃;
Convergent Rounding(收敛舍入模式):这种模式是向最近的奇数舍入或者最近的偶数舍入。当一个数 字的小数部分正好等于二分之一时,如果数字是奇数,收敛四舍五入就会向上舍入,如果数字是偶数就会向下舍入。
( 4 )" Input Data Width "用来选择 fft 运算输入数据的位宽,可选范围为 8bit~34bit 。当数据格式为
Floating-Point 模式时,输入数据宽度固定为 32 位,相位因子宽度可设置为 24 或 25 位。本次实验的输入数 据位宽为 16 位( ip 的输入数据为有符号数)。
注意这个位宽是实部或者虚部的位宽,而不是加起来。比如这里设置 16 ,那总的输入进来的长度就是 虚部拼接实部共 32bits 。
( 5 )" Phase Factor Width "用来选择 fft 运算输入相位因子的位宽,可选范围为 8bit~34bit 。通常情
况下将输入相位因子的位宽与输入数据的位宽设成一样,本次实验设为 16 。
( 6 )" Control Signals "用来选择 fft 运算是否需要时钟使能和同步复位。如果将 2 个选项同时勾选, 同步复位将覆盖时钟使能。如果不选择某个选项,则可以节省一些逻辑资源,并且可以实现更高的时钟频 率。这里需要注意的是同步复位的有效长度至少要保持 2 个驱动时钟,否则可能会导致复位不成功。本次实 验勾选同步复位,不勾选时钟使能。
( 7 )" Output Odering "用来选择 fft 运算输出数据的模式,这个选项有 2 种模式可选,分别是 Bit/Digit Reversed Order( 反序输出 )和 Natural Order (顺序输出),本次实验选择顺序输出。
Bit/Digit Reversed Order( 反序输出 ):按照变化后的顺序直接输出,是倒序输出,需要自己后续处理
Natural Order(顺序输出): FFT 变化后的输出已经调整了顺序,按照 xk_index 自然顺序列出变化结 果。
( 8 )" Cyclic Perfix Insertion "用来选择 fft 运算是否要循环前缀插入,该选项只在 Natural Order(顺序输出)的模式下可选,本次实验不勾选。
( 9 )" Optional Output Fields "用来选择 fft 的输出字段,该选项下有 2 种模式可选,分别是 XK_INDEX (输出结果索引)和 OVFLO (溢出指示信号)。
XK_INDEX(输出结果索引): FFT 变幻的结果索引,在 m_axis_data_user 中有相应的字段;
OVFLO(溢出指示信号):变换中溢出的指示信号,对应的信号名为 event_fft_overflow 。
( 10 )" Throttle Schemes "用来选择 fft 运算是否采用节流法案,该选项下有 2 个模式可选,分别是
Real Time (实时模式)和 Non-Real Time (非实时模式)。本次实验我们选择非实时模式。
Real Time(实时模式):实时模式通常提供更小、更快的设计方案,但对用户需要输入数据的时序有严 格的限制;
Non-Real Time(非实时模式): 非实时模式没有严格的时序限制,但设计所需的资源更多,运算的速度更慢。

Detailed Implementation 界面

(1)"Memory Options"用来选择 fft 运算的输入数据和输入相位因子存储在哪种 ram,ram 有 2 种 可选,分别是 Block RAM(块 RAM)和 Distributed RAM(分布式 RAM)。在 Burst I/O 模式下块 RAM 和 分布式 RAM 都可以选择;Pipelined Streaming I/O 模式下是同时使用块 RAM 和分布式 RAM。

(2)"Reorder Buffer":该选项只有在运算的架构为 Pipelined Streaming I/O 模式下可选,表示重新 排序缓冲区使用哪种 RAM。
( 3 )" Optimize Block Ram Count Using Hy brid Memories ":该选项表示如果重新排序缓存区的大小 大于一个块 RAM ,则由块 RAM 和分布式 RAM 来混合构造重新排序缓冲区,其中大部分数据存储在块 RAM 中,剩下的一些存储在分布式 RAM 中 。
( 4 )" Complex Multipliers ":这个选项表示复杂的乘法用什么来构造,该选项有 3 种构造方式,分
别是 Use CLB logic (使用 CLB 资源)、 Use 3-multiplier structure (使用 3 次乘法结构)和 Use 4-multiplier structure(使用 4 次乘法结构)。
Use CLB logic:所有的乘法器都使用 CLB logic 构造。这选项适用于性能要求不高的程序或者只使用少 量 DSP 的程序 ;
Use 3-multiplier structure:所有复数乘数都使用 3 个实乘和 5 个加减来构造,其中乘法使用 DSP 片,加减法使用片逻辑。这种结构减少了 DSP 的片数,但多使用了一些片逻辑;
Use 4-multiplier structure :所有复数乘数都使用 4 个实乘和 2 个加减来构造,乘法和加减法都用 DSP 来实现。这种结构下可以产生最高的时钟性能,但代价是需要更多的 DSP 。
( 5 )" Butterfly Arithmetic ":这个选项表示蝶形运算用什么来构造,该选项有 2 种构造方式,分别
是 Use CLB logic (使用 CLB 资源)和 Use XtremeDSP Slices (使用 XtremeDSP 资源)。
Use CLB logic:所有的蝶型运算都采用 CLB 资源;
Use XtremeDSP Slices:该选项强制使用 DSP 中的加法器 / 减法器实现所有蝶形运算。

3.2 仿真

matlab

先进行matlab的FFT运算,输入数据1~1024,然后做1024个点的FFT,代码如下:

复制代码
% 用 matlab 生成数据文件,该信号包含 3,37,200 三个频点:
clc,clear,close all

%% 生成 testbench $readmemh 需要读取的 FFT IP 测试数据
N = 1024;
DataWidth = 16;

t = 0:N-1;
%data = 2*cos(2*pi/N*3*t) + sin(2*pi/N*37*t) + cos(2*pi/N*200*t+pi/3);
data = 1:1024 ;
data = data./max(abs(data))*0.99;   %归一化
data = round(data*2^(DataWidth-1)); %量化

fp = fopen('./fft_test_data.txt','w');  %在当前目录下保存文件。
for i=1:N %有符号数
    if data(i)>=0
        s = dec2hex(data(i),ceil(DataWidth/4));
    else
        s = dec2hex(data(i)+2^DataWidth,ceil(DataWidth/4));
    end
    fprintf(fp,s);
    fprintf(fp,'\n');
end
clear i s

fclose(fp);

%% fft
data_fft = fft(data)./N; % 因为data是1024个点,所以一次的长度是1024
data_real = real(data_fft) ;
figure('color','w')
subplot(3,1,1)
plot(data)
subplot(3,1,2)
plot(real(data_fft))
subplot(3,1,3)
plot(imag(data_fft))
%如果想看频率可以用下面的方法,上面的是单纯看每个点的值
% 方法1:使用FFT进行频谱分析
figure('Position', [100, 100, 1200, 800]);
N_fft = length(data);
fs = N ;
f_fft = (0:N_fft/2-1) * fs / N_fft;
Y = fft(data(1:N_fft), N_fft);
P_fft = abs(Y(1:N_fft/2)) / (N_fft/2);
plot(f_fft, 20*log10(P_fft));
xlabel('频率 (Hz)');
ylabel('幅度 (dB)');
title('FFT频谱分析 ');
grid on;

结果如下:

幅值:

|------------|---------|---------|---------|---------|
| X(1~1024) | 4 | 201 | 825 | 1022 |
| Y | 8190.53 | 2047.64 | 2047.64 | 8190.53 |

相位:

|------------|----------|--------|---------|---------|
| X(1~1024) | 38 | 201 | 825 | 988 |
| Y | -4095.26 | 3546.6 | -3546.6 | 4095.26 |

verilog

根据配置的IP,将同样的数据进行仿真:

代码如下:

复制代码
//测试FFT IP核
`timescale 1ns/100ps
`default_nettype none
module FFT_IP_tb();

reg		clk_100M	= 1'b1;
reg		rst_n		= 1'b1;

always #5 begin
	clk_100M	<= ~clk_100M;
end

//--------------------------FFT IP------------------------------------
//config
reg		[23:0]	s_axis_config_tdata		= {3'b0, 20'h55555, 1'b1};//这个格式在Implementation Details的数据格式中有说明
reg				s_axis_config_tvalid	= 1'b0;
wire			s_axis_config_tready;

//data in
reg		[31:0]	s_axis_data_tdata		= 32'd0;
reg				s_axis_data_tvalid		= 1'b0;
wire			s_axis_data_tready;
reg				s_axis_data_tlast		= 1'b0;

//data out
wire	[31:0]	m_axis_data_tdata;
wire	[9:0]	m_axis_data_tuser;
wire			m_axis_data_tvalid;
reg				m_axis_data_tready		= 1'b0;
wire			m_axis_data_tlast;

//events
wire			event_frame_started;
wire			event_tlast_unexpected;
wire			event_tlast_missing;
wire			event_status_channel_halt;
wire			event_data_in_channel_halt;
wire			event_data_out_channel_halt;


//----------------------------Ctrl-------------------------------------
reg		signed	[15:0]	fft_test_data	[0:1023];

reg		[9:0]	cnt		= 10'd0;
always @(posedge clk_100M or negedge rst_n) begin
	if(~rst_n) begin
		cnt		<= 10'd0;
	end
	else begin
		if(s_axis_data_tvalid & s_axis_data_tready) begin
			cnt		<= cnt + 1'b1;
		end
		else begin
			cnt		<= cnt;
		end
	end
end

//KN_real/img
reg		signed	[15:0]	KN_Real;
reg		signed	[15:0]	KN_Img;
always @(*) begin
	//KN_Real		<= fft_test_data[cnt];
	//KN_Img		<= 16'sd0;
	KN_Real		<= cnt;
	KN_Img		<= 16'sd0;
end
//s_axis_data_tdata
always @(*) begin
	s_axis_data_tdata	<= {KN_Img, KN_Real};
end

//s_axis_data_tvalid
always @(posedge clk_100M or negedge rst_n) begin
	if(~rst_n) begin
		s_axis_data_tvalid	<= 1'b0;
	end
	else begin
		s_axis_data_tvalid	<= 1'b1;
	end
end

//s_axis_data_tlast
always @(*) begin
	s_axis_data_tlast = (cnt==10'd1023)? 1'b1 : 1'b0;
end

//m_axis_data_tready  //表示可以一直接收
always @(posedge clk_100M or negedge rst_n) begin
	if(~rst_n) begin
		m_axis_data_tready	<= 1'b0;
	end
	else begin
		m_axis_data_tready	<= 1'b1;
	end
end

//XK_Real
reg		signed	[15:0]	XK_Real;
integer i;
always @(*) begin
	for(i=0; i<=15; i=i+1) begin
		XK_Real[i]		<= m_axis_data_tdata[i];//[15-i];//
	end
end

//XK_Img
reg		signed	[15:0]	XK_Img;
always @(*) begin
	for(i=0; i<=15; i=i+1) begin
		XK_Img[i]		<= m_axis_data_tdata[16+i];//[31-i];//
	end
end

wire			[9:0]	XK_INDEX; //下标从0开始。
assign  XK_INDEX = m_axis_data_tuser ;
initial begin
    $readmemh("D:/FPGA/FPGA_ETH_RTL/pro/FFT/matlab/fft_test_data.txt", fft_test_data);
	rst_n	= 1'b0;
	#200;
	rst_n	= 1'b1;

	#100000;
	$stop;
end
//FFT IP  每个变量的具体位宽在Implementation Details有说明  这里的s和m是相对于FFT这个IP核来说的,IP核是主,
xfft_0 FFT_inst(
	.aclk							(clk_100M), // input wire aclk //"Target Clock Frequency" fft 运算的时钟,
	.aresetn						(rst_n),// input wire aresetn //同步复位  至少维持两个周期

	//Config
	.s_axis_config_tdata			(s_axis_config_tdata),// input  缩放计划+顺序/逆序+循环前缀长度+运算长度
	.s_axis_config_tvalid			(s_axis_config_tvalid),//input 配置通道的TVALID信号,由外部主机输出,表示当前数据有效
	.s_axis_config_tready			(s_axis_config_tready),//output

	//DATA INPUT
	.s_axis_data_tdata				(s_axis_data_tdata),  //input //虚部+实部  虚部在前  //在Implementation Details中有说明
	.s_axis_data_tvalid				(s_axis_data_tvalid),//input
	.s_axis_data_tready				(s_axis_data_tready),//output
	.s_axis_data_tlast				(s_axis_data_tlast),//input

	//DATA OUTPUT
	.m_axis_data_tdata				(m_axis_data_tdata),//output
	.m_axis_data_tuser				(m_axis_data_tuser),//output //表示该通道的数据分布,输出数据的索引值+块缩放指数+输出数据的缩放系数  索引值在前(但有时候只有索引)
	.m_axis_data_tvalid				(m_axis_data_tvalid),//output
	.m_axis_data_tready				(m_axis_data_tready),//input
	.m_axis_data_tlast				(m_axis_data_tlast),//output

	//event signal
	.event_frame_started			(event_frame_started),			//output 
	.event_tlast_unexpected			(event_tlast_unexpected),       //output 
	.event_tlast_missing			(event_tlast_missing),          //output 
	.event_status_channel_halt		(event_status_channel_halt),    //output 
	.event_data_in_channel_halt		(event_data_in_channel_halt),   //output 
	.event_data_out_channel_halt	(event_data_out_channel_halt)   //output 
);
endmodule

仿真结果如下:

幅值:

|------------|-------|-------|-------|-------|
| X(0~1023) | 3 | 200 | 824 | 1021 |
| Y | 8187 | 2046 | 2047 | 8188 |
| 误差 | -3.53 | -1.64 | -0.64 | -1.47 |

相位:

|------------|-------|------|-------|-------|
| X(0~1023) | 37 | 200 | 824 | 987 |
| Y | -4096 | 3546 | -3548 | 4093 |
| 误差 | -0.74 | -0.6 | -1.4 | -1.74 |

自然序的结果与matlab仅相差+-3以内。

以上就是FFT IP核的基本使用方法。需要注意在什么时候输入数据,什么时候停止数据的输入。一般只要s_axis_data_tready为高电平,即接收方能接受就可以输入数据,需要注意的是FFT IP核的s_axis_data_tready为高电平的时间大于NFFT个周期,如下图所示,但是输入的数据是可以存到FFT中的,下一帧的数据还是对的。

4.参考资料

(1).正点原子的资料------【正点原子】Kintex7之FPGA开发指南V1.1.pdf

(2)师兄的文章:vivado FFT IP Core_vivado fft ip核-CSDN博客

(3)FFT IP核的手册:pg109-xfft-en-us-9.1.pdf

以上就是本次笔记的记录。

相关推荐
brave and determined4 天前
可编程逻辑器件学习(day36):从沙粒到智能核心:芯片设计、制造与封装的万字全景解析
fpga开发·制造·verilog·fpga·芯片设计·硬件设计·芯片制造
云雾J视界5 天前
AI芯片设计实战:用Verilog高级综合技术优化神经网络加速器功耗与性能
深度学习·神经网络·verilog·nvidia·ai芯片·卷积加速器
brave and determined6 天前
可编程逻辑器件学习(day34):半导体编年史:从法拉第的意外发现到塑造现代文明的硅基浪潮
人工智能·深度学习·fpga开发·verilog·fpga·设计规范·嵌入式设计
stay_cloud7 天前
《Verilog语言与FPGA实现》课程实验
verilog·fpga·数码管
IC_Brother7 天前
数字IC经典电路(6)—Ring Oscillator(环形振荡器)与工艺角监控
verilog·数字ic·dc综合
brave and determined7 天前
可编程逻辑器件学习(day30):数字电路设计中的流水线技术:原理、实现与优化
学习·fpga开发·verilog·fpga·数字电路·硬件设计·嵌入式设计
brave and determined8 天前
可编程逻辑器件学习(day29):Verilog HDL可综合代码设计规范与实践指南
深度学习·fpga开发·verilog·fpga·设计规范·硬件编程·嵌入式设计
i道i16 天前
Verilog 利用伪随机,时序,按键消抖等,实现一个(打地鼠)游戏
游戏·fpga开发·verilog
9527华安19 天前
FPGA纯verilog实现 2.5G UDP协议栈,基于1G/2.5G Ethernet PCS/PMA or SGMII,提供14套工程源码和技术支持
5g·fpga开发·udp·ethernet·verilog·sgmii·2.5g udp