这两天学着用了一下q2中的fftv9.1核,主要学了variable streaming数据流结构,altera关于fft核的ug_fft写的还是相当详细的,我就是照着这个做的。
下面是对对一些要点的总结:
一:
在这张parameter tab中:
twiddle precision 就是我们平常所说的旋转因子的位数,旋转因子的位数必须小于等于数据的位数。
在architecture tab中:
我选择的是variable streaming数据流,这个其实和streaming差不多,只是vs中你可以通过改变fftpts的值来改变fft的点数。然而其他的时序都是相同的。
输入数据的顺序是顺序输入,输出数据的顺序是位倒序输出,假如你选择的是顺序输出,那将加大你系统的资源消耗,因为系统还得增加个模块将输出转换为顺序输出。
数据表示用的是定点数,而非浮点数。
最终generate后,会生成好多文件,我用到最多的还是下面几个:
1、imag_input.txt,real_input.txt 输入的实部虚部在放在这两个文本文档里。
data_rf = $fopen("real_input.txt","r");
用fopen将文件以只读方式打开,并且将指向该流的文件指针返回给data_rf;
rc_x = $fscanf(data_rf,"%d",data_real_in_int);
fscanf函数通过data_rf这个流指针将数据格式化输入到data_real_in_int中。(我对这个
函数理解也不是很深,还得再学学,但大概意思就是这样的)
2、fft_tb.v这是个很重要的testbench,这个必须仔细看,还能看出一些时序什么的。但在这个程序中我发现了一个问题,
wire [31 - 1: 0] source_real;
wire [31 - 1: 0] source_imag;
integer fft_real_out_int,fft_imag_out_int;
fft_real_out_int = source_real;
fft_imag_out_int = source_imag;
source_real是31位数据,而fft_real_out_int为32位数据,当soruce_real为负数时,传给fft_real_out_int后因为fft_real_out_int高位没变,依旧为0,所以数据就变成了正数。这就违背
此文来自: 马开东博客 转载请注明出处 网址: http://www.makaidong.com
了本意了。
所以我将fft_real_out_int改为[31-1:0],而非integer。
二:
做完上面的步骤我们就可以开始仿真了,datasheet中列了两种方式,一直是matlab,还有就是modelsim。
当我按照说明做matlab仿真时,在command界面中输入:fft_tb时跳出了如下错误
说是这个文件没存在,让我进行hdl级仿真,但我已经进行rtl级仿真了,不知道怎么回事了。。。。。。
但是进行modelsim仿真还是没有错误的,还长了些见识。
(1)on the processing menu, point to start and click start analysis & elaboration
查找了q2 handbook,其中这么解释:
analysis and elaboration—check a design for syntax and semantic errors and perform elaboration to identify the design hierarchy. to perform analysis and elaboration, on the processing menu, point to start and click start analysis & elaboration除了检查语法语义错误,还得定义设计层次。
顺便查了下我们常用的start analysis & synthesis的解释:
analysis and synthesis—perform complete analysis and synthesis on a design, including technology mapping. to perform analysis and synthesis, on the processing menu, point to start and click start analysis & synthesis. this is the most commonly used command and is part of the full compilation flow.
这个就包括综合了,还有mapping。
(2)on the tools menu, click tcl scripts. select the <variationname>_nativelink.tcl tclscript and click run. check for a message confirming that the tcl script was successfully loaded.
这个我还是第一次用到,用了tcl后真的方便好多,节省了好多步骤,不用自己去点了,还是很值得去学一学的。
三:
仿真过后就可以分析结果了,研究一下时序什么的。
sink_sop:输入端口,在一个输入frame中的第一个数据期间为高电平,其余时间为低电平。(也可以在上电时开始时就一直为高,直到第一个数据结束后拉低)
sink_eop:输入端口,在一个输入frame中的最后一个数据期间为高电平,其余时间为低电平。
sink_valid:输入端口,数据在数据总线上有效时可以拉高,当sink_valid和sink_ready都拉高时,数据开始传输。
sink_ready:输出端口,这个不用管,输出肯定为高电平的。
source_sop、source_eop、source_valid、source_ready这和上面的原理都一样。
先初略得写到这吧,有想到的再补充。
--------------------------------------------------------------------------------------------------------------------------------------
Altera FFT核
FFT IP core的总体架构分析:FFT分为fixed transform size architectture 和 variable streaming architecture。variable streaming architecture下又分为radix 2 和radix 4两种运算结构,而内部数据运算表达方式可分为fixed point ,floating point 和block floating point三种。
IO数据流支持流(Streaming)、可变流(Variable Streaming)、缓存突发(Buffered Burst)和突发(Burst)等I/O数据流结构。流FFT结构可以连续处理输入的数据和输出连续的复数数据流,不需要在FFT快内或模块外暂停数据流。突发缓存结构和突发结构的FFT比流FFT结构所需资源更少,但代价是平均块吞吐量下降。
指定FFT复数乘法的实现结构,可包括4 Mults/2 Adders 和 3 Mults/5 Adders。前者使用DSP块结构最小化逻辑资源的使用,但最大化DSP块的使用,这种结构能够提高FFT的最大频率;后者要求的DSP块较少,但需要更多的逻辑资源,得到的FFT的最大频率也相对低些。如果勾选Implement appropriate logic function in RAM则表示使用内嵌的RAM块实现内部逻辑功能,例如FFT中的抽头延迟线,该选项可以减少逻辑资源的使用。
Quartus II提供GUI界面来配置参数,按照以下步骤操作,进可完成功能仿真。
1. 建立工程,根据GUI界面完成FFT核配置参数
2. 设置好仿真工具(在Quartus工具栏Options下选择EDA Tools Options),编译。
3. 执行工程目录下的Tcl文件,然后启动仿真
当完成功能仿真后,发现得到数据和Matlab仿真的结果相差比较大,因为功能仿真的结果需要按照公式 output∗2−exponent 进行转换(注意:公式 1N∗output∗2−exponent 对应于IFFT),才可以得到正确的结果。
案例
实际工程中,需要我们编写逻辑来控制FFT核。IFFT是OFDM基带发送部分的关键,下面给出怎么实现IFFT变换。配置参数为:点数N为64、流水线结构、输入输出位宽16bit、输入输出为自然顺序、Quad Output(4 输出)。
上图是流水线结构的输入时序。在reset信号无效后,将sink_valide置为高有效,表示输入端至少有N个复数据样点可以输入。当sink_ready(FFT核输出的)信号为高电平,表明有能力接收这些输入数据。同时将sink_sop(start)信号置为高电平,表示输入一帧数据(64)的开始,当最后一个数据输入后,sink_eop 被置为高电平 ,表示完成这一帧数据的传输。一定要控制好sink_valid、sink_sop、sink_eop三个信号的时序,否则会导致没有输出或者输出数据出错(笔者曾遇到过)。下图为功能仿真波形图: