0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Vivado Xilinx FFT IP核v9.0使用说明

FPGA设计论坛 来源:FPGA设计论坛 2025-01-08 11:33 次阅读

一 傅里叶变换FFT

想必大家对傅里叶老人家都不陌生了,网上也有这方面的很多资料。通过FFT将时域信号转换到频域,从而对一些在时域上难以分析的信号在频域上进行处理。在这里,我们需要注意采样频率、FFT采样点数这两个参数

根据奈奎斯特采样定理,采样频率需大于信号频率的两倍;

FFT采样点数,代表对信号在频域的采样数;

采样频率Fs和采样点数N决定了信号的频域分辨力,即分辨力=Fs/N,即N越大,频域分辨力越好,反之频域分辨力越差。

二 Xilinx FFT v9.0

1.输入输出端口

6d37a12c-ccac-11ef-9310-92fbcf53809c.png


如上图所示,左侧的端口均为输入端口,右侧端口均为输出端口,其中,S_AXIS_DATA为输入数据端口,我们要进行FFT的数据需要通过这根线输入给IP核;S_AXIS_CONFIG为输入配置端口,这个信号包含了对数据进行FFT还是IFFT、缩放因子、FFT变换点数等信息;FFT变换后的数据从M_AXIS_DATA端口输出。这些端口的具体功能可以参见pg109手册。

2.Vivado中IP核的配置

打开Vivado软件,我的版本是2018.04

6d4d59d6-ccac-11ef-9310-92fbcf53809c.png


找到FFT IP核后,双击,弹出如下对话框:

6d766844-ccac-11ef-9310-92fbcf53809c.png


第二页implementation

6d93946e-ccac-11ef-9310-92fbcf53809c.png


第三页

6db45b68-ccac-11ef-9310-92fbcf53809c.png


配置完成后,我们可以点击左侧的implementation detail选项卡,看到IP核的具体信息:

6ddb2fd6-ccac-11ef-9310-92fbcf53809c.png


其中包含了S_AXIS_DATA_TDATA、S_AXIS_CONFIG_TDATA以及M_AXIS_DATA_TDATA的数据格式,我们需要加以关注:

S_AXIS_DATA_TDATA:共32位,其中低16位为输入数据的实部,高16位为输入数据的虚部(但在实际使用中,高16位才是实部,低16位是虚部,如果有大神明白是咋回事儿,欢迎留言)

S_AXIS_CONFIG_TDATA:最低位第0位,决定对数据进行FFT还是IFFT,置1时FFT,清零时IIFT,由于要进行补零操作,因此在最终写入S_AXIS_CONFIG_TDATA时,除了最低位以外,还要再补七个零,补到8位

M_AXIS_DATA_TDATA:48位数据输出,低24位为实部,高24位为虚部

3.软件仿真

IP核配置完成后,下面开始编写我们的TestBench文件。
我们通过matlab对F(t) = 200 + 100cos(2pi10t) + 100cos(2pi30t)这个信号以Fs = 100HZ进行采样,采样点数N = 128,采样完成后,将数据转换为16位二进制,并存入txt文件中。matlab程序如下:

clear

Fs=100;                         %采样率1ns一个点
%t=0:1/Fs:63/Fs;                 %数据时长:64个采样周期
N = 128;
n = 1:N;
t = n/Fs;
% 生成测试信号
f1 = 10;                   %
f2 = 30;                     %
s1 = cos(2*pi*f1*t);    
s2 = cos(2*pi*f2*t);
signalN = 2 + s1 + s2 ;
data_before_fft = 100*signalN;  %系数放大100倍


