OQPSK基于MATLAB/FPGA的OQPSK实现
Posted fpga&matlab
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OQPSK基于MATLAB/FPGA的OQPSK实现相关的知识,希望对你有一定的参考价值。
1.软件版本
ISE14.7
2.本算法理论知识
OQPSK也称为偏移四相相移键控(offset-QPSK),是QPSK的改进型。它与QPSK有同样的相位关系,也是把输入码流分成两路,然后进行正交调制。不同点在于它将同相和正交两支路的码流在时间上错开了半个码元周期。由于两支路码元半周期的偏移,每次只有一路可能发生极性翻转,不会发生两支路码元极性同时翻转的现象。因此,OQPSK信号相位只能跳变0°、±90°,不会出现180°的相位跳变。
OQPSK信号可采用正交相干解调方式解调,其原理如图5-49所示。由图看出,它与QPSK信号的解调原理基本相同,其差别仅在于对Q支路信号抽样判决时间比I支路延迟了/2,这是因为在调制时Q支路信号在时间上偏移了/2,所以抽样判决时刻也应偏移/2,以保证对两支路交错抽样。
OQPSK克服了QPSK的l80°的相位跳变,信号通过BPF后包络起伏小,性能得到了改善,因此受到了广泛重视。但是,当码元转换时,相位变化不连续,存在90°的相位跳变,因而高频滚降慢,频带仍然较宽。
采用非归零码直接进行调制所得的QPSK信号的幅度非常恒定,但其信号频谱较大。然而,当QPSK进行波形成形时,它们将失去恒包络的性质。偶尔发生的弧度为π的相移,会导致信号的包络在瞬间通过零点。任何一种在过零点的硬限幅或非线性放大都会引起旁瓣再生和频谱扩展,必须使用效率较低的线性放大器放大QPSK信号,这将使放大器的效率受到限制,进而影响到终端的小型化。
为了克服QPSK对信道的线性度要求很高,交错QPSK(OQPSK)或参差QPSK虽然在非线性环境下也会产生频谱扩展,但对此已不那么敏感,因此能支持更高效率的放大器。
在OQPSK中,其I支路比特流和Q支路比特流在数据沿上差半个符号周期,其它特性和QPSK信号类似。在QPSK信号中,奇比特流和偶比特流的比特同时跳变,但是在OQPSK信号中,I支路比特流和Q支路比特流,在它们的变化沿的地方错开一比特(半个符号周期)。它们的波形如图下图:
由于在标准QPSK中,相位跳变仅在每个Ts=2TB秒时发生,并且存在180°的最大相移。可是在OQPSK信号中,比特跳变(从而相位跳变)每Tb秒发生一次。因为I支路和Q支路的跳变瞬时被错开了,所以在任意给定时刻只有两个比特流中的一个改变它的值。这意味着,在任意时刻发送信号的最大相移都限制在±90°。因此OQPSK信号消除了180°相位跳变,改善了其包括特性。
图2
从上图中的星座图看出,180°相位跳变消除了,所以OQPSK信号的带限不会导致信号包络经过零点。OQPSK包络的变化小多了,因此对OQPSK的硬限幅或非线性放大不会再生出严重的频带扩展现,OQPSK即使在非线性放大后仍能保持其带限的性质,这就非常适合移动通信系统,因为在低功率应用情况下,带宽效率和高效非线性放大器是起决定性作用的。还有,当在接收机端由于参考信号的噪声造成相位抖动时,OQPSK信号表现的性能比QPSK要好。
OQPSK复基带信号可以表示为:
在OQPSK调制解调器设计中成形滤波、数字下变频、载波恢复和定时恢复是实现OQPSK调制解调器的难点和重点。
在数字通信系统中,由于基带码元采用矩形波表示,其频谱是无限宽,当信号通过实际带限信道,频域截短,时域变为无限,产生码间串扰,为了克服码间串扰,需要对码元进行成形滤波。实际应用中,大多采用升余弦滤波器作为成形滤波器。
具有滚降系数α的升余弦滚降特性H(ω)可表示为:
而相应的h( t)为:
升余弦滚降信号在前后抽样值处的码间串扰为0,满足抽样值无失真传输条件,滚降系数α越小,则波形的振荡起伏就越大,但传输频带减小,对接收端的定时要求增加;反之,α越大,则波形振荡起伏越小,但频带增加。α=0时,升余弦滤波器变成了理想低通滤波器,此时信号的频带最窄;α=1时,升余弦滤波器的频带最宽,为理想低通滤波器的2倍。所以,升余弦滚降滤波器是以频带的增加来换取码间干扰的减少。
从工作原理上讲,数字下变频与模拟下变频是一样的,就是输入信号与一个本地振荡信号的乘法运算。与模拟下变频相比,数字下变频的运算速度受DSP处理速度的限制,同时,其运算速度决定了其输入信号的数据流可达到最高速率,相应地也限定了ADC的最高采样速率;另外,数字下变频的数据精度和运算速度也影响着接收机的性能,所以,数字下变频器必须进行优化设计。
3.部分核心代码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 13:28:31 01/23/2009
// Design Name:
// Module Name: qpsk_fa
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
`define bw_mod 10
`define bw_s_c 8
`define bw_two 2
module qpsk_fa(
//input
clk, //8m
rst,
I,
Q,
cos,
sin,
I_cos,
Q_sin,
r
);
parameter NUM=400;
parameter IND= 29'd6710886;
parameter IND1=29'd000000;
input clk;
input rst;
input I;
input Q;
output signed [`bw_s_c-1:0] cos; //8
output signed [`bw_s_c-1:0] sin; //8
output signed [`bw_mod-1:0] I_cos; //16
output signed [`bw_mod-1:0] Q_sin; //16
output signed [`bw_mod-1:0] r; //16
wire signed [`bw_s_c-1:0] cos; //8
wire signed [`bw_s_c-1:0] sin; //8
reg signed [`bw_mod-1:0] I_cos; //16
reg signed [`bw_mod-1:0] Q_sin; //16
reg signed [`bw_two-1:0] I2; //2
reg signed [`bw_two-1:0] Q2; //2
reg signed [`bw_mod-1:0] r;
reg signed [`bw_mod-1:0] r1;
//--------------------generate the head of sys-------------------------------
reg[31:0]i;
always @(posedge clk or negedge rst)
begin
if(!rst)
i<=32'b0000_0000_0000_0000_0000_0000_0000_0000;
else begin
if(i==NUM)
i<=NUM;
else
i<=i+1'b1;
end
end
reg I_tmp;
reg Q_tmp;
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
I_tmp<=0;
Q_tmp<=0;
end
else begin
if(i<NUM)
begin
I_tmp<=1'b1;
Q_tmp<=1'b1;
end
else
begin
I_tmp<=I;
Q_tmp<=Q;
end
end
end
//=================one->two================================================
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
I2<=2'b00;
Q2<=2'b00;
end
else begin
I2<=(I_tmp==1)?2'b01:2'b11;
Q2<=(Q_tmp==1)?2'b01:2'b11;
end
end
sin_cos0 sin_cos0_u(
.reg_select (1'b0),
.clk (clk),
.we (rst),
.data (IND),
.sine (sin),
.cosine (cos)
);
//==================进行调制=================================================
wire signed[9:0]I_COS_tmp;
wire signed[9:0]Q_SIN_tmp;
mult mult_u1(
.sclr (~rst),
.clk (clk),
.a (I2),
.b (cos),
.p (I_COS_tmp)
);
mult mult_u2(
.sclr (~rst),
.clk (clk),
.a (Q2),
.b (sin),
.p (Q_SIN_tmp)
);
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
I_cos<=10'h0000;
Q_sin<=10'h0000;
end
else begin
I_cos<=I_COS_tmp;
Q_sin<=Q_SIN_tmp;
end
end
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
r1<=10'd0;
end
else begin
r1<=I_cos+Q_sin;
end
end
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
r<=10'd0;
end
else begin
r<=r1;
end
end
endmodule
clc;
clear;
N=200;
I_data=zeros(1,N); %I支路符号
Q_data=zeros(1,N); %Q支路符号
for n1=1:N
bits(n1)=binornd(1,0.5,1,1);%信源比特流
end
for no=1:(N/2)
I_bits(no)=bits(2*no-1); %I支路比特流
end
for ne=1:(N/2)
Q_bits(ne)=bits(2*ne); %Q支路比特流
end
Flag=1;
%I支路符号
for no=1:N
Flag=-Flag;
if Flag==1
I_data(no)=1;
elseif Flag==-1
I_data(no)=-1;
end
end
%Q支路符号
for no=1:N
Flag=-Flag;
if Flag==1
Q_data(no)=1;
elseif Flag==-1
Q_data(no)=-1;
end
end
figure(1)
subplot(211),stairs(I_data);
axis([0,length(Q_bits),-2,2]);
subplot(212),stairs(Q_data);
axis([0,length(Q_bits),-2,2]);
fc=4; %载波频率
fs=40; %采样频率
T=1;
samples=T*fs; %每符号内的采样点数
t=0:T/samples:(T-T/samples);
sin_c=sin(2*pi*fc*t);
cos_c=cos(2*pi*fc*t);
windows=ones(1,length(cos_c)); %矩形窗
%生成调制信号I支路调制信号
for n1=1:length(I_data)
data_number((samples*(n1-1)+1):(samples*(n1-1)+samples))=(I_data(n1)*sin_c).*windows;
end
figure(2)
Sit=data_number;
subplot(211),plot(Sit);
title('I支路');
axis([0,length(data_number),-2,2]);
%生成Q支路调制信号
for n1=1:length(I_data)
data_number((samples*(n1-1)+1):(samples*(n1-1)+samples))=(Q_data(n1)*cos_c).*windows;
end
Sqt=data_number;
subplot(212),plot(Sqt);
title('Q支路');
axis([0,length(data_number),-2,2]);
St=Sit+Sqt;
figure(3)
plot(St)
title('OQPSK仿真波形图');
axis([0,length(St),-4,4]);
%========================信号解调=====================
for n1=1:200
I_data_number((samples*(n1-1)+1):(samples*(n1-1)+samples))=(St((samples*(n1-1)+1):(samples*(n1-1)+samples)).*sin_c(1:samples));
end
%
for n1=1:200
Q_data_number((samples*(n1-1)+1):(samples*(n1-1)+samples))=(St((samples*(n1-1)+1):(samples*(n1-1)+samples)).*cos_c(1:samples));
end
%
figure(4)
subplot(211),plot(I_data_number);
subplot(212),plot(Q_data_number);
%======================信号滤波=======================================
Ts=1/1000 ;%设置采样频率
N=128; %设置阶数
n=[0:(N-1)];
Wn=0.2; %设置截止频率
t=0:Ts:3*pi;
x=win(0,N-1,0,N-1);
x=(0.5-0.5*cos(2*pi*n/(N-1))).*x;
[B,A]=fir1(N,Wn,'low',hann(N+1)); I_data_number_Win=filter(B,A, I_data_number);
[B,A]=fir1(N,Wn,'low',hann(N+1)); Q_data_number_Win=filter(B,A, Q_data_number);
figure(5)
subplot(211),plot(I_data_number_Win);
subplot(212),plot(Q_data_number_Win);
%=====================符号判决==============================================
for i=1:8000
if I_data_number_Win(i)>=0
I_r(i)=1;
end
if I_data_number_Win(i)<0
I_r(i)=-1;
end
end
for i=1:8000
if Q_data_number_Win(i)>=0
Q_r(i)=1;
end
if Q_data_number_Win(i)<0
Q_r(i)=-1;
end
end
figure(6)
subplot(211),plot(I_r);axis([0,length(I_r),-2,2]);
subplot(212),plot(Q_r);axis([0,length(Q_r),-2,2]);
4.仿真结论
这里成形滤波器的设计主要通过IP核来设计,通过MATLAB我们可以得到滤波器的系数:
Radix = 10;
Coefficient_Width = 18;
CoefData = 0.02022066,
0.00443409,
-0.03751318,
-0.07842133,
-0.05305165,
0.07842133,
0.28931623,
0.48724768,
0.56830989,
0.48724768,
0.28931623,
0.07842133,
-0.05305165,
-0.07842133,
-0.03751318,
0.00743409,
0.02022066;
这里是IP核所要调用的COE文件的文件格式,这些数据是FIR滤波器所采用的系数,这些系数是通过MATLAB来得到的。
具体IP核参数设置如下所示:
图1 参数设置一
图2 参数设置2
通过这个设置,我们可以得到FIR滤波器的基本参数功能如下所示:
图3 FIR滤波器设置效果
以上我们基本完成了RRC滤波器的设计过程。
这里要设计一个NCO来完成发送端的调制过程,主要利用ISE的NCO-IP核来完成。这里的参数设置比较简单,就不做具体介绍了,新建一个IP核,打开NCO核生成器。
其基本参数的设置如下:
图4 NOC参数设置1
图5 NOC参数设置2
图6 NOC参数设置3
通过以上设置,我们基本完成了NOC模块的设置,通过NCO-IP核可以得到SIN,COS两个载波的波形。
首先,信号通过成形滤波器后得到的波形如下图所示:
图7 发送的01信号
由上图可以看到,1,0,1,0信号通过滤波器后可以得到滤波信号。从而验证了这个模块的正确性。
同时发送段产生载波,这里产生SIN,COS载波。
图8 本地载波
同时将信号和载波进行相乘,得到调制信号。
图9 调制信号
下面的波形就是信号通过COSTAS滤波器后的信号。通过COSTAS后,信号基本和原来的信号匹配了,说明COSTAS是正确的。
图10 解调以后的信号
以上结果表明:信号通过COSTAS后,得到了基本的还原。
5.参考文献
A01-112
以上是关于OQPSK基于MATLAB/FPGA的OQPSK实现的主要内容,如果未能解决你的问题,请参考以下文章
通信算法之112:载波同步及comm.CarrierSynchronizer
OFDM-FPGA基于MATLAB/FPGA的基础OFDM系统的实现