OFDM调制及解调系统的设计.docx
《OFDM调制及解调系统的设计.docx》由会员分享,可在线阅读,更多相关《OFDM调制及解调系统的设计.docx(29页珍藏版)》请在冰豆网上搜索。
OFDM调制及解调系统的设计
OFDM调制及解调系统的设计
一、基本原理概述
OFDM背景介绍
随着无线通信的迅速发展,以OFDM为代表的多载波调制技术凭借其强大的抗多径衰落能力和较高的频谱利用率,被认为是最有前途的4G方案之一。
OFDM通信技术是多载波传输技术的典型代表。
多载波传输把数据流分解为若干个独立的子载波比特流,每个子数据流将具有低得多的比特速率,用这样低比特速率形成的低速率多状态符号去调制相应的子载波,就构成了多个低速率符号并行发送的传输系统。
OFDM系统的基本原理
OFDM是一种多载波调制技术,其原理是用N个子载波把整个信道分割成N个子信道,即将频率上等间隔的N个子载波信号调制并相加后同时发送,实现N个子信道并行传输信息。
这样每个符号的频谱只占用信道带宽的1/N,且使各子载波在OFDM符号周期内保持频谱的正交性。
图1-1是在一个OFDM符号内包含4个子载波的实例。
其中,所有的子载波都具有相同的幅值和相位,但在实际应用中,根据数据符号的调制方式,每个子载波都有相同的幅值和相位是不可能的。
从图1-1可以看出,每个子载波在一个OFDM符号周期内都包含整数倍个周期,而且各个相邻的子载波之间相差1个周期。
这一特性可以用来解释子载波之间的正交性,即
图1-1 OFDM符号内包括4个子载波的情况
这种正交性还可以从频域的角度来解释,图1-2给出了相互覆盖的各个子信道内经过矩形波成形得到的符号sinc函数频谱。
每个子载波频率最大值处,所以其他子信道的频谱值恰好为零。
因为在对OFDM符号进行解调过程中,需要计算这些点上所对应的每个子载波频率的最大值,所以可以从多个相互重叠的子信道符号中提取每一个子信道符号,而不会受到其他子信道的干扰。
从图1-2中可以看出OFDM符号频谱实际上可以满足奈奎斯特准则,即多个子信道频谱之间不存在相互干扰。
因此这种子信道频谱出现最大值而其他子信道频谱为零的特点可以避免载波间干扰(ICI)的出现。
图1-2 OFDM系统中子信道符号的频谱
在发送端,设串行的码元周期为ts,速率为rs=1/ts。
经过串/并变换后N个串行码元被转换为长度为Ts=Nts、速率为Rs=1/Ts=1/Nts=rs/N的并行码。
N个码元分别调制N个子载波:
(n=0,1,2,…,N-1)
式中:
Δf为子载波的间隔,设计为
它是OFDM系统的重要设计参数之一。
当f0>>1/Ts时,各子载波是两两正交的,即
1,n=m
1,n≠m
输入的串行比特以L比特为一帧,每帧分为N组,每组比特数可以不同,第i组有qi个比特,即
第i组比特对应第i子信道的Mi=2qi个信号点。
这些复数信号点对应这些子信道的信息符号,用dn(n=0,1,2,…,N-1)表示。
利用IDFT可以完成{dn}的OFDM基带调制,因为式(4-147)的复包络可以表示为
则OFDM信号就为
若对A(t)以1/ts速率抽样,由式(4-147)得到:
可见,所得到的A(m)是{dn}的IDFT,或者说直接对{dn}求离散傅氏反变换就得到A(t)的抽样A(m)。
而A(m)经过低通滤波(D/A变换)后所得到的模拟信号对载波进行调制便得到所需的OFDM信号。
在接收端则进行相反的过程,把解调得到的基带信号经过A/D变换后得到dn,在经过并串变换输出。
当N比较大时可以采用高的效率IFFT(FFT)算法,现在已有专用的IC可用,利用它可以取代大量的调制解调器,使结构变得简单。
OFDM系统实现框图如下。
其中,上部分对应于发射机链路,下半部分对应于接收机链路,整个系统包含信道编/解码、数字调制/解调、IFFT/FFT、加/去保护间隔。
二、系统仿真设计方案
拟用MATLAB进行仿真。
采用自上而下的策略。
首先根据系统原理框图编写,然后再实现子程序模块,然后整合汇总成main_OFDM.m主函数。
根据OFDM系统原理,在此环境下仿真系统的构建可分为以下8部分:
信源、编码交织和解码去交织、调制映射和解调逆映射、OFDM发送和接收、并串和串并变换模块、信道、信道估计和信道补偿、误
码率计算模块。
仿真模型是建立在基带传输的基础上的,这是因为载波系统可以进行低通等效。
下图为基带系统框图。
OFDM发送和接受框图模型为:
具体包括了发送端的串并转换、训练序列的插入、过采样的IFFT变换及加入循环前缀和接收端的循环前缀的去除、FFT变换、去除虚子载波、训练序列的接收以及并串转换。
继续将系统框图细化:
信道估计仿真模型:
为了研究信道和噪声对OFDM传输系统的影响,采用加性高斯白噪声信道(AWGN)和多径瑞利衰落信道(MuhipathReyleighFading)模块进行仿真。
具体实现如下:
1.信道编码
信道编码采用卷积码和交织编码进行信道级联编码。
卷积码码率为1/2,仿真时设置k=1,G=[1011011;1111001],将输入的90个0、1二进制数经过卷积编码后可得到192个0、1二进制数。
交织编码采用24行8列的矩阵,按行写入,按列读出,交织编码可以有效的抗突发干扰。
卷积实现如下:
%************************beginningoffile*****************************
%cnv_encd.m
%卷积码编码程序
functionoutput=cnv_encd(G,k0,input)
%cnv_encd(G,k0,input),k0是每一时钟周期输入编码器的bit数,
%G是决定输入序列的生成矩阵,它有n0行L*k0列n0是输出bit数,
%参数n0和L由生成矩阵G导出,L是约束长度。
L之所以叫约束长度
%是因为编码器在每一时刻里输出序列不但与当前输入序列有关,
%而且还与编码器的状态有关,这个状态是由编码器的前(L-1)k0。
%个输入决定的,通常卷积码表示为(n0,k0,m),m=(L-1)*k0是编码
%器中的编码存贮个数,也就是分为L-1段,每段k0个
%有些人将m=L*k0定义为约束长度,有的人定义为m=(L-1)*k0
%查看是否需要补0,输入input必须是k0的整数部
%+++++++++++++++++++++++variables++++++++++++++++++++++++++++
%G决定输入序列的生成矩阵
%k0每一时钟周期输入编码器的bit数
%input输入数据
%output输入数据
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ifrem(length(input),k0)>0
input=[input,zeros(size(1:
k0-rem(length(input),k0)))];
end
n=length(input)/k0;
%检查生成矩阵G的维数是否和k0一致
ifrem(size(G,2),k0)>0
error('Error,Gisnotoftherightsize.')
end
%得到约束长度L和输出比特数n0
L=size(G,2)/k0;
n0=size(G,1);
%在信息前后加0,使存贮器归0,加0个数为(L-1)*k0个
u=[zeros(size(1:
(L-1)*k0)),input,zeros(size(1:
(L-1)*k0))];
%得到uu矩阵,它的各列是编码器各个存贮器在各时钟周期的内容
u1=u(L*k0:
-1:
1);
%将加0后的输入序列按每组L*k0个分组,分组是按k0比特增加
%从1到L*k0比特为第一组,从1+k0到L*k0+k0为第二组,。
。
。
。
,
%并将分组按倒序排列。
fori=1:
n+L-2
u1=[u1,u((i+L)*k0:
-1:
i*k0+1)];
end
uu=reshape(u1,L*k0,n+L-1);
%得到输出,输出由生成矩阵G*uu得到
output=reshape(rem(G*uu,2),1,n0*(L+n-1));
%************************endoffile***********************************
交织实现如下:
%************************beginningoffile*****************************
%interlacecode.m
functiondout=interlacecode(din,m,n)
%实现信道的交织编码
%din为输入交织编码器的数据,m,n分别为交织器的行列值
%+++++++++++++++++++++++variables++++++++++++++++++++++++++++
%din输入数据
%m交织器的行值
%n交织器的列值
%dout输出数据
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
forj=1:
m
temp(j,:
)=din(j*n-(n-1):
j*n);
end
dout_temp=reshape(temp,1,length(din));
dout=dout_temp(1:
end);
%************************endoffile**********************************
%************************beginningoffile*****************************
%qpsk.m
%QPSK调制映射
functiondout=qpsk(din)
%+++++++++++++++++++++++variables++++++++++++++++++++++++++++
%din输入数据
%dout输出数据
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
din2=1-2*din;
din_temp=reshape(din2,2,length(din)/2);
fori=1:
length(din)/2,
dout(i)=din_temp(1,i)+j*din_temp(2,i);
end
%************************endoffile***********************************
2.QPSK调制
在数字信号的调制方式中,使用了QPSK,这种调制方法具有较高的频谱利用率以及抗干扰性。
实现代码见附件。
3.插导频、矩阵变换
导频数据是在进行矩阵变换之前插入有效数据的,在系统设计中我们每8个有效数据插入一个导频,但是数据中间位置不插入导频。
96个复数据插入10个导频后,一帧数据长度为106。
矩阵变换是为了降低系统的PAPR,采用方法的是改进Nyquist脉冲调整法(PS)。
这里矩阵大小为106*128,滚将系数a=0.22。
具体实现如下:
%************************beginningoffile*****************************
%seq_train.m
%生成用于同步的训练符号
functiondout=seq_train()
%第一帧产生短训练序列,第二帧产生长训练序列
%每个短训练符号由16个子载波组成,短训练序列
%是由伪随机序列经过数字调制后插0后,再经过
%IFFT之后得到的。
具体过程如下:
首先采用抽头
%系数为[1001]的4级移位寄存器产生长度为
%15的伪随机序列之后末尾补0,经过QPSK调制之
%后的伪随机序列只在16的整数倍位置上出现,其
%余的位置补0,产生长度为128的序列,此序列再
%补128个0经过数据搬移后做256点的IFFT变换就
%得到16个以16为循环的训练序列,经过加循环前
%后缀就会产生20个相同的短训练序列。
长训练序
%列的产生同短训练序列。
globalseq_num
ifseq_num==1
fbconnection=[1001];
QPSKdata_pn=[m_sequence(fbconnection),0];
QPSKdata_pn=qpsk(QPSKdata_pn);
elseifseq_num==2
fbconnection=[1000001];
QPSKdata_pn=[m_sequence(fbconnection),0];
QPSKdata_pn=qpsk(QPSKdata_pn);
end
countmod=0;
fork=1:
128
ifseq_num==1
ifmod(k-1,16)==0%生成16位循环的短训练符号
countmod=countmod+1;
trainsp_temp(k)=QPSKdata_pn(countmod);
else
trainsp_temp(k)=0;
end
elseifseq_num==2
ifmod(k-1,2)==0
countmod=countmod+1;
trainsp_temp(k)=QPSKdata_pn(countmod);
else
trainsp_temp(k)=0;
end
end
end
dout=trainsp_temp;
%************************endoffile***********************************
4.IFFT变换
经过矩阵乘模块后,一帧数据长度为128,由于子载波个数为256,所以需要在数据后面补128个零。
具体实现如下:
%************************beginningoffile*****************************
%fft_my.m
%实现N点FFT运算
functiondout=fft_my(din)
%本程序对输入序列din实现DIT——FFT基2算法,点数取大于等于din长度的2的幂次
%+++++++++++++++++++++++variables++++++++++++++++++++++++++++
%din输入数据
%dout输出数据
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
m=nextpow2(din);
N=2^m;
iflength(din)din=[din,zeros(1,N-length(din))];
end
nxd=bin2dec(fliplr(dec2bin([1:
N]-1,m)))+1;
y=din(nxd);
formm=1:
m
Nmr=2^mm;
u=1;
WN=exp(-i*2*pi/Nmr);
forj=1:
Nmr/2
fork=j:
Nmr:
N
kp=k+Nmr/2;
t=y(kp)*u;
y(kp)=y(k)-t;
y(k)=y(k)+t;
end
u=u*WN;
end
end
dout=y;
%************************endoffile**********************************
5.加循环前后缀与升采样
用IFFT输出数据的钱32点作为循环后缀,后32点作为循环前缀。
假定射频的采样时钟为2.56MHz,所以需要数据速率匹配,对基带进行升采样。
采样过程由两部分组成。
第一部分对加了循环前后缀之后的数据进行2倍升采样,所采取的方式是在每个数据中间插入1个0;第二部分用上变频模块CIC内插滤波器对信号进行20倍升采样。
具体实现:
%add_GI_upsample.m
%加循环前后缀和升采样程序
functiondout=add_CYC_upsample(din,upsample)
%插入循环前后缀是将每个OFDM符号的前32个数据放
%到符号尾部,将每个OFDM符号的后32个数据放到符号头部,
%升采样是通过中间插零的方式实现
%+++++++++++++++++++++++variables++++++++++++++++++++++++++++
%din输入数据
%upsample升采样倍数
%dout输出数据
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
data_buf=[din(225:
256),din,din(1:
32)];
temp(1,:
)=data_buf;
temp(2:
upsample,:
)=zeros(upsample-1,length(data_buf));
dout_temp=reshape(temp,1,length(data_buf)*upsample);
dout=dout_temp(1:
end);
%************************endoffile*********************************
6.系统的同步
将基带信号送到帧检测模块,目的是系统需要知道是否有信号到达和信号来到后粗定时的位置,当检测到信号来到后同时启动粗定时模块、频偏捕获模块。
符号粗定时与粗频偏捕获利用的是前导序列中的短序列来实现的,二细频偏估计采用的是前导序列中的长训练序列实现的。
然后,利用前导序列中的Tm1和Tm2进行本地互相关,得到相关峰值,通过峰值所确定的位置确定精确的FFT开窗位置,并通过OFDM数据帧中的循环前后缀的循环特性进行频率跟踪,在频域中,再利用解调出的导频信息进行相位补偿。
实现框图:
(具体实现见附件)
7.主函数模块
%main_OFDM.m
%这是一个相对完整的OFDM通信系统的仿真设计,包括编码,调制,IFFT,
%上下变频,高斯信道建模,FFT,PAPR抑制,各种同步,解调和解码等模
%块,并统括系统性能的仿真验证了系统设计的可靠性。
clearall
closeall
clc
%++++++++++++++++++++++++++全局变量++++++++++++++++++++++++++++++
%seq_num表示当前帧是第几帧
%count_dds_up上变频处的控制字的累加
%count_dds_down下变频处的控制字的累加(整整)
%count_dds_down_tmp下变频处的控制字的累加(小数)
%dingshi定时同步的定位
%m_syn记录定时同步中的自相关平台
globalseq_num
globalcount_dds_up
globalcount_dds_down
globalcount_dds_down_tmp
globaldingshi
globalm_syn
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%SNR_Pre设定用于仿真的信噪比的初值
%interval_SNR设定用于仿真的信噪比间隔
%frame_num每一个信噪比下仿真的数据帧数
%err_int_final用于计算每帧出现的误比特数
%fwc_down设定的接收机初始载波频率控制字
%fre_offset设定接收机初始载波频率偏移调整量(单位为Hz)
%k0每次进入卷积编码器的信息比特数
%G卷积编码的生成矩阵
SNR_Pre=-5;
interval_SNR=1;
forSNR_System=SNR_Pre:
interval_SNR:
5
frame_num=152;
dingshi=250;
err_int_final=0;
fwc_down=16.050;
fre_offset=0;
k0=1;
G=[1011011;1111001];
disp('--------------start-------------------');
forseq_num=1:
frame_num,%frame_num帧数
%+++++++++++++++++++++++以下为输入数据部分+++++++++++++++++++++++
datain=randint(1,90);
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%++++++++++++++++++++++以下为信道卷积编码部分+++++++++++++++++++++
encodeDATA=cnv_encd(G,k0,datain);
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%+++++++++++++++++++++++++++信道交织编码+++++++++++++++++++++++++
interlacedata=interlacecode(encodeDATA,8,24);
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%+++++++++++++++++++++++++以下为QPSK调制部分+++++++++++++++++++++
QPSKdata=qpsk(interlacedata);
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%+++++++++++++++++++++++++++生成训练序列+++++++++++++++++++++++++
ifseq_num<3
trainsp_temp=seq_train();
end
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
%++++++++++++++++++++++++++++插入导频++++++++++++++++++++++++++++
PILOT=(1+j);
m_QPSKdata=QPSKdata;
data2fft_temp=[m_QPSKdata(1:
8),PILOT,m_QPSKdata(9:
16),PILOT,m_QPSKdata(17:
24),PILOT,m_QPSKdata(25:
32),PILOT,m_QPSKdata(33:
40),PILOT,m_QPSKdata(41:
48),m_QPSKdata(49:
56),PILOT,m_QPSKdata(57:
6