暂时先不管扰码、信道编码和交织部分,
一帧输入数据为192bit的伪随机序列,时钟为20MHz;
经过16QAM调制之后,一帧数据变为48byte,时钟为80MHz,对应于48个频率的子载波,频率点为-26到-22、-20到-8、-6到-1、1到6、8到20、22到26;
插入导频部分是将4个导频符号插入到48个复数数据中,对应于-21、-7、7、21号子载波,并且在插入导频模块中,需要通过地址变换将导频符号插入;
根据协议中对IFFT输入端口的映射规定,将计算后1至26的标号分配给图
模块的1至26端日,计算后-26至-1的标号分配给 38 至63端口,同时将4个导频信号映射到IFFT运算模块的43、57、7、21号输入端口,剩下的输入端口则输入零值。
经过地址变换之后,64点信息为:
中间遇到了数据不对的问题,仔细仿真后,发现了问题所在:RAM的延时为2个clk,而代码中设计的为1个时钟,将IP核中输出register这个选项去掉之后数据正确!!
插入导频仿真:
接着就是IFFT,这个IP核贼烦。尤其是验证数据的正确性,因为点数和精度差异,算出来的结果和matlab算的差异比较大,目前我打算先通过IFFT然后再通过同样设置的FFT看看数据前后的差异。
IFFT的设置参照笔记中的IP核分区,完成64点IFFT运算之后,得到如下数据:
接下来插入循环前缀,直接在IP核设置界面更改就好了,然后将configData修改为16'h0010,加入循环前缀后的仿真:
短训练序列共16个(6 -34 -3 36 24 36 -3 -34 14 1 -20 -3 0 -3 -20 1),循环10次,直接存储在ROM中读取,加入短训练序列仿真:
长训练序列为32+64*2=160个,其中前32是64的CP,加入长训练序列仿真:
最后,需要一个控制模块控制整个发射机,写一个状态机,首先使能信号源模块,然后根据仿真查看ifft数据延时多长时间输出,等到IFFT数据输出的时候,使能整个模块的输出使能
IP核仿真
这大约是一个很烦的IP核。
FFT IP核原理:将长序列的DFT运算分解成短序列的DFT运算,同时利用旋转因子具有周期和对称的特点,将DFT运算进一步简化FFT。算法有两类:一种是基于时间的抽取算法,其二是基于频率抽取算法。
算法:分为 基 2-FFT 的时间抽取算法 和 基 2-FFT 的频率抽取算法;都是基于序列奇偶性;
接口图:
虽然接口看起来很多很烦,不如老版本的IP核简单易用,但是大部分新的Xilinx IP的接口其实是统一的,都是基于AXI协议的接口,所以使用方式上可以举一反三;
信号名称中以S开头的表示此信号是从信号,和上游信号连接;信号名称中以m开头的表示此信号是主信号,和下游信号连接;信号名称中以event开头的表示此信号是状态信号,可以反映IP的工作状态;
信号名称中有data的表示信号是数据信号,包含config表示配置信号,包含tvalid的表示有效信号,包含status表示状态信号,包含tlast表示最后一个信号,包含tready表示准备好反馈信号;
基本握手过程:当valid和ready同时为高时,传输就可以进行了;
需要考虑的接口信号有configuration sig,input sig,output sig,
Configuration channel:
主要配置s_axis_config_tdata这个信号,信号的结构为:
SCALE_SCH:缩放因子;仅在IFFT时使用,且仅在勾选了缩放选项时需要配置;
FWD/INV:为1表示FFT,为0表示IFFT;
CP_LEN:循环前缀的长度,长度为[log2(max_point)-1 : 0];仅在勾选了循环前缀选项时需要配置;
NFFT:变换点数;仅在勾选实时配置点数选项时才需要配置;
Input channel:
s_axis_data_tdata结构,要注意的地方就是都需要填充为8bit的倍数:
Output channel:
m_axis_data_tdata结构,要注意的地方同样是填充:
Event sig:
event_frame_started:当IP核开始处理新的一帧数据是输出一个脉冲;
event_tlast_unexpected:当输入的tlast信号不是真正的最后一个数据是输出一个脉冲;
event_tlast_missing:当是最后一个数据是tlast信号却没有指示时输出一个脉冲;
值得注意的是,当tvalid信号有效时,event_frame_started信号总是延时6个时钟周期输出脉冲,而tlast信号的输出则以和tvalid的间隔时间为准;例如1024点的FFT,那么tlast信号应该在tvalid信号拉高后1023个数据周期拉高;
整体仿真: