vivado之FFT ip核的入门学习(已补充调用模块)
一、什么是FFT
1.1 简介与我的理解
FFT是离散傅立叶变换的快速算法,可以将一个信号变换到频域。有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了。这就是很多信号分析采用FFT变换的原因。另外,FFT可以将一个信号的频谱提取出来,这在频谱分析方面也是经常用的。
下面说说具体物理意义。一个模拟信号,经过ADC采样之后,就变成了数字信号。采样定理告诉我们,采样频率要大于信号频率的两倍,这些我就不在此罗嗦了。采样得到的数字信号,就可以做FFT变换了。N个采样点,经过FFT之后,就可以得到N个点的FFT结果。为了方便进行FFT运算,通常N取2的整数次方。假设采样频率为Fs,信号频率F,采样点数为N。那么FFT之后结果就是一个为N点的复数。每一个点就对应着一个频率点。这个点的模值,就是该频率值下的幅度特性。
假设FFT之后某点n用复数a+bi表示,那么这个复数的模就是An=根号a*a+b*b,相位就是Pn=atan2(b,a)。根据以上的结果,就可以计算出n点(n≠1,且n<=N/2)对应的信号的表达式为:An/(N/2)*cos(2*pi*Fn*t+Pn),即2*An/N*cos(2*pi*Fn*t+Pn)。对于n=1点的信号,是直流分量,幅度即为A1/N。 由于FFT结果的对称性,通常我们只使用前半部分的结果,即小于采样频率一半的结果。atan2(a,b)返回以弧度表示的 y/x 的反正切.相位的计算可用函数atan2(b,a)计算。atan2(b,a)是求坐标为(a,b)点的角度值,范围从-pi到pi。
1.2 实际例子介绍(网络照搬)
以一个实际信号为例,求取其FFT。
信号为:S=2+3*cos(2*pi*50*t-pi*30/180)+1.5*cos(2*pi*75*t+pi*90/180)
式中cos参数为弧度,所以-30度和90度要分别换算成弧度。
我们以256Hz的采样率对这个信号进行采样,总共采样256点。按照我们上面的分析,Fn=(n-1)*Fs/N,我们可以知道,每两个点之间的间距就是1Hz,第n个点的频率就是n-1。
我们的信号有3个频率:0Hz(直流2v)、50Hz、75Hz,应该分别在第1个点、第51个点、第76个点上出现峰值,其它各点应该接近0
1点: 512+0i
2点: -2.6195E-14 – 1.4162E-13i
3点: -2.8586E-14 – 1.1898E-13i
50点:-6.2076E-13 – 2.1713E-12i
51点:332.55 – 192i
52点:-1.6707E-12 – 1.5241E-12i
75点:-2.2199E-13 -1.0076E-12i
76点:3.4315E-12 + 192i
77点:-3.0263E-14 +7.5609E-13i
很明显,1点、51点、76点的值都比较大,它附近的点值都很小,可以认为是0,即在那些频率点上的信号幅度为0。接着,我们来计算各点的幅度值。分别计算这三个点的模值,结果如下:
1点 : 512
51点:384
76点:192
按照公式,可以计算出直流分量为:512/N=512/256=2(第一个点是除以N其他的除2);50Hz信号的幅度为:384/(N/2)=384/(256/2)=3;75Hz信号的幅度为192/(N/2)=192/(256/2)=1.5。可见,从频谱分析出来的幅度是正确的。
然后再来计算相位信息。直流信号没有相位可言,不用管它。先计算50Hz信号的相位,atan2(-192, 332.55)=-0.5236,结果是弧度,换算为角度就是180*-0.5236)/pi=-30.0001。再计算75Hz信号的相位,atan2(192, 3.4315E-12)=1.5708弧度,换算成角度就是180*1.5708/pi=90.0002。可见,相位也是对的。根据FFT结果以及上面的分析计算,我们就可以写出信号的表达式了,它就是我们开始提供的信号。
附上MATLAB仿真代码
1.3总结
假设采样频率为Fs,采样点数为N,做FFT之后,某一点n(n从1开始)表示的频率为:Fn=(n-1)*Fs/N;该点的模值除以N/2就是对应该频率下的信号的幅度(对于直流信号是除以N);该点的相位即是对应该频率下的信号的相位。相位的计算可用函数atan2(b,a)计算。atan2(b,a)是求坐标为(a,b)点的角度值,范围从-pi到pi。要精确到xHz,则需要采样长度为1/x秒的信号,并做FFT。要提高频率分辨率,就需要增加采样点数,这在一些实际的应用中是不现实的,需要在较短的时间内完成分析。解决这个问题的方法有频率细分法,比较简单的方法是采样比较短时间的信号,然后在后面补充一定数量的0,使其长度达到需要的点数,再做FFT,这在一定程度上能够提高频率分辨力。
二、VIVADO之FFT ip核使用
fft的ip核使用对新手来说显得十分复杂。这里直接从ip核设置每个地方开始介绍。
2.1 调出ip核设置
接下来是具体参数介绍
(1)number of channels :变换通道,可以选择多通道,实现多帧数据同时进行FFT运算
(2)transform lenfgth : FFT变换长度,如果选择了最下面的‘run time configurable transdorm legth’,则该参数是FFT变化的最大长度,一般不选。
(3)采样时钟核数据时钟:这个设置越大速度越快,且可以fft测得clk/2大小的频率,如100mhz时钟可以算出50M以内得频率。
(4)architecure choice:FFT架构选择,消耗资源依次递减。第一个是自动选择。选完架构可以从左边框中的latency(隐藏起来了)看一次FFT需要的时间,即求完这N个点(FFT变换长度)的时间。资源消耗越高耗时越短,根据工程需求选择。一般选中间的。
(5)data format:1. 定点全精度 2. 定点缩减位宽 一般就默认Fixed Point
(6) scaling optios :缩放选项 :
1、 block floating point :不管输入的格式如何,FFT变化内部都采用浮点,会根据每一级的的数据情况自动缩放。 这个模式的输入输出位宽一致,便于调用。没有特殊需求就用这个。
2、scaled :在m_axis_data_tuser中会有5BIT表示每一级的缩放情况,在s_axis_config_data中会有相应的字段配置配置缩放因子.每一级别包含2个stage ,2个bit 表示一级缩放,一般0-3可选,如果log(NFFT)不是2的倍数,则最高一级的缩放只能在0-1之间选取。
3、unscaled :不用担心变化过程中会出现溢出,但是输出位宽会非常大,一般情况为了后续的信号处理,不建议用。
(7) Aresten : 复位信号要勾选,至少保持两个时钟的低电平。FFT IP核的复位引脚(ARESETn)最好使用,怎么使用?–把时钟IP核输出的locked引脚赋给FFT的复位引脚,并且在locked引脚为低时给FFT IP核一系列输入引脚均赋予初值。时钟IP核locked引脚代表意义:时钟IP核输出的时钟是否稳定有效,低时不稳定,高时表明时钟IP核输出时钟稳定
(8) output odering options:默认是倒序但是我们一般选自然输出。
(9)optional output fileds :选项输出字段:
1、xk_index:FFT 变幻的结果索引,在m_axis_data_user中有相应的字段。
2、OVFLO是变换中溢出的指示信号,对应event_fft_overflow.
其他的一般不用设置。
我们可以看到假设我们输入的数据位宽是10,则FFT之后,还有虚数部分,[9:0]是实数,[25:16]是虚数。一共有2048个点,一次FFT。
2.2 IP核参数的意义
这里面引脚很多,最重要的当然就是输入输出了。
.aclk(aclk), 输入时钟
.aresetn(aresetn), 复位 ,接PLL的locked
Input[N:0]: s_axis_config_tdata:控制输入模式,最低位控制。1fft 0ifft。如果我们只需要FFT就直接设置N'b1就ok,这里在配置scale模式的时候需要使用,之后再专门介绍。
Input: s_axis_config_tvalid: 设置为1就行
Output: s_axis_config_tready:不接不管他,总之如果你的IP核没启动这个就为0.
Output: s_axis_data_tready:aresetn拉高两个时钟周期后,该口输出1;此时ip核初始化完成,可进行数据输入。
Input: s_axis_data_tvalid:数据有效 当s_axis_data_tready高电平后,将s_axis_data_tvalid拉高L个周期,输入L个数据进行fft;L是FFT的点数。
Input[M:0]: s_axis_data_tdata:看配置界面会提示如下图低16就是实部高16虚部,我们ADC的数据是实信号放实部就好,新手注意这里必须是有符号数。
Input: s_axis_data_tlast:输入L个数据后拉高,停止数据输入。TLAST是起到一个输入数据末端指示作用,比如你作8点FFT运算,你要给8个数据给IP核吧,在最后一个数据期间你把TLAST拉高就行了,意思是告诉IP核,这一组的8个数据都给你带过来了,这是最后一个。IP核一验算,整整齐齐8个,就不会找你麻烦了。
做fft需要耗费的时钟周期计算如下s_axis_data_tlast- s_axis_data_tvalid
Output[M1:0]:m_axis_data_tdata:高位为虚部,低位为实部。 在FPGA里不好开方所以我们一般求他的功率谱即实部和虚部平方相加。
Output: m_axis_data_tvalid:当fft结果输出时拉高,输出2最后一个数据时拉低,这个是对齐最后一个数据的。
Output[M2:0]:m_axis_data_tuser:这里的OVFLO是溢出指示位,这里的XK_INDEX就是索引了,是对齐谱线的。XK_INDEX*fs/N=频率(fs就是你的采样率,N就是FFT点数)
Input: m_axis_data_tready:需保持高电平,保证FFT单元处在计算模式,并且能够输出结算结果;接 1 .m_axis_data_tready(1)
Output: m_axis_data_tlast:当fft结果输出到最后一个结果时拉高,紧接着下一个时钟就拉低。
主要就是时钟、复位、配置、数据、和事件报告。s是从机,m是主机,也好理解,对于FPGA来说是要接受主句的输出来作为输入数据,去FFT。
转自 数字信号处理(三):Xilinx FFT IP核详解(二) – 知乎 (zhihu.com)
20230109补充代码和解释
本代码是把FFTIP例化在模块内方便调用。
要注意的是,我输入datach1是无符号补码,都是正数。在送给fft ip时,实际上要补上一个符号位0,s_axis_data_tdata <= {22'd0,input_data_ch1};这里面就是我补了0,实际使用根据你的输入来自己设置。总之,ip输入带符号。而输出肯定也是带符号的。用ILA看的时候设置为有符号数看。
我下面还例化了别的IP,自行去除。本模块只需要设置好你的输入,即可跑出fft 后的实部和虚部。
注意事项补充:
1.始终均可拉高的引脚:S_AXIS_CONFIG_TVALID,S_AXIS_DATA_TREADY。
2.我们要注意采样频率和FFT采样点数,这两个关系到分辨率,而且采样频率还得满足奈奎斯特定理。FFT采样点数越大越好,即分辨率会高。但是太大了运算时间就会长,分辨率分辨的就是频率,第m个点对应频率m*FS/N。
3.当FFT计算结果输出完成后,信号fft_m_data_tlast变为高电平,代表数据输出结束,并在延时一小段时间后,fft_s_data_tready重新变为低电平,代表IP核重新进入到空闲状态。可以进行对IP核下一组数据的输入。
4.输入输出如果不到8bit会补上,例如12bit的实数输入,输出会有32位,[11:0]是实数部分[25:16]是虚数,实数虚数前各补4个0,输出也是一样的
2024.03.22补充:
这个地方有坑。一般我们只希望我们拉高多少个电平时读多少数据来FFT,在有一次设计中,我把FIFO空信号设置为读使能来将数据读到FFTip中,但是发现不对!!!我以为是FFT ip只支持连续送数据进去,结果是我不小心设置成实时的了,而空信号是断断续续的………………我超服了。
过几天把缩放的介绍一下再把多通道的介绍一下。
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/95499.html