实验六 快速傅立叶变换(FFT)的实现(2)

2018-11-24 15:22

2200h2201h2202h2203h2204h2205h2206h2207h2208h2209h220Ah220Bhr[0]=a[0]i[0]=a[1]r[64]=a[128]i[64]=a[129]r[32]=a[64]i[32]=a[65]r[96]=a[192]i[96]=a[193]r[16]=a[32]i[16]=a[33]r[80]=a[160]i[80]=a[161]22FEh22FFh2300h2301h2302h2303h2304h2305h2306h2307h2308h2309h230Ah230Bhr[127]=a[254]i[127]=a[255]a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]a[10]a[11]23FEh23FFha[254]a[255]图2

* 编程技巧:在用C54x进行位倒序组合时,使用位倒序寻址方式可以大大提高程序执行的速度和使用存储器的效率。在这种寻址方式中,AR0存放的整数N是FFT点数的一半,一个辅助寄存器指向一数据存放的单元。当使用位倒序寻址把AR0加到辅助寄存器中时,地址以位倒序的方式产生,即进位是从左到右,而不是从右到左。例如,当AR0 = 0x0060,

121

AR2 = 0x0040时,通过指令:

MAR AR2+0B

我们就可以得到AR2位倒序寻址后的值为0x0010。

下面是0x0060(1100000)与0x0040(1000000)以位倒序方式相加的过程:

1 1 0 0 0 0 0+1 0 0 0 0 0 00 0 1 0 0 0 0

实现256点数据位倒序存储的具体程序段如下:

bit_rev:

STM #d_input_addr,ORIGINAL_INPUT

;在AR3(ORIGINAL_INPUT)中 ;放入输入地址

;在AR7(DATA_PROC_BUF)中 ;放入处理后输出的地址

STM #fft_data,DATA_PROC_BUF

MVMM DATA_PROC_BUF,REORDERED_DATA ;AR2(REORDERED_DATA) STM #K_FFT_SIZE-1,BRC

STM #K_FFT_SIZE,AR0 RPTB bit_rev_end

MVDD *ORIGINAL_INPUT+,*REORDERED_DATA+ MVDD *ORIGINAL_INPUT-,*REORDERED_DATA+

;将原始输入缓冲中的数据 ;放入到位倒序缓冲中去之 ;后输入缓冲(AR3)指针加1 ;位倒序缓冲(AR2)指针也加 ;一

;将原始输入缓冲中的数据 ;放入到位倒序缓冲中去之 ;后输入缓冲(AR3)指针减一

;AR0的值是输入数据数目的一半=128

;中装入第一个位倒序数据指针

;位倒序缓冲(AR2)指针加一

;以保证位倒序寻址正确

122

MAR *ORIGINAL_INPUT+0B bit_rev_end:

;按位倒序寻址方式修改AR3

注意,在上面的程序中。输入缓冲指针AR3(即ORIGINAL_INPUT)在操作时先加一再减一,是因为我们把输入数据相邻的两个字看成一个复数,在用寄存器间接寻址移动了一个复数(两个字的数据)之后,对AR3进行位倒序寻址之前要把AR3的值恢复到这个复数的首字的地址,这样才能保证位倒序寻址的正确。

第二步,N点复数FFT

在数据处理缓冲器里进行N点复数FFT运算。由于在FFT运算中要用到旋转因子WN,

它是一个复数。我们把它分为正弦和余弦部分,用Q15格式将它们存储在两个分离的表中。每个表中有128项,对应从0度到180度。因为采用循环寻址来对表寻址,128 = 27 < 28,因此每张表排队的开始地址就必须是8个LSB位为0的地址。参照前面图1 DES 系统的存储区分配,所以我们必须把正弦表第一项“sine_table”放在0x0D00的位置,余弦表第一项“cos_table”放在0x0E00的位置。

① 根据公式

nkD?k???d[n]WNn?0N?1k?0,1,...,N?1 利用蝶形结对d[n]进行N=128点复数FFT运算,其中

?j(2?)nkNWnkN?e?cos(2?2?nk)?jsin(nk)NN所需的正弦值和余弦值分别以Q15的格式存储于内存区以0x0D00开始的正弦表和以0x0E00开始的余弦表中。我们把128点的复数FFT分为七级来算,第一级是计算两点的FFT蝶形结,第二级是计算四点的FFT蝶形结,然后是八点、十六点、三十二点六十四点、一百二十八点的蝶形结计算。最后所得的结果表示为: D[k] = F{d[n]} = R[k] + j I[k]

123

2200h2201h2202h2203h2204h2205h2206h2207h2208h2209h220Ah220BhR[0]I[0]R[1]I[1]R[2]I[2]R[3]I[3]R[4]I[4]R[5]I[5]22FEh22FFh2300h2301h2302h2303h2304h2305h2306h2307h2308h2309h230Ah230BhR[127]I[127]a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]a[10]a[11]23FEh23FFha[254]a[255]其中,R[k]、I[k]分别是D[k]的实部和虚部。

图3

② FFT完成以后,结果序列D[k]就存储到数据处理缓冲器的上半部分,如图3所示,下半部分任然保留原始的输入序列a[n],这半部分将在第三步中被改写。这样原始的a[n]序列的所有DFT的信息都在D[k]中了,第三步中需要做的就是就是把D[k]变为最终的2N=256点复合序列,A[k]=F{a(n)}。

* 编程技巧:在实际的DSP的编程中为了节约程序运行时间,提高代码的效率,往往要用到并行程序指令。比如:

124

ST B,*AR3 ||LD *AR3+,B

并行指令的执行效果是,使原本分开要两个指令周期才能执行完的两条指令在一个指令周期中中就能执行完。上述指令是将B移位(ASM-16)所决定的位数,存于AR3所指定的存储单元中,同时并行执行,将AR3所指的单元中的值装入到累加器B的高位中。由于指令的src和dst都是acc B,所以存入*AR3中的值是这条指令执行以前的值。 这一步中,实现FFT计算的具体程序如下:

fft:

;---------stage1 :计算FFT的第一步,两点的FFT .asg AR1,GROUP_COUNTER .asg AR2,PX .asg AR3,QX .asg AR4,WR .asg AR5,WI

;定义FFT计算的组指针

;定义AR2为指向参加蝶形运算第一个数据的指针 ;定义AR3为指向参加蝶形运算第二个数据的指针 ;定义AR4为指向余弦表的指针 ;定义AR5为指向正弦表的指针 ;定义AR6为指向蝶形结的指针 ;定义在第一步中的数据处理缓冲指针 ;定义剩下几步中的数据处理缓冲指针

.asg AR6,BUTTERFLY_COUNTER .asg AR7,DATA_PROC_BUF .asg AR7,STAGE_COUNTER

pshm st0 pshm ar0 pshm bk

SSBX SXM

STM #K_ZERO_BK,BK LD #-1,ASM

;保存环境变量

;开启符号扩展模式

;让BK=0 使 *ARn+0% = *ARn+0 ;为避免溢出在每一步输出时右移一位

;PX指向参加蝶形结运算的第一个数的实部(PR) ;AH := PR 125

MVMM DATA_PROC_BUF,PX LD *PX,16,A


实验六 快速傅立叶变换(FFT)的实现(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:百一测评——2014年---全国专利代理人《专利法律知识》考试模拟

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: