导航:首页 > 源码编译 > fft倒序算法

fft倒序算法

发布时间:2023-06-18 10:51:22

1. 16点DFT的FFT算法

FFT(快速傅里叶变换)是DFT的一种特殊情况,就是当运算点的个数是2的整数次幂的时候进行的运算(不够用0补齐)。

FFT计算原理及流程图:

原理:FFT的计算要求点数必须为2的整数次幂,如果点数不够用0补齐。例如计算{2,3,5,8,4}的16点FFT,需要补11个0后进行计算。FFT计算运用蝶形运算,在蝶形运算中变化规律由W(N, p)推导,其中N为FFT计算点数,J为下角标的值。

L = 1时,W(N, p) = W(N, J) = W(2^L, J),其中J = 0;

L = 2时,W(N, p) = W(N, J) = W(2^L, J),其中J = 0, 1;

L = 3时,W(N, p) = W(N, J) = W(2^L, J),其中J = 0, 1, 2, 3;

所以,W(N, p) = W(2^L, J),其中J = 0, 1, ..., 2^(L-1)-1

又因为2^L = 2^M*2^(L-M) = N*2^(L-M),这里N为2的整数次幂,即N=2^M,

W(N, p) = W(2^L, J) = W(N*2^(L-M), J) = W(N, J*2^(M-L))

所以,p = J*2^(M-L),此处J = 0, 1, ..., 2^(L-1)-1,当J遍历结束但计算点数不够N时,J=J+2^L,后继续遍历,直到计算点数为N时不再循环。

流程图:

/*======================================================================
*方法名:fft
*方法功能:计算数组的FFT,运用蝶形运算
*
*变量名称:
*yVector-原始数据
*length-原始数据长度
*N-FFT计算点数
*fftYreal-FFT后的实部
*fftYImg-FFT后的虚部
*
*返回值:是否成功的标志,若成功返回true,否则返回false
*=====================================================================*/

+(BOOL)fft:(floatfloat*)yVectorandOriginalLength:(NSInteger)lengthandFFTCount:(NSInteger)NandFFTReal:(floatfloat*)fftYRealandFFTYImg:(floatfloat*)fftYImg
{
//确保计算时时2的整数幂点数计算
NSIntegerN1=[selfnextNumOfPow2:N];

//定义FFT运算是否成功的标志
BOOLisFFTOK=false;

//判断计算点数是否为2的整数次幂
if(N!=N1)
{
//不是2的整数次幂,直接计算DFT
isFFTOK=[selfdft:yVectorandOriginalLength:lengthandFFTCount:NandFFTReal:fftYRealandFFTYImg:fftYImg];

//返回成功标志
returnisFFTOK;
}


//如果计算点数位2的整数次幂,用FFT计算,如下
//定义变量
floatyVectorN[N1];//N点运算的原始数据
NSIntegerpowOfN=log2(N1);//N=2^powOfN,用于标记最大运算级数(公式中表示为:M)
NSIntegerlevel=1;//运算级数(第几次运算),最大为powOfN,初值为第一级运算(公式中表示为:L)
NSIntegerlineNum;//行号,倒序排列后的蝶形运算行号(公式中表示为:k)
floatinverseOrderY[N1];//yVector倒序x
NSIntegerdistanceLine=1;//行间距,第level级运算每个蝶形的两个节点距离为distanceLine=2^(L-1)(公式中表示为:B)
NSIntegerp;//旋转因子的阶数,旋转因子表示为W(N,p),p=J*2^(M-L)
NSIntegerJ;//旋转因子的阶数,旋转因子表示为W(2^L,J),J=0,1,2,...,2^(L-1)-1=distanceLine-1
floatrealTemp,imgTemp,twiddleReal,twiddleImg,twiddleTheta,twiddleTemp=PI_x_2/N1;
NSIntegerN_4=N1/4;

//判断点数是否够FFT运算点数
if(length<=N1)
{
//如果N至少为length,先把yVector全部赋值
for(NSIntegeri=0;i<length;i++)
{
yVectorN[i]=yVector[i];
}

if(length<N1)
{
//如果N>length后面补零
for(NSIntegeri=length;i<N1;i++)
{
yVectorN[i]=0.0;
}
}
}
else
{
//如果N<length截取相应长度的数据进行运算
for(NSIntegeri=0;i<N1;i++)
{
yVectorN[i]=yVector[i];
}
}

//调用倒序方法
[selfinverseOrder:yVectorNandN:N1andInverseOrderVector:inverseOrderY];

//初始值
for(NSIntegeri=0;i<N1;i++)
{
fftYReal[i]=inverseOrderY[i];
fftYImg[i]=0.0;
}

//三层循环
//第三层(最里):完成相同旋转因子的蝶形运算
//第二层(中间):完成旋转因子的变化,步进为2^level
//第一层(最外):完成M次迭代过程,即计算出x(k)=A0(k),A1(k),...,Am(k)=X(k)

//第一层循环
while(level<=powOfN)
{
distanceLine=powf(2,level-1);//初始条件distanceLine=2^(level-1)
J=0;
NSIntegerpow2_Level=distanceLine*2;//2^level
NSIntegerpow2_NSubL=N1/pow2_Level;//2^(M-L)

//第二层循环
while(J<distanceLine)
{
p=J*pow2_NSubL;
lineNum=J;
NSIntegerstepCount=0;//J运算的步进计数

//求旋转因子
if(p==0)
{
twiddleReal=1.0;
twiddleImg=0.0;
}
elseif(p==N_4)
{
twiddleReal=0.0;
twiddleImg=-1.0;
}
else
{
//计算尤拉公式中的θ
twiddleTheta=twiddleTemp*p;

//计算复数的实部与虚部
twiddleReal=cos(twiddleTheta);
twiddleImg=-11*sin(twiddleTheta);
}

//第三层循环
while(lineNum<N1)
{
//计算下角标
NSIntegerfootNum=lineNum+distanceLine;

/*---------------------------------------
*用复数运算计算每级中各行的蝶形运算结果
*X(k)=X(k)+X(k+B)*W(N,p)
*X(k+B)=X(k)-X(k+B)*W(N,p)
*---------------------------------------*/
realTemp=fftYReal[footNum]*twiddleReal-fftYImg[footNum]*twiddleImg;
imgTemp=fftYReal[footNum]*twiddleImg+fftYImg[footNum]*twiddleReal;

//将计算后的实部和虚部分别存放在返回数组中
fftYReal[footNum]=fftYReal[lineNum]-realTemp;
fftYImg[footNum]=fftYImg[lineNum]-imgTemp;
fftYReal[lineNum]=fftYReal[lineNum]+realTemp;
fftYImg[lineNum]=fftYImg[lineNum]+imgTemp;

stepCount+=pow2_Level;

//行号改变
lineNum=J+stepCount;
}

//旋转因子的阶数变换,达到旋转因子改变的效果
J++;
}

//运算级数加一
level++;
}

isFFTOK=true;
returnisFFTOK;
}

2. 如何实现128点的基2-FFT算法,并与MATLAB的fft算法作对比分析.

我只能给你一个fft算法,流程图说起来有点复杂,可以matlab里面的函数tic(开启时钟)t=toc(关闭时钟)t就是运算过程的时间
当然tic放程序开始,toc放结尾,来分析之即可
function d=lxfft(x)
n=length(x);
if n>2
for i=0:n/2-1
x1(i+1)=x(2*i+1);
x2(i+1)=x(2*i+2);
end
X1=lxfft(x1);
X2=lxfft(x2);
for i=0:n/2-1
X2(i+1)= X2(i+1)*exp(-j*2*pi/n*i);//旋转因子
d(i+1)=X1(i+1)+X2(i+1);
d(i+n/2+1)=X1(i+1)-X2(i+1);
end
else
d(1)=x(1)+x(2);
d(2)=x(1)-x(2);
end
end

3. 求用C++实现的FFT算法

很早以前的,如果管用别忘了给我加分呀
/*
This computes an in-place complex-to-complex FFT
x and y are the real and imaginary arrays of 2^m points.
dir = 1 gives forward transform
dir = -1 gives reverse transform
*/
short FFT(short int dir,long m,double *x,double *y)
{
long n,i,i1,j,k,i2,l,l1,l2;
double c1,c2,tx,ty,t1,t2,u1,u2,z;

/* Calculate the number of points */
n = 1;
for (i=0;i<m;i++)
n *= 2;

/* Do the bit reversal */
i2 = n >> 1;
j = 0;
for (i=0;i<n-1;i++) {
if (i < j) {
tx = x[i];
ty = y[i];
x[i] = x[j];
y[i] = y[j];
x[j] = tx;
y[j] = ty;
}
k = i2;
while (k <= j) {
j -= k;
k >>= 1;
}
j += k;
}

/* Compute the FFT */
c1 = -1.0;
c2 = 0.0;
l2 = 1;
for (l=0;l<m;l++) {
l1 = l2;
l2 <<= 1;
u1 = 1.0;
u2 = 0.0;
for (j=0;j<l1;j++) {
for (i=j;i<n;i+=l2) {
i1 = i + l1;
t1 = u1 * x[i1] - u2 * y[i1];
t2 = u1 * y[i1] + u2 * x[i1];
x[i1] = x[i] - t1;
y[i1] = y[i] - t2;
x[i] += t1;
y[i] += t2;
}
z = u1 * c1 - u2 * c2;
u2 = u1 * c2 + u2 * c1;
u1 = z;
}
c2 = sqrt((1.0 - c1) / 2.0);
if (dir == 1)
c2 = -c2;
c1 = sqrt((1.0 + c1) / 2.0);
}

/* Scaling for forward transform */
if (dir == 1) {
for (i=0;i<n;i++) {
x[i] /= n;
y[i] /= n;
}
}

return(TRUE);
}

---------------------------------------------------------------------------------
/*****************fft programe*********************/
#include "typedef.h"
#include "math.h"

struct compx EE(struct compx b1,struct compx b2)
{
struct compx b3;
b3.real=b1.real*b2.real-b1.imag*b2.imag;
b3.imag=b1.real*b2.imag+b1.imag*b2.real;
return(b3);
}

void FFT(struct compx *xin,int N)
{
int f,m,nv2,nm1,i,k,j=1,l;
/*int f,m,nv2,nm1,i,k,j=N/2,l;*/
struct compx v,w,t;
nv2=N/2;
f=N;
for(m=1;(f=f/2)!=1;m++){;}
nm1=N-1;

/*变址运算*/
for(i=1;i <=nm1;i++)
{
if(i <j){t=xin[j];xin[j]=xin[i];xin[i]=t;}
k=nv2;
while(k <j){j=j-k;k=k/2;}
j=j+k;
}

{
int le,lei,ip;
float pi;
for(l=1;l <=m;l++)
{ le=pow(2,l);// 这里用的是L而不是1 !!!!
lei =le/2;
pi=3.14159;
v.real=1.0;
v.imag=0.0;
w.real=cos(pi/lei);
w.imag=-sin(pi/lei);
for(j=1;j <=lei;j++)
{
/*double p=pow(2,m-l)*j;
double ps=2*pi/N*p;
w.real=cos(ps);
w.imag=-sin(ps);*/
for(i=j;i <=N;i=i+le)
{ /* w.real=cos(ps);
w.imag=-sin(ps);*/
ip=i+lei;
t=EE(xin[ip],v);
xin[ip].real=xin[i].real-t.real;
xin[ip].imag=xin[i].imag-t.imag;
xin[i].real=xin[i].real+t.real;
xin[i].imag=xin[i].imag+t.imag;
}
v=EE(v,w);
}
}
}
return;
}

/*****************main programe********************/

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "typedef.h"

float result[257];
struct compx s[257];
int Num=256;
const float pp=3.14159;

main()
{

int i=1;
for(;i <0x101;i++)
{
s[i].real=sin(pp*i/32);
s[i].imag=0;
}

FFT(s,Num);

for(i=1;i <0x101;i++)
{
result[i]=sqrt(pow(s[i].real,2)+pow(s[i].imag,2));
}

}

-----------------------------------------------------------------------------------
FFT变换 C源代码

FFT C source code (Simple radix-2)

