数字信号处理-11-FPGA FFT IP应用实例

news2024/11/22 20:03:35

前言

本文根据FFT相关原理进行设计构建工程,仿造前文的工程构建的混频功能的工程,设计工程显示该混频信号的功率谱,然后进行仿真分析。

FFT仿真与分析

本文不再针对FFT的原理进行过多赘述,提供一份简单的matlab仿真代码。根据仿真简述下FFT的相关使用注意事项。

clc;clear all;
fs=50e6;%采样率
N=1024;%采样点数
t=[0:N-1]/fs; %时间序列
f1=3e6;%频点1 3MHZ
f2=4e6;%频点2 4MHZ
s1=sin(2*pi*f1*t);%信号1
s2=sin(2*pi*f2*t);%信号2
mixsign=s1.*s2;%混频
fftsign=fft(mixsign);%求fft
fftabs=abs(fftsign);%取模运算
plot(fftabs);

代码设计,模拟生成了两个不同频率的信号3MHz和4MHz,模拟采样了1024,将两个信号进行混频后则产生了7MHz和1MHz的信号。然后通过FFT函数,取模运算,求得FFT的幅度谱,然后进行显示输出。

1024点的FFT结果

频率分辨率

频率分辨率是FFT的一个重要的参数,横坐标每一个单位的频率精度等于 fs/N,N 是 FFT 的点数。即求出该仿真情况下的频率分辨率如下:
50 M H z 1024   = 48828.125 H z \frac {50MHz}{1024}\ = 48828.125Hz 102450MHz =48828.125Hz
将仿真输出的图片放大,并标注坐标,可见,第一个峰值的横坐标为21,第二个峰值的横坐标为144,计算可知,第一个峰值对应的频率为1.0254MHz,第二个峰值对应的频率为1.0254MHz,7.0313MHz。

FFT结果

可见实际FFT出来后的结果,和仿真设置的相差了一点,但是基本上是在设置的附近,这是因为频率分辨率不够,48828.125Hz的分辨率不能恰好对应到设置的1MHz和7MHz。

如果想恰好得到1MHz和7MHz的FFT的处理结果,或者想进一步减小误差,则需要进行相干采样,频率分辨率恰好是所求的频率的倍数。

关于频谱泄露

频率分辨率欠佳后,就会造成频谱泄露。

当信号X(t)的频率f0是fs/N的整数倍时,这说明在处理长度NT内有信号的K个整周期。这时由X(t)构成的以NT为周期的周期性信号是连续的。当信号X(t)的频率f0不是fs/N的整数倍时,则在NT的处理长度内,就不是恰好为信号周期的整数倍,有X(t)以NT为周期进行周期延拓所得到的周期性信号就出现了不连续点,造成了频谱分量从其正常频谱扩展开来,就这样形成了频谱泄露现象。

整周期截断,不会造成频谱泄露;非整周期截断,必然造成频谱泄露。

前面提到的相干采样,正式因为进行了整数周期的截断才使得频谱不进行泄露,并且FFT后的信号尖峰也恰好能对应我们设置的预期的频率。

使用FFT IP进行工程设计

可以将DDS应用实例的工程进行复制备份,然后添加相关 IP,进行工程适配。

实现功率谱逻辑

FFT 的原理是可以通过实部和虚部的数据恢复出周期信号的相位和幅值; 假如 a 是实部数据, b 是虚部数据, a+bj 是复数;对应的模运算是=sqrt(a2+b2),FFT处理后取模运算中的开更号在FPGA中实现比较麻烦,可以利用自带的cordic IP去处理,这里可以简化一下求FFT处理后的功率谱,也即(a2+b2)。

因此在调用FFT函数后,将输出的数据的实部虚部进行平方再相加即可得到FFT处理后的功率谱。

添加FFT IP

在配置界面可配置FFT的通道个数,傅里叶变换的长度,该结构的时钟,以及采用的算法架构。改变通道个数为N后,对应的数据位宽会变成一个通道的N倍。这里设置 IP 核 1024 点 FFT, 采样率 50MHz, 选择基 2 突发结构。

FFT IP配置

数据格式选择定点数类型,放缩设置为块浮点模式, 输出 FFT 结果选择顺序输出。

FFT ip配置二

在侧边栏可以看到IP的接口状态,以及具体实现架构的相关细节,从实现细节界面可看到,在CONFIG接口处的数据位,有一个FWD_INV的配置参数,该参数是配置正变换还是反变换,因为 FFT 的计算正变换和反变换可以用一套算法实现。 这里 FWD_INV=1 为正变换, 为 0 是反变换。

这里看到 CHAN_0_XN_IM_0(31:16)是复数的虚部数据,并且使用的是 fix16_15 定点数, 意思是最高位为符号位, 小数部分有15位。CHAN_0_XN_RE_0(15:0)是复数的实部数据;这里的FFT混频信号只提供了实部的信号,因此,在信号连接时,只需要把低 16 位赋值为乘法器输出值, 而高 16 位赋值为 0即可。

FFT侧边栏

从侧边栏还可以对FFT进行延时分析,从图中可知,该架构的FFT变化需要146.820us才能完成。

延时分析

添加DDS IP

添加DDS IP,配置输出两路信号分别为3MHz和4MHz。匹配FFT的IP采样频率的50MHz,修改SFDR为45。

DDS ip配置

配置完成基本信息配置下一页,基本保持默认即可,这里只想查看波形,所以相位输出就关闭。

配置界面二

DDS的IP核多通道之间是分时复用的,所以在细节实现配置界面最好使能通道ID以供进行区别单个通道的信号波形。其余可以保持默认。

使能通道ID

配置输出频率为3MHz和4MHz。其余保持默认,点击OK,完成配置。

配置输出频率

修改乘法器IP

将乘法器适配当前的数据位宽,并保存设置。该乘法器用于实现混频乘法。

乘法器配置

调用第二个乘法器,配置输入位宽为16位,输出为32位,有符号类型。该乘法器用于实现FFT处理后的功率谱逻辑。

image-20221128132020847

编写.V文件

根据上面的逻辑结构,例化IP、编写代码依次实现DDS的信号产生、混频、FFT处理、以及功率谱运算逻辑。

