关于xilinx的FFTIP的使用和仿真

工具:vivado2018.3,modelsim10.6d

场景:在进行数据进行频谱分析的时候,使用FPGA来完成FFT的计算可以加快数据的计算速度。

下面使用仿真完成DDS产生的数据的FFT以及IFFT。原始数据使用DDSIP产生,通过IP产生的波形数据直接输入到FFT进行傅里叶正变换。然后再使用FFT对数据进行IFFT傅里叶逆变换还原波形数据。过程中完成了fftshift(将零频分量搬移到频谱中心),以及使用cordic计算平方根的过程。

FFT端口说明

端口名称

方向

描述

aclk

I

时钟

aresetn

I

复位

s_axis_config_tvalid

I

配置有效

s_axis_config_tready

O

配置准备好

s_axis_config_tdata

I

针对配置通道的TDATA。携带配置信息: CP_LEN、FWD/INV、NFFT和SCALE_SCH。关于FWD/INV为FFTIP的方式,1为FFT,0为IFFT。当选择FFT点数可配置时NFFT为点数。SCALE_SCH为缩放计划,以确保在计算过程中不溢出。对于不同的IO架构有不同的规则。

s_axis_data_tdata

I

输入数据

s_axis_data_tvalid                

I

数据有效

s_axis_data_tready

O

数据准备好

s_axis_data_tlast

I

输入的一帧最后一个数据

m_axis_data_tvalid

O

输出数据有效

m_axis_data_tready

I

输出数据准备好

m_axis_data_tdata

O

输出数据

m_axis_data_tuser

O

输出数据状态参数。包含XK_INDEX, OVFLO, and BLK_EXP.

XK_INDEX输出数据索引

OVFLO溢出标志
BLK_EXP块指数,字段中出现的值表示在转换过程中数据被缩放的比特总数。例如,如果BLK_EXP的值为00101 = 5,这意味着相关的输出数据(XK_RE,XK_IM)被缩放为5位(向右移5位),或者换句话说,被除以32,以充分利用输出数据路径的可用动态范围而不会溢出。

m_axis_data_tlast

O

输出的最后一个数据。

m_axis_status_tvalid

O

状态有效

m_axis_status_tready

I

状态准备好

m_axis_status_tdata

O

状态数据。包含每一帧的状态休息。

event_frame_started

O

事件帧开始

event_tlast_unexpected

O

当核心在不是帧中最后一个的数据样本上看到s_axis_data_tlast高时有效

event_tlast_missing

O

当一帧的最后一个数据样本上的s_axis_data_tlast为低时断言。

event_fft_overflow

O

当正在从数据输出通道卸载的数据样本中出现溢出时断言。仅在溢出是一个有效的选项时才会出现。

event_data_in_channel_halt

O

当核心从数据输入通道请求数据而没有数据可用时断言。

event_data_out_channel_halt

O

当核心从数据输入通道请求数据而没有数据可用时断言。

event_status_in_channel_halt

O

当核心试图将数据写入状态通道而无法这样做时,将被断言。仅在非实时模式下出现。

FFT IP的配置界面

Channels:从1到12中选择通道数。三种Burst I/O架构均可使用多通道操作。对于浮点格式,通道必须为1。

Transform Length: 选择一次处理所需点的大小。

The Pipelined Streaming I/O:运行连续处理。

Radix-4,Radix-2,Radix-2 Lite Burst I/O。几种不同的实现方式,延迟依次增大,资源依次减少。

Run time configurable Transform Length:允许运行的过程中改变点数。勾选此后注意,s_axis_config_tdata的字段的意义。

DataFormat:选择输入和输出数据样本是否为定点格式,或在IEEE-754单精度(32位)浮点格式中。浮点格式不是当核心处于多通道配置时可用。

Scaling Options:

Scaling:用户自定义缩放格式。注意s_axis_config_tdata的字段需要配置每个阶段的缩放信息。

Block Floating-Point:由核心来判断所需的缩放程度,以实现对可用动态范围的最佳利用,并以块指数的形式报告缩放因子。注意m_axis_data_tuser字段的块指数报告。