void fft_float (
unsigned NumSamples,
int InverseTransform,
float *RealIn,
float *ImagIn,
float *RealOut,
float *ImagOut )
{
unsigned NumBits; /* Number of bits needed to store indices */
unsigned i, j, k, n;
unsigned BlockSize, BlockEnd;
double angle_numerator = 2.0 * DDC_PI;
double tr, ti; /* temp real, temp imaginary */
if ( !IsPowerOfTwo(NumSamples) )
{
fprintf (
stderr,
"Error in fft(): NumSamples=%u is not power of two\n",
NumSamples );
exit(1);
}
if ( InverseTransform )
angle_numerator = -angle_numerator;
CHECKPOINTER ( RealIn );
CHECKPOINTER ( RealOut );
CHECKPOINTER ( ImagOut );
NumBits = NumberOfBitsNeeded ( NumSamples );
/*
** Do simultaneous data and bit-reversal ordering into outputs...
*/
for ( i=0; i < NumSamples; i++ )
{
j = ReverseBits ( i, NumBits );
RealOut[j] = RealIn;
ImagOut[j] = (ImagIn == NULL) ? 0.0 : ImagIn;
}
/*
** Do the FFT itself...
*/
BlockEnd = 1;
for ( BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1 )
{
double delta_angle = angle_numerator / (double)BlockSize;
double sm2 = sin ( -2 * delta_angle );
double sm1 = sin ( -delta_angle );
double cm2 = cos ( -2 * delta_angle );
double cm1 = cos ( -delta_angle );
double w = 2 * cm1;
double ar[3], ai[3];
double temp;
for ( i=0; i < NumSamples; i += BlockSize )
{
ar[2] = cm2;
ar[1] = cm1;
ai[2] = sm2;
ai[1] = sm1;
for ( j=i, n=0; n < BlockEnd; j++, n++ )
{
ar[0] = w*ar[1] - ar[2];
ar[2] = ar[1];
ar[1] = ar[0];
ai[0] = w*ai[1] - ai[2];
ai[2] = ai[1];
ai[1] = ai[0];
k = j + BlockEnd;
tr = ar[0]*RealOut[k] - ai[0]*ImagOut[k];
ti = ar[0]*ImagOut[k] + ai[0]*RealOut[k];
RealOut[k] = RealOut[j] - tr;
ImagOut[k] = ImagOut[j] - ti;
RealOut[j] += tr;
ImagOut[j] += ti;
}
}
BlockEnd = BlockSize;
}
/*
** Need to normalize if inverse transform...
*/
if ( InverseTransform )
{
double denom = (double)NumSamples;
for ( i=0; i < NumSamples; i++ )
{
RealOut /= denom;
ImagOut /= denom;
}
}
}

int IsPowerOfTwo ( unsigned x )
{
if ( x < 2 )
return FALSE;
if ( x & (x-1) ) // Thanks to 'byang' for this cute trick!
return FALSE;
return TRUE;
}

unsigned NumberOfBitsNeeded ( unsigned PowerOfTwo )
{
unsigned i;
if ( PowerOfTwo < 2 )
{
fprintf (
stderr,
">>> Error in fftmisc.c: argument %d to NumberOfBitsNeeded is too small.\n",
PowerOfTwo );
exit(1);
}
for ( i=0; ; i++ )
{
if ( PowerOfTwo & (1 << i) )
return i;
}
}

unsigned ReverseBits ( unsigned index, unsigned NumBits )
{
unsigned i, rev;
for ( i=rev=0; i < NumBits; i++ )
{
rev = (rev << 1) | (index & 1);
index >>= 1;
}
return rev;
}

double Index_to_frequency ( unsigned NumSamples, unsigned Index )
{
if ( Index >= NumSamples )
return 0.0;
else if ( Index <= NumSamples/2 )
return (double)Index / (double)NumSamples;
return -(double)(NumSamples-Index) / (double)NumSamples;
}

4. 求傅里叶变化 详细过程 谢谢 又追加悬赏