fp = fopen('D:ynq_Coredata_before_fft.txt','w');
for i = 1:N
   if(data_before_fft(i)>=0)
       temp= dec2bin(data_before_fft(i),16);
   else
       temp= dec2bin(data_before_fft(i)+2^16+1, 16);
   end
    for j=1:16
        fprintf(fp,'%s',temp(j));
    end
    fprintf(fp,'
');
end
fclose(fp);

y = fft(data_before_fft,N);
y = abs(y);
f = n*Fs/N;
plot(f,y);

程序执行结束后,我们可以看到在指定目录下新建了一个txt文件,内容如下所示:

6e07da40-ccac-11ef-9310-92fbcf53809c.png


由于我们在配置IP核的时候配置了数据位宽为16位,因此我们存入的数据也要设置为16位的。采样点数N=128,因此一共有128个这样的数据。

得到采样数据后,在vivado中新建一个sim文件:

6e1a33c0-ccac-11ef-9310-92fbcf53809c.png

TB文件代码如下:

`timescale 1ns / 1ps
module FFT_test2();

reg clk;
reg rst_n;
reg signed [15:0] Time_data_I[127:0];
reg data_finish_flag;

wire              fft_s_config_tready;

reg signed [31:0] fft_s_data_tdata;
reg               fft_s_data_tvalid;
wire              fft_s_data_tready;
reg               fft_s_data_tlast;

wire signed [47:0] fft_m_data_tdata;
wire signed [7:0]  fft_m_data_tuser;
wire               fft_m_data_tvalid;
reg                fft_m_data_tready;
wire               fft_m_data_tlast;

wire          fft_event_frame_started;
wire          fft_event_tlast_unexpected;
wire          fft_event_tlast_missing;
wire          fft_event_status_channel_halt;
wire          fft_event_data_in_channel_halt;
wire          fft_event_data_out_channel_halt;

reg [7:0]     count;

reg signed [23:0] fft_i_out;
reg signed [23:0] fft_q_out;
reg signed [47:0] fft_abs;

initial begin
    clk = 1'b1;
    rst_n = 1'b0;
    fft_m_data_tready = 1'b1;
    $readmemb("D:/Zynq_Core/data_before_fft.txt",Time_data_I);
end

always #5 clk = ~clk;

always @ (posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        fft_s_data_tvalid <= 1'b0;
        fft_s_data_tdata  <= 32'd0;
        fft_s_data_tlast  <= 1'b0;
        data_finish_flag  <= 1'b0;
        count <= 8'd0;
        rst_n = 1'b1;
    end
    else if (fft_s_data_tready) begin 
        if(count == 8'd127) begin
            fft_s_data_tvalid <= 1'b1;
            fft_s_data_tlast  <= 1'b1;
            fft_s_data_tdata  <= {Time_data_I[count],16'd0};
            count <= 8'd0;
            data_finish_flag <= 1'b1;
        end
        else begin
            fft_s_data_tvalid <= 1'b1;
            fft_s_data_tlast  <= 1'b0;
            fft_s_data_tdata  <= {Time_data_I[count],16'd0};   
            count <= count + 1'b1;
        end
    end
    else begin
        fft_s_data_tvalid <= 1'b0;
        fft_s_data_tlast  <= 1'b0;
        fft_s_data_tdata <= fft_s_data_tdata;
    end
end

always @ (posedge clk) begin
    if(fft_m_data_tvalid) begin
        fft_i_out <= fft_m_data_tdata[23:0];
        fft_q_out <= fft_m_data_tdata[47:24];
    end
end

always @ (posedge clk) begin
    fft_abs <= $signed(fft_i_out)* $signed(fft_i_out)+ $signed(fft_q_out)* $signed(fft_q_out);
end


//fft ip核例化
xfft_0 u_fft(
    .aclk(clk),                                                // 时钟信号(input)
    .aresetn(rst_n),                                           // 复位信号,低有效(input)
    .s_axis_config_tdata(8'd1),                                // ip核设置参数内容,为1时做FFT运算,为0时做IFFT运算(input)
    .s_axis_config_tvalid(1'b1),                               // ip核配置输入有效,可直接设置为1(input)
    .s_axis_config_tready(fft_s_config_tready),                // output wire s_axis_config_tready
    //作为接收时域数据时是从设备
    .s_axis_data_tdata(fft_s_data_tdata),                      // 把时域信号往FFT IP核传输的数据通道,[31:16]为虚部,[15:0]为实部(input,主->从)
    .s_axis_data_tvalid(fft_s_data_tvalid),                    // 表示主设备正在驱动一个有效的传输(input,主->从)
    .s_axis_data_tready(fft_s_data_tready),                    // 表示从设备已经准备好接收一次数据传输(output,从->主),当tvalid和tready同时为高时,启动数据传输
    .s_axis_data_tlast(fft_s_data_tlast),                      // 主设备向从设备发送传输结束信号(input,主->从,拉高为结束)
    //作为发送频谱数据时是主设备
    .m_axis_data_tdata(fft_m_data_tdata),                      // FFT输出的频谱数据,[47:24]对应的是虚部数据,[23:0]对应的是实部数据(output,主->从)。
    .m_axis_data_tuser(fft_m_data_tuser),                      // 输出频谱的索引(output,主->从),该值*fs/N即为对应频点;
    .m_axis_data_tvalid(fft_m_data_tvalid),                    // 表示主设备正在驱动一个有效的传输(output,主->从)
    .m_axis_data_tready(fft_m_data_tready),                    // 表示从设备已经准备好接收一次数据传输(input,从->主),当tvalid和tready同时为高时,启动数据传输
    .m_axis_data_tlast(fft_m_data_tlast),                      // 主设备向从设备发送传输结束信号(output,主->从,拉高为结束)
    //其他输出数据
    .event_frame_started(fft_event_frame_started),                  // output wire event_frame_started
    .event_tlast_unexpected(fft_event_tlast_unexpected),            // output wire event_tlast_unexpected
    .event_tlast_missing(fft_event_tlast_missing),                  // output wire event_tlast_missing
    .event_status_channel_halt(fft_event_status_channel_halt),      // output wire event_status_channel_halt
    .event_data_in_channel_halt(fft_event_data_in_channel_halt),    // output wire event_data_in_channel_halt
    .event_data_out_channel_halt(fft_event_data_out_channel_halt)   // output wire event_data_out_channel_halt
  );
    
    
endmodule

由于我们设置程序一直保持正向FFT模式,因此将s_axis_config_tdata始终写入1即可。

同时我们还要注意文件读入函数readmemb(),这一函数是以二进制格式读入数据,而readmemh()是以16进制读入数据,大家不要搞混了。我就是用readmemh()弄了半天,结果数据一个也不对,找了半天才发现那是h不是b…[cry][cry][cry]

4.仿真分析

运行仿真后,时序图如下所示:

6e28c796-ccac-11ef-9310-92fbcf53809c.png


如图所示,首先判断fft_s_data_tready信号是否为高电平,即IP核是否准备好了接收数据,当检测到该信号有效后,将fft_s_data_tvalid信号拉高,准备向IP核写入数据,并开启count计数。在fft_s_data_tvalid有效期间内,读出指定txt文件中的数据,并在低16位进行补零处理后,按顺序写入到fft_s_data_tdata信号线中。当count计数到127,即最后一个数据时,将fft_s_data_tlast信号拉高,代表数据写入完成。

可以看到,在数据写入完成后(fft_s_data_tlast出现脉冲),fft_s_data_tready变为低电平,则代表IP核此时变为忙状态,不能再继续写入数据。

6e4a66e4-ccac-11ef-9310-92fbcf53809c.png


延时一段时间后,fft_m_data_tvalid变为高电平,代表fft_m_data_tdata中将输出有效数据,即128点FFT的计算结果。结果的实部和虚部分别见上图中的fft_q_out和fft_i_out。将IP核的计算结果与matlab的计算结果相对比,发现实部数据基本正确,虚部数据略有偏差。

6e60c0ec-ccac-11ef-9310-92fbcf53809c.png


通过对IP核的计算结果进行分析,发现数据在第0个、第14个和34个数据的位置出现峰值,对应0HZ、10HZ和30HZ,正代表着原始信号中的这三个频率分量,因此FFT IP核计算结果正确无误。

同时,从仿真中还可以看出,当FFT计算结果输出完成后,信号fft_m_data_tlast变为高电平,代表数据输出结束,并在延时一小段时间后,fft_s_data_tready重新变为低电平,代表IP核重新进入到空闲状态。可以进行对IP核下一组数据的输入。

原文链接:

https://gitcode.csdn.net/6628ae7c9c80ea0d22719dd0.html

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Xilinx
    +关注

    关注

    71

    文章

    2170

    浏览量

    121906
  • IP
    IP
    +关注

    关注

    5

    文章

    1715

    浏览量

    149802
  • FFT
    FFT
    +关注

    关注

    15

    文章

    437

    浏览量

    59483
  • Vivado
    +关注

    关注

    19

    文章

    815

    浏览量

    66788

原文标题:Vivado Xilinx FFT IP核v9.0 使用详解

文章出处:【微信号:gh_9d70b445f494,微信公众号:FPGA设计论坛】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    关于altera FFT IP matlab 仿真问题请教

    本帖最后由 Laputa_fly 于 2013-11-23 13:46 编辑 用quartus9.0调用了altera FFT IP  生成了modisim 和 matlab 的仿真文件。用modelsim 仿真有结果。
    发表于 11-23 13:43

    xilinx FPGA的FFT IP的调用

    有没有大神可以提供xilinx FPGA的FFT IP的调用的verilog 的参考程序,最近在学习FFT
    发表于 12-25 17:05

    DSP Builder V9.0软件下载

    DSP Builder V9.0安装程序,使用前请先安装 Quartus II V9.0软件。点击下载
    发表于 04-22 16:37

    基于FPGA的FFT和IFFT IP应用实例

    基于FPGA的FFT和IFFT IP应用实例AT7_Xilinx开发板(USB3.0+LVDS)资料共享腾讯链接:https://share.weiyun.com/5GQyKKc百度
    发表于 08-10 14:30

    玩转Zynq连载48——[ex67] Vivado FFT和IFFT IP应用实例

    VivadoFFT IP生成的数据。 2 Matlab产生测试数据,绘制cos时域和频域波形使用projectzstar_ex67matlab文件夹下的Matlab源码
    发表于 01-07 09:33

    fft核心v9.0的数据表如何实现FFT核心

    亲爱的大家我已经通过fft核心v9.0的数据表。我想实现FFT核心,但我没有在顶层模块(VHDL)中找到任何FFT核心的例子。如果有人建议我提供一些文档或示例,我将感激不尽。这是我第一
    发表于 05-21 08:19

    Vivadoxilinx_courdic IP怎么使用

    Vivadoxilinx_courdic IP(求exp指数函数)使用
    发表于 03-03 07:35

    基于Xilinx_FPGA_IPFFT算法的设计与实现

    利用FPGA的IP设计和实现FFT算法
    发表于 05-24 14:14 37次下载

    FFT变换的IP的源代码

    Xilinx FPGA工程例子源码:FFT变换的IP的源代码
    发表于 06-07 11:44 10次下载

    Xilinx Vivado的使用详细介绍(3):使用IP

    IPIP Core) Vivado中有很多IP核可以直接使用,例如数学运算(乘法器、除法器、浮点运算器等)、信号处理(
    发表于 02-08 13:08 2376次阅读
    <b class='flag-5'>Xilinx</b> <b class='flag-5'>Vivado</b>的使用详细介绍(3):使用<b class='flag-5'>IP</b><b class='flag-5'>核</b>

    FFT的分析和Xilinx FFT的介绍

    -FS/2~FS/2 提高采样频率则可提高量程,却会(在转换长度不变的情况下)降低分辨率。此时需要通过增加转换长度的方式增加分辨率,但却会增加处理时间。 相关ipFFT V7.1
    发表于 02-08 15:15 1348次阅读

    vivado调用IP详细介绍

    大家好,又到了每日学习的时间了,今天咱们来聊一聊vivado 调用IP。 首先咱们来了解一下vivadoIP
    的头像 发表于 05-28 11:42 3.7w次阅读

    ACDSee v9.0 Build 50

    ACDSee v9.0 Build 50(大工电源技术在线作业1)-ACDSee v9.0 Build 50;看图软件,感谢原创作者!
    发表于 09-27 15:10 13次下载
    ACDSee <b class='flag-5'>v9.0</b> Build 50

    如何进行FFT IP配置和设计

    Xilinx Vivado设计套件中提供的FFT IP为例,简要说明如何进行FFT
    的头像 发表于 07-22 10:21 2484次阅读

    VivadoFFT IP的使用教程

    本文介绍了Vidado中FFT IP的使用,具体内容为:调用IP>>配置界面介绍>>IP
    的头像 发表于 11-06 09:51 1402次阅读
    <b class='flag-5'>Vivado</b>中<b class='flag-5'>FFT</b> <b class='flag-5'>IP</b><b class='flag-5'>核</b>的使用教程