Output ordering:自然顺序和反转顺序。这里使用自然顺序。

Optional Output Fields:XK_INDEX,输出数据索引。

资源消耗设置界面。

关于matlab仿真,产生1MHZ的正弦波余弦波信号,采样率为100MHZ。共计1024个点。对其进行FFT。

matlab仿真程序

% 生成正弦波
fc = 1e6;               % 频率
fs = 100e6;             % 采样率
t1 = 0:1/fs:1e-3;       % 时间序列,1微秒
t = t1(1:1024);         %RW需要取整数计算出的频率是真实

sin_wave = sin(2 * pi * fc * t);
cos_wave = cos(2 * pi * fc * t);

% 复数
plural_wave = cos_wave+ 1i*sin_wave;

% 加噪声
data =awgn(cos_wave,100) ;
% data =awgn(plural_wave,100) ;

% 绘制原始正弦波数据
figure;
subplot(1,1,1);
plot(t*1e9, imag(plural_wave));
title('原始正弦波');
xlabel('时间 (ns)');
ylabel('幅值');


%%做FT变化,算平均功率谱,并画谱输出
FFT_data = data; N = length(FFT_data); w = blackman(N);Fs =100e6;
% Sf_I_Q_wave=fftshift(fft((FFT_data).*w',N)*2.381);
% w = gausswin(N);%高斯窗函数,窗长度为N
gauss_data = fft((FFT_data).*w',N)*2.396;%%做FFT变换,加窗并还原窗系数
Sf_I_Q_wave=fftshift(gauss_data);
Sf_I_Q_wave_dBm =(abs(Sf_I_Q_wave));
% Sf_I_Q_wave_dBm =20*log10(1/N*abs(Sf_I_Q_wave));
X_freq=Fs.*(-N/2:N/2-1)/N;figure(2);plot(X_freq,Sf_I_Q_wave_dBm);title('plural_wave原始数据普');

对实信号余弦波进行傅里叶变换,频谱图如下。

对复信号进行进行傅里叶变换频谱。

在逻辑中我们使用DDSIP来产生我们需要的波形数据。

DDS IP配置界面

可以看到我需要控制DDS的控制字来生成不同频率的波形数据,输出数据的格式为高16位为正弦,低16位为余弦。

输出频率计算公式。

其中X为频率控制字,Fs采样率,即系统时钟。N为多少位的控制字。要输出1MHZ的波形信号的控制字为X=655。

输出波形正好为一个周期1000ns。即1MHZ。

1024点FFT实信号输入。

FFTSHIFT频谱搬移模块

对于FFTSHIFT模块我们打开matlab帮助后可以发现,搬移的效果就是以频谱中心左右两端谱线互换。

ABS求平方根模块

求复数的模,定义为

复数\left | a+b*i \right |\sqrt{a^{2}+b^{2}}

在逻辑中我们使用cordic来计算平方根。

cordicIP配置如下所示

模块仿真

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/08/12 14:14:51
// Design Name: 
// Module Name: vtf_fft_test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module vtf_fft_test;
//fft
//input
wire               [31:0] s_axis_data_tdata    ; 
wire                      s_axis_data_tvalid   ; 
wire                      s_axis_data_tready   ; 
wire                      s_axis_data_tlast    ; 
//output
wire               [31:0] m_axis_data_tdata    ; 
wire                      m_axis_data_tvalid   ; 
wire                      m_axis_data_tready   ; 
wire                      m_axis_data_tlast    ; 
wire               [23:0] m_axis_data_tuser    ; 

//dds
wire                      m_dds_tvalid         ; 
wire               [31:0] m_dds_tdata          ; 

//system signal
reg                       clk                  ; 
reg                       rst_n                ; 
reg                       data_gen             ; 
reg                       data_flog            ; 
reg                       douta_vld            ; 
reg                [15:0] cnt                  ; 

//fftshift
wire               [31:0] fftshift_data        ; // 
wire                      fftshift_data_valid  ; // 
wire                [9:0] fftshift_cnt         ; // 

//abs

wire               [15:0] abs_data             ; // (output)
wire                      abs_data_valid       ; // (output)
//system signal

//
assign  s_axis_data_tdata   = douta_vld ? m_dds_tdata : 32'h0;//给复信号
//assign  s_axis_data_tdata   = douta_vld ? {16'd0,m_dds_tdata[15:0]} : 32'h0;//实信号
assign  s_axis_data_tvalid  = douta_vld;
assign  s_axis_data_tlast   = (cnt == 16'd1023 );

assign  m_axis_data_tready  = 1'b1;

//FFT后数据
//取实部
wire               [15:0] f_imag               ; 
wire               [15:0] f_real               ; 
wire               [31:0] f_abs                ; 

assign  f_imag = m_axis_data_tdata[31:16];
assign  f_real = m_axis_data_tdata[15:0];
assign  f_abs  = f_imag + f_real;



//=========================================================
dds_compiler_0 u_dds (
    .aclk                         (clk                         ), // input wire aclk
    .s_axis_config_tvalid         (1'b1                         ), // input wire s_axis_config_tvalid
    .s_axis_config_tdata          (16'd655                      ), // input wire [15 : 0] s_axis_config_tdata
    .m_axis_data_tvalid           (m_dds_tvalid                 ), // output wire m_axis_data_tvalid
    .m_axis_data_tdata            (m_dds_tdata                  ), // output wire [31 : 0] m_axis_data_tdata
    .m_axis_phase_tvalid          (                             ), // output wire m_axis_phase_tvalid
    .m_axis_phase_tdata           (                             )// output wire [15 : 0] m_axis_phase_tdata
);

//=========================================================
xfft_0 u_fft (
    .aclk                         ( clk                         ), // input wire aclk
    .aresetn                      ( rst_n                       ), // input wire aresetn
    .s_axis_config_tdata          (8'd1                         ), // input wire [7 : 0] s_axis_config_tdata
    .s_axis_config_tvalid         (1'b1                         ), // input wire s_axis_config_tvalid
    .s_axis_config_tready         (                             ), // output wire s_axis_config_tready
    .s_axis_data_tdata            (s_axis_data_tdata            ), // input wire [31 : 0] s_axis_data_tdata
    .s_axis_data_tvalid           (s_axis_data_tvalid           ), // input wire s_axis_data_tvalid
    .s_axis_data_tready           (s_axis_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_axis_data_tdata            ), // output wire [31 : 0] m_axis_data_tdata
    .m_axis_data_tuser            (m_axis_data_tuser            ), // output wire [23 : 0] m_axis_data_tuser
    .m_axis_data_tvalid           (m_axis_data_tvalid           ), // output wire m_axis_data_tvalid
    .m_axis_data_tready           (m_axis_data_tready           ), // input wire m_axis_data_tready
    .m_axis_data_tlast            (m_axis_data_tlast            ), // output wire m_axis_data_tlast
    .m_axis_status_tdata          (                             ), // output wire [7 : 0] m_axis_status_tdata
    .m_axis_status_tvalid         (                             ), // output wire m_axis_status_tvalid
    .m_axis_status_tready         (1'b1                         ), // input wire m_axis_status_tready
    .event_frame_started          (                             ), // output wire event_frame_started
    .event_tlast_unexpected       (                             ), // output wire event_tlast_unexpected
    .event_tlast_missing          (                             ), // output wire event_tlast_missing
    .event_status_channel_halt    (                             ), // output wire event_status_channel_halt
    .event_data_in_channel_halt   (                             ), // output wire event_data_in_channel_halt
    .event_data_out_channel_halt  (                             )// output wire event_data_out_channel_halt
);

//==========================================================
fft_shift u_fft_shift(
//
    .fft_data                     (m_axis_data_tdata            ), // (input ) 
    .fft_cnt                      (m_axis_data_tuser[9:0]       ), // (input ) 
    .fft_last                     (m_axis_data_tlast            ), // (input ) 
    .fft_data_valid               (m_axis_data_tvalid           ), // (input ) 
    .fftshift_data                (fftshift_data                ), // (output) 
    .fftshift_data_valid          (fftshift_data_valid          ), // (output) 
    .fftshift_cnt                 (fftshift_cnt[9:0]            ), // (output) 
//system signal
    .sys_clk                      (clk                          ), // (input ) 
    .rst_n                        (rst_n                        )// (input ) 
    );

//==========================================================
abs_top u_abs_top(
//
    .plural_data                  (fftshift_data[31:0]            ), // (input ) (input )
    .plural_data_valid            (fftshift_data_valid            ), // (input ) (input )
    .abs_data                     (abs_data[15:0]               ), // (output) (output)
    .abs_data_valid               (abs_data_valid               ), // (output) (output)
//system signal
    .clk                          (clk                          ), // (input ) (input )
    .rst_n                        (rst_n                        )  // (input ) (input )
);

//==========================================================
xfft_0 u_ifft (
    .aclk                         ( clk                         ), // input wire aclk
    .aresetn                      ( rst_n                       ), // input wire aresetn
    .s_axis_config_tdata          (8'd1                         ), // input wire [7 : 0] s_axis_config_tdata
    .s_axis_config_tvalid         (1'b1                         ), // input wire s_axis_config_tvalid
    .s_axis_config_tready         (                             ), // output wire s_axis_config_tready
    .s_axis_data_tdata            (m_axis_data_tdata            ), // input wire [31 : 0] s_axis_data_tdata
    .s_axis_data_tvalid           (m_axis_data_tvalid           ), // input wire s_axis_data_tvalid
    .s_axis_data_tready           (m_axis_data_tready           ), // output wire s_axis_data_tready
    .s_axis_data_tlast            (m_axis_data_tlast            ), // input wire s_axis_data_tlast
    .m_axis_data_tdata            (                             ), // output wire [31 : 0] m_axis_data_tdata
    .m_axis_data_tuser            (                             ), // output wire [23 : 0] m_axis_data_tuser
    .m_axis_data_tvalid           (                             ), // output wire m_axis_data_tvalid
    .m_axis_data_tready           (1'b1                         ), // input wire m_axis_data_tready
    .m_axis_data_tlast            (                             ), // output wire m_axis_data_tlast
    .m_axis_status_tdata          (                             ), // output wire [7 : 0] m_axis_status_tdata
    .m_axis_status_tvalid         (                             ), // output wire m_axis_status_tvalid
    .m_axis_status_tready         (1'b1                         ), // input wire m_axis_status_tready
    .event_frame_started          (                             ), // output wire event_frame_started
    .event_tlast_unexpected       (                             ), // output wire event_tlast_unexpected
    .event_tlast_missing          (                             ), // output wire event_tlast_missing
    .event_status_channel_halt    (                             ), // output wire event_status_channel_halt
    .event_data_in_channel_halt   (                             ), // output wire event_data_in_channel_halt
    .event_data_out_channel_halt  (                             )// output wire event_data_out_channel_halt
);

//================================================================
//================================================================
initial
begin
        clk = 0;
        rst_n=0;
        data_gen   =0;
        #100;
        rst_n      =1;
        #1000;
        data_gen   =1;
        #100;
        data_gen   =0;


end

always @ (posedge clk or negedge rst_n)
begin
        if(rst_n == 1'b0)begin         
                data_flog   <= 1'b0;
        end
        else if(data_gen == 1'b1)begin
                data_flog   <= 1'b1;
        end 
        else if(cnt   >= 10'd1022)begin
                data_flog   <= 1'b0;
        end
end

always @ (posedge clk or negedge rst_n)
begin
        if(rst_n == 1'b0)begin         
                douta_vld   <= 1'b0;
        end
        else begin
                douta_vld   <= data_flog;
        end 

end


always @ (posedge clk or negedge rst_n)
begin
        if(rst_n == 1'b0)begin         
                cnt <= 16'd0;
        end
        else if(s_axis_data_tvalid == 1'b1 && s_axis_data_tready == 1'b1)begin
                cnt <= cnt + 1'b1;
        end 
        else begin
                cnt <= cnt;
        end

end

//================================================================
//================================================================

always #5 clk = ~clk;

endmodule

复信号输入。

实信号输入。

逆傅里叶变换结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/870597.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux入门】Linux常见指令

目录 前言 一、Linux基本指令 1.ls指令 2.pwd命令 3.cd 指令 4.touch指令 5.mkdir指令 6.rmdir指令 && rm 指令 7.man指令 8.cp指令 9.mv指令 10.cat 11.date 12.top 13.shutdown-关机 14.重要的几个热键 二、Linux扩展指令 总结 前言 Linux指令是在…

map/set和unordered_map/unordered_set的区别及使用情况

map/set和unordered_map/unordered_set的区别 容器底层数据结构是否有序实现版本复杂度迭代器map/set红黑树有序C98O(logN&#xff09;双向迭代器unordered_map/unordered_set哈希表/散列表无序C11O(1)单向迭代器 unordered_set无序的&#xff08;VS下&#xff09; void uno…

Spring IoCDI(下)—DI的尾声

我们之前学习了控制反转IoC&#xff0c;接下来就开始学习依赖注入DI的细节。 依赖注入是一个过程&#xff0c;是指IoC容器在创建Bean时&#xff0c;去提供运行时所依赖的资源&#xff0c;而资源指的就是对象。我们使用 Autowired 注解&#xff0c;完成依赖注入的操作。简单来说…

【数据结构初阶】二叉树--基本概念

hello&#xff01; 目录 一、树 1.1 树的概念和结构 1.2 树的相关术语 1.3 树的表示 1.4 树形结构实际应用场景 二、二叉树 2.1 概念和结构 2.2 特殊的二叉树 2.2.1 满二叉树 2.2.2 完全二叉树 2.3 二叉树的存储结构 2.3.1 顺序结构 2.3.2 链式结构 …

keil调试程序进入“BEAB BKPT 0xAB“断点处

1&#xff1a;异常现象 发现程序新增加代码的时候&#xff0c;程序会进入 “BEAB BKPT 0xAB” 断点处&#xff0c;无法进入main函数&#xff1b; 2&#xff1a;异常原因 屏蔽新增加的代码&#xff0c;最后发现是复制过来的代码中有 printf() 函数打印日志&#xff0c;但是k…

Windows 环境下 Go 语言使用第三方压缩包 gozstd 的报错处理

该文章主要记录在windows平台用go语言使用gozstd包时&#xff0c;遇到的错误及处理过程&#xff08;踩坑之旅&#xff09;&#xff01; 一、gozstd简介 gozstd是一个针对Zstandard&#xff08;简称Zstd&#xff09;的Go语言包装器&#xff0c;它提供了简单且高效的API&#xf…

赋能基层,融合创新:EasyCVR视频汇聚平台构建平安城市视频共享系统

一、雪亮工程建设的意义 雪亮工程的核心在于通过高清视频监控、环境监测和智能预警等先进技术手段&#xff0c;构建一个高效、智能、安全、便捷的社会安全防控体系。这一工程的建设不仅代表了现代化科技手段在城市治安管理中的应用&#xff0c;更是提升社会安全保障能力、推动…

【Angular18】封装自定义组件

1. 准备组件 2. 创建打包文件夹及部分配置文件 创建 文件夹app-legalentities-root拷贝组件源文件到新的文件夹app-legalentities中创建文件 .npmrc registry发布地址always-authtrue创建文件 ng-package.json {"$schema": "./node_modules/ng-packagr/ng-pac…

自动化解决 reCAPTCHA v2:CapSolver 教程

对于那些经常进行网页爬取的人来说&#xff0c;你是否曾觉得 reCAPTCHA v2 就像是互联网版的过于严格的裁判员&#xff0c;总是在质疑你的真实性&#xff1f;但如果你能够轻松且合规地与这些裁判员达成和解&#xff0c;使你的网络搜索和自动化任务变得更顺畅&#xff0c;那该有…

社交媒体分析:如何利用Facebook的数据提升业务决

在数字化时代&#xff0c;社交媒体已经成为企业战略中不可或缺的一部分。Facebook&#xff0c;作为全球最大的社交平台之一&#xff0c;提供了丰富的数据资源&#xff0c;这些数据不仅能够帮助企业了解市场趋势&#xff0c;还能提升业务决策的精准度。本文将探讨如何有效利用Fa…

共享经济背景下校园、办公闲置物品交易平台-计算机毕设Java|springboot实战项目

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

navicate premium16破解

下载链接&#xff1a;https://pan.baidu.com/s/1BWowOJLYchFcRMgIn-j97A?pwdvmfu 双击安装navicat160_premium_cs_x64.exe&#xff0c;安装完不要打开 然后断网打开NavicatCracker.exe 打开如果报病毒按照下面方法处理&#xff1a; 记得一定要断网&#xff0c;不断网…

安卓相关环境配置

安卓相关环境配置 偶尔更新。。。 JEB&#xff08;动态调试好用&#xff09; JEB动态调试Smali-真机/模拟器&#xff08;详细&#xff0c;新手必看&#xff09; 夜步城 JADX官网&#xff08;静态分析&#xff09; https://github.com/skylot/jadx/releases/tag/v1.5.0 雷…

嵌入式软件--模电基础 DAY 2

强电和弱电&#xff0c;简单一点是以电死人为标准的&#xff0c;交流电36伏特以下&#xff0c;直流电24V以下&#xff0c;为安全电压&#xff0c;是为弱电&#xff0c;反则强电。 市电进入家庭&#xff0c;连接你的电脑&#xff0c;220V的电压为什么没有让你感到危险&#xff…

怎么屏蔽电脑监控软件?企业管理者的智慧选择——精准定位,合理屏蔽,让监控软件成为助力而非障碍!

电脑监控软件在企业管理中扮演着日益重要的角色&#xff0c;它们能够提升工作效率、保障信息安全、预防内部风险。然而&#xff0c;过度或不当使用监控软件也可能引发员工隐私担忧&#xff0c;影响工作积极性和团队氛围。因此&#xff0c;作为企业管理者&#xff0c;如何精准定…

论文创新大杀器!LSTM结合UNet,性能突出,涨点显著

最近&#xff0c;浙大等团队提出了xLSTM-UNet&#xff0c;通过将U-Mamba中的Mamba换成xLSTM&#xff0c;就可以直接提升2D和3D医学图像分割性能&#xff0c;涨点效果显著&#xff01; xLSTM-UNet是一种结合了LSTM和UNet的混合网络模型&#xff0c;这类模型保留了UNet出色的空间…

迭代器失效

一、什么是迭代器失效 迭代器的主要作用就是让算法能够不用关心底层数据结构&#xff0c;其底层实际就是一个指针&#xff0c;或者是对指针进行了封装&#xff0c;比如&#xff1a;vector的迭代器就是原生态指针T* 。因此迭代器失效&#xff0c;实际就是迭代器底层对应指针所指…

数据埋点系列 17| 预测分析和预测模型:用数据洞察未来

在数据驱动的决策时代&#xff0c;预测分析和预测模型已成为组织的重要战略工具。通过分析历史数据&#xff0c;我们可以预测未来趋势&#xff0c;做出更明智的决策。本文将深入探讨预测分析的核心概念、常用技术和实际应用。 目录 1. 预测分析的基础1.1 预测分析的类型 2. 高…

Unity与UE,哪种游戏引擎适合你?

PlayStation vs Xbox&#xff0c;Mario vs Sonic&#xff0c;Unreal vs Unity&#xff1f;无论是游戏主机、角色还是游戏引擎&#xff0c;人们总是热衷于捍卫他们在游戏行业中的偏爱。 专注于游戏引擎&#xff0c;Unity和Unreal Engine&#xff08;简称UE4&#xff09;是目前市…

C++:平衡二叉搜索树之红黑树

一、红黑树的概念 红黑树&#xff0c; 和AVL都是二叉搜索树&#xff0c; 红黑树通过在每个节点上增加一个储存位表示节点的颜色&#xff0c; 可以是RED或者BLACK&#xff0c; 通过任何一条从根到叶子的路径上各个节点着色方式的限制&#xff0c;红黑树能够确保没有一条路径会比…