尽管最初傅立叶分析是作为热过程的解析分析的工具,但是其思想方法仍然具有典型的还原论和分析主义的特征。"任意"的函数通过一定的分解,都能够表示为正弦函数的线性组合的形式,而正弦函数在物理上是被充分研究而相对简单的函数类,这一想法跟化学上的原子论想法何其相似!奇妙的是,现代数学发现傅立叶变换具有非常好的性质,使得它如此的好用和有用,让人不晌缓得不感叹造物的神奇: 1. 傅立叶变换是线性算子,若赋予适当的范数,它还是酉算子; 2. 傅立叶变换的逆变换容易求出,而且形式与正变换非常类似; 3. 正弦基函数是微分运算的本征函数,从而使得线性微分方程的求解可以转化为常系数的代数方程的求解.在线性时不变的物理系统内,频率是个不变的性质,从而系统对于复杂激励的响应可以通过组合其对不同频率正弦信号的响应来获取; 4. 着名的卷积定理指出:傅立叶变换可以化复杂的卷积运算为简单的乘积运算,从而提供了计算卷积的一种简单手段; 5. 离散形式的傅立叶变换可以利用数字计算机快速的算出(其算法称山滑为快速傅立叶变换算法(FFT)). 正是由于上述的良好性质,傅里叶变换在物理学、数论、组合数学、信号处理、概率、统计、密码学、声学、光学等领域都有着广泛的应用。 有関傅立叶变换的FPGA实现 傅立叶变换是数字信号处理中的基本操作,广泛应用于表述及分析离散时域信号领域。但由于其运算量与变换点数N的平方成正比关系,因此,在N较大时,直接应用DFT算法进行谱变换是不切合实际的。然而,快速傅立叶变换技术的出现使情况发生了根本性的变化。本文主要描述了采用FPGA来实现2k/4k/8k点FFT的设计方法。
整体结构
一般情况下,N点的傅立叶变换对为: 其中,WN=exp(-2pi/N)。X(k)和x(n)都为复数。与之相对的快速傅立叶变换有很多种,如DIT(时域抽取法)、DIF(频域抽取法)、Cooley-Tukey和Winograd等。对于2n傅立叶变换,Cooley-Tukey算法可导出DIT和DIF算法。本文运用的基本思想是Cooley-Tukey算法,即将高点数的傅立叶变换通过多重低点数傅立叶变换来实现。虽然DIT与DIF有差别,但由于它们在本质上都是一种基于标号分解的算法,故在运算量和算法复杂性等方面完全一样,而没有性能上的优劣之分,所以可以根据需要任取其中一种,本文主要以DIT方法为对象来讨论。 N=8192点DFT的运算表达式为: 式中,m=(4n1+n2)(2048k1+k2)(n=4n1+n2,k=2048k1+k2)其中n1和k2可取0,1,...,2047,k1和n2可取0,1,2,3。 由式(3)可知,8k傅立叶变换可由4×2k的傅立叶变换构成。同理,4k傅立叶变换可由2×2k的傅立叶变换构成。而2k傅立叶变换可由128×16的傅立叶变换构成。128的傅立叶变换可进一步由16×8的傅立叶变换构成,归根结底,整个傅立叶变换可由基2、基4的傅立叶变换构成。2k的FFT可以通过5个基4和1个基2变换来实现;4k的FFT变换可通过6个基4变换来实现;8k的FFT可以通过6个基4和1个基2变换来实现。也就是说:FFT的基本结构可由基2/4模块、复数乘法器、存储单元和存储器控制模块构成,其整体结构如图1所示。 图1中,RAM用来存储输入数据、运算过程中的中间结果以及运算完成后的数据,ROM用来存储旋转因子表。蝶形运算单元即为基2/4模块,控逗谨腊制模块可用于产生控制时序及地址信号,以控制中间运算过程及最后输出结果。
蝶形运算器的实现
基4和基2的信号流如图2所示。图中,若A=r0+j*i0,B=r1+j*i1,C=r2+j*i2,D=r3+j*i3是要进行变换的信号,Wk0=c0+j*s0=1,Wk1=c1+j*s1,Wk2=c2+j*s2,Wk3=c3+j*s3为旋转因子,将其分别代入图2中的基4蝶形运算单元,则有: A′=[r0+(r1×c1-i1×s1)+(r2×c2-i2×s2)+(r3×c3-i3×s3)]+j[i0+(i1×c1+r1×s1)+(i2×c2+r2×s2)+(i3×c3+r3×s3)]? (4) B′=[r0+(i1×c1+r1×s1)-(r2×c2-i2×s2)-(i3×c3+r3×s3)]+j[i0-(r1×c1-i1×s1)-(i2×c2+r2×s2)+(r3×c3-i3×s3)] (5) C′=[r0-(r1×c1-i1×s1)+(r2×c2-i2×s2)-(r3×c3-i3×s3)]+j[i0-(i1×c1+r1×s1)+(i2×c2+r2×s2)-(i3×c3+r3×s3)] (6) D′=[r0-(i1×c1+r1×s1)-(r2×c2-i2×s2)+(i3×c3+r3×s3)]+j[i0+(r1×c1-i1×s1)-(i2×c2+r2×s2)-(r3×c3-i3×s3)]? (7) 而在基2蝶形中,Wk0和Wk2的值均为1,这样,将A,B,C和D的表达式代入图2中的基2运算的四个等式中,则有: A′=r0+(r1×c1-i1×s1)+j[i0+(i1×c1+r1×s1)]? (8) B′=r0- (r1×c1-i1×s1)+j[i0-(i1×c1+r1×s1)] (9) C′=r2+(r3×c3-i3×s3)+j[i0+(i3×c3+r3×s3)]? (10) D′=r2-(r3×c3-i3×s3)+j[i0-(i3×c3+r3×s3)]? (11) 在上述式(4)~(11)中有很多类同项,如i1×c1+r1×s1和r1×c1-i1×s1等,它们仅仅是加减号的不同,其结构和运算均类似,这就为简化电路提供了可能。同时,在蝶形运算中,复数乘法可以由实数乘法以一定的格式来表示,这也为设计复数乘法器提供了一种实现的途径。 以基4为例,在其运算单元中,实际上只需做三个复数乘法运算,即只须计算BWk1、CWk2和DWk3的值即可,这样在一个基4蝶形单元里面,最多只需要3个复数乘法器就可以了。在实际过程中,在不提高时钟频率下,只要将时序控制好?便可利用流水线(Pipeline)技术并只用一个复数乘法器就可完成这三个复数乘法,大大节省了硬件资源。 图2 基2和基4蝶形算法的信号流图
FFT的地址
FFT变换后输出的结果通常为一特定的倒序,因此,几级变换后对地址的控制必须准确无误。 倒序的规律是和分解的方式密切相关的,以基8为例,其基本倒序规则如下: 基8可以用2×2×2三级基2变换来表示,则其输入顺序则可用二进制序列(n1 n2 n3)来表示,变换结束后,其顺序将变为(n3 n2 n1),如:X?011→ x?110,即输入顺序为3,输出时顺序变为6。 更进一步,对于基16的变换,可由2×2×2×2,4×4,4×2×2等形式来构成,相对于不同的分解形式,往往会有不同的倒序方式。以4×4为例,其输入顺序可以用二进制序列(n1 n2 n3n4)来表示变换结束后,其顺序可变为((n3 n4)(n1 n2)),如: X?0111→ x?1101。即输入顺序为7,输出时顺序变为13。 在2k/4k/8k的傅立叶变换中,由于要经过多次的基4和基2运算,因此,从每次运算完成后到进入下一次运算前,应对运算的结果进行倒序,以保证运算的正确性。
旋转因子
N点傅立叶变换的旋转因子有着明显的周期性和对称性。其周期性表现为: FFT之所以可使运算效率得到提高,就是利用了对称性和周期性把长序列的DFT逐级分解成几个序列的DFT,并最终以短点数变换来实现长点数变换。 根据旋转因子的对称性和周期性,在利用ROM存储旋转因子时,可以只存储旋转因子表的一部分,而在读出时增加读出地址及符号的控制,这样可以正确实现FFT。因此,充分利用旋转因子的性质,可节省70%以上存储单元。 实际上,由于旋转因子可分解为正、余弦函数的组合,故ROM中存的值为正、余弦函数值的组合。对2k/4k/8k的傅立叶变换来说,只是对一个周期进行不同的分割。由于8k变换的旋转因子包括了2k/4k的所有因子,因此,实现时只要对读ROM的地址进行控制,即可实现2k/4k/8k变换的通用。
存储器的控制
因FFT是为时序电路而设计的,因此,控制信号要包括时序的控制信号及存储器的读写地址,并产生各种辅助的指示信号。同时在计算模块的内部,为保证高速,所有的乘法器都须始终保持较高的利用率。这意味着在每一个时钟来临时都要向这些单元输入新的操作数,而这一切都需要控制信号的紧密配合。 为了实现FFT的流形运算,在运算的同时,存储器也要接收数据。这可以采用乒乓RAM的方法来完成。这种方式决定了实现FFT运算的最大时间。对于4k操作,其接收时间为4096个数据周期,这样?FFT的最大运算时间就是4096个数据周期。另外,由于输入数据是以一定的时钟为周期依次输入的,故在进行内部运算时,可以用较高的内部时钟进行运算,然后再存入RAM依次输出。 为节省资源,可对存储数据RAM采用原址读出原址写入的方法,即在进行下一级变换的同时,首先应将结果回写到读出数据的RAM存贮器中;而对于ROM,则应采用与运算的数据相对应的方法来读出存储器中旋转因子的值。 在2k/4k/8k傅立叶变换中,要实现通用性,控制器是最主要的模块。2k、4k、8k变换具有不同的内部运算时间和存储器地址,在设计中,针对不同的点数应设计不同的存储器存取地址,同时,在完成变换后,还要对开始输出有用信号的时刻进行指示。
硬件的选择
本设计的硬件实现选用的是现场可编程门阵列(FPGA)来满足较高速度的需要。本系统在设计时选用的是ALTERA公司的STRATIX芯片,该芯片中包含有DSP单元,可以完成较为耗费资源的乘法器单元。同时,该器件也包含有大量存储单元,从而可保证旋转因子的精度。 除了一些专用引脚外,FPGA上几乎所有的引脚均可供用户使用,这使得FPGA信号处理方案具有非常好的I/O带宽。大量的I/O引脚和多块存储器可使设计获得优越的并行处理性能。其独立的存储块可作为输入/工作存储区和结果的缓存区,这使得I/O可与FFT计算同时进行。在实现的时间方面,该设计能在4096个时钟周期内完成一个4096点的FFT。若采用10MHz的输入时钟,其变换时间在200μs左右。而由于最新的FPGA使用了MultiTrack互连技术,故可在250MHz以下频率稳定地工作,同时,FFT的实现时间也可以大大缩小。 FFT运算结果的精度与输入数据的位数及运算过程中的位数有关,同时和数据的表示形式也有很大关系。一般来说,浮点方式比定点方式精度高。而在定点计算中,存储器数据的位数越大,运算精度越高,使用的存储单元和逻辑单元也越多。在实际应用中,应根据实际情况折衷选择精度和资源。本设计通过MATLAB进行仿真证明:其实现的变换结果与MATLAB工具箱中的FFT函数相比,信噪比可以达到65db以上,完全可以满足一般工程的实际应用要求。

阅读全文

与fft倒序算法相关的资料

热点内容
dvd光盘存储汉子算法 浏览:757
苹果邮件无法连接服务器地址 浏览:963
phpffmpeg转码 浏览:671
长沙好玩的解压项目 浏览:145
专属学情分析报告是什么app 浏览:564
php工程部署 浏览:833
android全屏透明 浏览:737
阿里云服务器已开通怎么办 浏览:803
光遇为什么登录时服务器已满 浏览:302
PDF分析 浏览:485
h3c光纤全工半全工设置命令 浏览:143
公司法pdf下载 浏览:382
linuxmarkdown 浏览:350
华为手机怎么多选文件夹 浏览:683
如何取消命令方块指令 浏览:350
风翼app为什么进不去了 浏览:778
im4java压缩图片 浏览:362
数据查询网站源码 浏览:150
伊克塞尔文档怎么进行加密 浏览:892
app转账是什么 浏览:163