`timescale 1ns / 1ps
module top(
    input clk
    );

    wire          m_axis_data_tvalid_ch3;
    wire [7 : 0]  m_axis_data_tdata_ch3;
    wire [0 : 0]  m_axis_data_tuser_ch3;

    //多通道测试
    dds_compiler_1 multi_ch_dds(
    .aclk(clk),                                // input wire aclk
    .m_axis_data_tvalid(m_axis_data_tvalid_ch3),    // output wire m_axis_data_tvalid
    .m_axis_data_tdata(m_axis_data_tdata_ch3),      // output wire [7 : 0] m_axis_data_tdata
    .m_axis_data_tuser(m_axis_data_tuser_ch3)
    );

    reg [7 : 0] data3MHz;
    reg [7 : 0] data4MHz;
    always @(posedge clk) begin
        case(m_axis_data_tuser_ch3)
            0:data3MHz<=m_axis_data_tdata_ch3;
            1:data4MHz<=m_axis_data_tdata_ch3;
        endcase
     end

    //混频测试
    wire [15 : 0]  mixer_singal;
    mult_gen_0 mult_mixer (
        .CLK(clk),  // input wire CLK
        .A(data3MHz),      // input wire [7 : 0] A
        .B(data4MHz),      // input wire [7 : 0] B
        .P(mixer_singal)      // output wire [15 : 0] P
    );

    reg div_clk=0;
    always @(posedge clk ) begin
        div_clk<=!div_clk;
    end

    wire mixer_singal_tready;
    wire [31 : 0] after_fft_data;
    wire [7 : 0] m_axis_data_tuser;
    wire m_axis_data_tvalid;

    xfft_0 uut_fft(
    .aclk(div_clk),                                                // input wire aclk
    .s_axis_config_tdata('d1),                  // input wire [7 : 0] s_axis_config_tdata
    .s_axis_config_tvalid(1),                // input wire s_axis_config_tvalid
    .s_axis_config_tready(),                // output wire s_axis_config_tready
    .s_axis_data_tdata({16'd0,mixer_singal}),                      // input wire [31 : 0] s_axis_data_tdata
    .s_axis_data_tvalid(1),                    // input wire s_axis_data_tvalid
    .s_axis_data_tready(mixer_singal_tready),                    // output wire s_axis_data_tready
    .s_axis_data_tlast(0),                      // input wire s_axis_data_tlast
    .m_axis_data_tdata(after_fft_data),                      // output wire [31 : 0] m_axis_data_tdata
    .m_axis_data_tuser(m_axis_data_tuser),                      // output wire [7 : 0] m_axis_data_tuser
    .m_axis_data_tvalid(m_axis_data_tvalid),                    // output wire m_axis_data_tvalid
    .m_axis_data_tready(1),                    // 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),                // 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
    );
    
    wire [31 : 0] fft_re_2;
    mult_gen_1 mult_re (
        .CLK(div_clk),  // input wire CLK
        .A(after_fft_data[15:0]),      // input wire [15 : 0] A
        .B(after_fft_data[15:0]),      // input wire [15 : 0] B
        .P(fft_re_2)      // output wire [31 : 0] P
    );

    wire [31 : 0] fft_im_2;
    mult_gen_1 mult_im (
        .CLK(div_clk),  // input wire CLK
        .A(after_fft_data[31:15]),      // input wire [15 : 0] A
        .B(after_fft_data[31:15]),      // input wire [15 : 0] B
        .P(fft_im_2)      // output wire [31 : 0] P
    );

    wire [32 : 0] sum = fft_re_2 + fft_im_2;

endmodule

运行仿真测试

这里仿真只需要给一个时钟源即可,编写仿真代码实现100MHz的时钟。运行仿真将相关信号添加到波形窗口中,观察信号。这里的sum为做完FFT处理后,实现功率谱逻辑的信号。将波形转换成模拟形式后可看出波形和matlab的代码仿真类似,然后确定下横坐标是否为21和144,即对应信号频率是否为1MHz和7MHz。

仿真波形

从下图可看出,从FFT处理输出的第一个信号到输出第一个峰值花费了420ns,FFT的配置频率和工作频率是50MHz,也就是周期就是20ns,恰好对应了第21个点,和仿真结果一致。

波形分析

第二个峰值距离FFT输出第一个数据的时间花费了2880ns,换算下来也就是144个时钟周期,和仿真结果一致。

波形分析

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在Soliworks中便捷添加自己的LOGO

在Soliworks中&#xff0c;一般采用草图图片样条曲线的方式绘制个人logo&#xff0c;但是对于一些复杂的logo&#xff0c;对每个模型都绘制一遍显然是不显示的&#xff0c;所以我摸索了一套只需绘制LOGO一遍&#xff0c;就能够将其应用在其他模型的方式。 1. 绘制LOGO 采用草…

黑马点评--好友关注

好友关注&#xff1a; 关注和取关 在探店图文的详情页面中&#xff0c;可以关注发布笔记的作者&#xff1a; 需求&#xff1a;基于该数据结构&#xff0c;实现两个接口 关注和取关接口 Overridepublic Result follow(Long id, Boolean isFollow) {// 1.获取登录用户Long us…

软件设计师教程(二)计算机系统知识-计算机体系结构

软件设计师教程 软件设计师教程&#xff08;一&#xff09;计算机系统知识-计算机系统基础知识 计算机体系结构软件设计师教程计算机体系结构的发展计算机系统结构概述计算机体系结构分类指令系统指令集体系结构的分类CISC和RISC指令的流水处理阵列处理机、并行处理机和多处理…

wy的leetcode刷题记录_Day51

wy的leetcode刷题记录_Day51 声明 本文章的所有题目信息都来源于leetcode 如有侵权请联系我删掉! 时间&#xff1a;2022-11-24 前言 目录wy的leetcode刷题记录_Day51声明前言795. 区间子数组个数题目介绍思路代码收获98. 验证二叉搜索树题目介绍思路代码收获795. 区间子数组…

Linux中修改环境变量的几种方法比较分析

修改环境变量的作用 使得命令可以在命令行直接运行 第一种方式&#xff0c;在终端直接使用export **特点&#xff1a;**即可生效&#xff0c;无需重启或刷新文件&#xff1b;终端关闭则失效 第二种方式&#xff0c;修改/etc/profile文件 特点&#xff1a;对所有用户永久有…

算法刷题打卡第29天:省份数量---并查集

省份数量 难度&#xff1a;中等 有 n 个城市&#xff0c;其中一些彼此相连&#xff0c;另一些没有相连。如果城市 a 与城市 b 直接相连&#xff0c;且城市 b 与城市 c 直接相连&#xff0c;那么城市 a 与城市 c 间接相连。 省份 是一组直接或间接相连的城市&#xff0c;组内不…

SQL注入漏洞 | iwebsec

文章目录靶场搭建SQL注入漏洞靶场搭建 配置 云服务器&#xff1a;阿里云 系统&#xff1a;CentOS 7.6 靶场&#xff1a;iwebsec CentOS-7.6安装docker 安装iwebsec 启动靶场 docker run --restartalways --name iwebsec -it -dp 8001:80 iwebsec/iwebsec访问不成功 可能是…

希望流程挖掘成为撬动企服市场的突破口 | 专访凡得科技CEO海广跃、首席技术顾问刘聪

2022年&#xff0c;全球流程挖掘市场规模预计将达70多亿人民币&#xff0c;而目前中国流程挖掘行业尚处于市场启蒙期&#xff0c;仅少数大型企业与机构对流程挖掘进行了初步或尝试性的投入。从目前来看&#xff0c;原生流程挖掘厂商会直接面向客户输出流程挖掘能力&#xff0c;…

Spring集合注入

一、环境准备 创建一个Maven项目pom.xml添加Spring依赖resources下添加spring的配置文件applicationContext.xml项目中添加BookDao、BookDaoImpl类 public interface BookDao {public void save(); }public class BookDaoImpl implements BookDao {private int[] array;priva…

容器云平台初始化(harbor的安装部署)

1.虚拟机规划 设备说明主机名接口IP地址虚拟机1MasterEth010.0.0.10/24虚拟机2Node1Eth010.0.0.20/24虚拟机3HarborEth010.0.0.30/24 2.容器云平台初始化(harbor的安装部署) 1.根据规划的IP地址&#xff0c;创建虚拟机&#xff0c;确保网络正常通信。按照规划表修改主机名并关…

Linux-ACL权限

ACL权限简介 ACL&#xff1a;access control list 允许给任何用户或者用户组设置任何文件或者目录的访问权限 查看Linux是否开启ACL dumpe2fs Linux一般都开启了ACL权限&#xff0c;可以使用下面的命令查看分区的ACL权限是否打开 首先可以使用df -h或者lsblk来查看Linux系统…

JioNLP上的那些好用的冷门工具

大家好&#xff0c;JioNLP(https://github.com/dongrixinyu/JioNLP)目前已经在Github上有了1600星的点赞&#xff0c;下载安装量大概有几万了。 被使用最多的功能&#xff0c;也是被问得最多的&#xff0c;主要是关键短语抽取、时间语义解析、地址按省市县三级解析等等。其它功…

程序员迷茫:30岁以上的“大龄程码农”出路在哪?java码农该怎么办?

程序员生存、成功、制胜的法则源自IT精英的职业发展秘诀热爱工作&#xff0c;享受生活 为什么程序员过了30就不行了&#xff1f; 我们被固定在“敲代码”的坑里&#xff0c;一干就是10年&#xff0c;再干别的早已不会。敲代码已经成了一项流水线般的工作&#xff0c;就像搬砖工…

Postman非GUI运行脚本工具Newman的安装简介

一、Newman简介 Newman是为Postman而生&#xff0c; 专门用来运行Postman编写好的脚本&#xff1b;使用Newman&#xff0c; 你可以很方便的用命令行来执行postman collections 二、Newman安装 1.先下载Node.js https://nodejs.org/zh-cn/download/ 根据自己电脑系统及位数…

数字验证学习笔记——SystemVerilog芯片验证12 ——句柄的使用包的使用

一、句柄的使用 句柄可以作为形式参数通过方法来完成对象指针的传递&#xff0c;从外部传入方法内部。 句柄也可以在方法内部首先完成修改&#xff0c;而后再由外部完成使用 最后会报错&#xff0c;因为create&#xff08;t&#xff09;定义的是function&#xff0c;没有返回…

锁机制之 Condition 接口

1. 前言 本节内容主要是对 Java 锁机制之 Condition 接口进行讲解&#xff0c;Condition 接口是配合 Lock 接口使用的&#xff0c;我们已经学习过 Lock 接口的相关知识&#xff0c;那么接下来对 Condition 接口进行讲解。本节内容的知识点如下&#xff1a; 2. Condition 接口…

cookie、localStorage 和sessionStorage

文章目录Cookie1.什么是 Cookie&#xff1f;2.cookie的工作机制&#xff0c;运作流程cookie属性项3.读取cookie4.修改cookie5.删除cookielocalStorage 和sessionStorage1.生存期2.数据结构3.API 不管是 localStorage&#xff0c;还是 sessionStorage&#xff0c;可使用的API都相…

基于FPGA+MPU+MCU全自动血细胞分析仪解决方案

全自动血细胞分析仪是医院临床检验应用非常广泛的仪器之一&#xff0c;用来检测红细胞、血红蛋白、白细胞、血小板等项目。是基于电子技术和自动化技术的全自动智能设备&#xff0c;功能齐全&#xff0c;操作简单&#xff0c;依托相关计算机系统在数据处理和数据分析等方面具有…

蓝牙学习三(GAP)

1.简介 GAP&#xff08;Generic Access Profile-通用访问配置文件&#xff09;与应用层紧密相连&#xff0c;所以要想了解BLE&#xff0c;GAP是必须认识的东西。 在第一章中我们说过GAP层&#xff0c;GAP层目前主要用来进行广播、扫描和发起连接。GAP保证了不同的BLE设备可以互…

深度学习入门(7)误差反向传播计算方式及简单计算层的实现

在上一节中《深度学习入门&#xff08;6&#xff09;误差反向传播基础---计算图与链式法则》&#xff0c;我们介绍了误差反向传播的计算图与导数计算的链式法则&#xff0c;这一节主要介绍计算图中各计算节点的误差反向传播计算方式&#xff0c;以及加法与乘法层的实现。 目录…