m基于FPGA的带相位偏差QPSK调制信号相位估计和补偿算法verilog实现,包含testbench

目录

1.算法仿真效果

2.算法涉及理论知识概要

2.1、问题描述

2.2、算法原理

2.3 相位偏差估计

2.4相位偏差补偿

2.5V&V算法

3.Verilog核心程序

4.完整算法代码文件


扫描二维码关注公众号,回复: 15493737 查看本文章

1.算法仿真效果


本系统进行Vivado2019.2平台的开发,其中Vivado2019.2仿真结果如下:

 将FPGA的仿真结果导入到matlab中,对比星座图,如下所示:

 

2.算法涉及理论知识概要

       相位偏差是数字通信系统中常见的问题,在QPSK调制通信系统中也同样存在。相位偏差可能导致误码率的增加和系统性能下降。因此,相位偏差的估计和补偿是数字通信系统中一个重要的问题。本文提出了一种基于V&V算法的带相位偏差QPSK调制信号相位估计和补偿方法,提高QPSK调制通信系统的性能。

2.1、问题描述

      在QPSK调制通信系统中,接收信号可以表示为:

$$
r(t)=Acos(2\pi f_ct+\phi)+n(t)
$$

其中,A是信号的振幅,f_c是载波频率,phi是相位偏差,n(t)是噪声。

我们的目标是估计相位偏差$\phi$并对其进行补偿,以提高通信系统的性能。

2.2、算法原理

QPSK调制信号可以表示为:

$$
s(t)=\sqrt{\frac{2E_s}{T_s}}[cos(2\pi f_ct)+cos(2\pi f_ct+\pi)][p_1(t)+p_2(t)]
$$

       其中,E_s是每个符号的能量,T_s是每个符号的持续时间,f_c是载波频率,p_1(t)和p_2(t)是两个正交的基带信号。

2.3 相位偏差估计


       为了估计相位偏差,我们可以选择频谱中的两个点$f_1$和$f_2$,分别对应于信号的正频率和负频率,然后计算这两个点之间的相位差$\Delta\phi$:

$$
\Delta\phi=\angle R(f_1)-\angle R(f_2)-\pi
$$

其中,$R(f_1)$和$R(f_2)$分别是频率为$f_1$和$f_2$的复数振幅。

2.4相位偏差补偿


       为了补偿相位偏差,我们可以将接收信号乘以一个相位旋转因子$e^{-j\hat{\phi}}$,其中$\hat{\phi}$是相位偏差的估计值。这样,我们可以得到补偿后的信号:

$$
r_c(t)=Acos(2\pi f_ct)+n(t)e^{-j\hat{\phi}}
$$

2.5V&V算法


       V&V算法是一种常用的相位偏差估计方法,该方法通过对接收信号进行FFT变换和相关运算来进行相位偏差的估计。

       具体而言,我们可以将接收信号进行离散傅里叶变换(DFT)得到频谱图,然后选择频谱图中两个点$f_1$和$f_2$,分别对应于信号的正频率和负频率。然后,我们可以计算这两个点之间的自相关函数$R_{xx}(k)$:

$$
R_{xx}(k)=\frac{1}{N}\sum_{n=0}^{N-1}x(n)x^*(n-k)
$$

其中,$x(n)$是DFT变换后的接收信号,$N$是信号的长度。

根据自相关函数$R_{xx}(k)$,我们可以得到相位偏差的估计值:

$$
\hat{\phi}=-\frac{1}{2}\angle R_{xx}(1)
$$

       基于V&V算法的带相位偏差QPSK调制信号相位估计和补偿方法,该方法通过对接收信号进行FFT变换和相关运算来进行相位偏差的估计和补偿,从而提高QPSK调制通信系统的性能。实验结果表明,该算法可以有效地估计和补偿相位偏差,具有一定的实用价值。

3.Verilog核心程序

.............................................................

//QPSK调制
TQPSK TQPSKU(
.i_clk  (i_clk),
.i_rst  (i_rst),
.i_clkSYM(i_clkSYM),
.i_dat  (i_dat),
.o_Idiff(o_Idiff),
.o_Qdiff(o_Qdiff),

.o_Ifir (o_Ifir_T),
.o_Qfir (o_Qfir_T),
.o_cos  (o_cos_T),
.o_sin  (o_sin_T),
.o_modc (o_modc_T),
.o_mods (o_mods_T),
.o_mod  (o_mod_T)
);

 


//QPSK相位估计和补偿
RQPSK_phase_est RQPSKU(
.i_clk  (i_clk),
.i_rst  (i_rst),
.i_clkSYM(i_clkSYM),
.i_med  (o_mod_T[25:10]),
.o_cos  (o_cos_R),
.o_sin  (o_sin_R),
.o_modc (o_modc_R),
.o_mods (o_mods_R),
.o_Ifir (o_Ifir_R),
.o_Qfir (o_Qfir_R),
.o_I_phase(o_I_phase),
.o_Q_phase(o_Q_phase),
.o_phase(o_phase)
);
reg writeen;
initial
begin
    writeen = 1'b0;
    i_clk = 1'b1;
    i_clkSYM=1'b1;
    i_rst = 1'b1;
    #1600
    i_rst = 1'b0;
    
    #100
    writeen = 1'b1;
end

always #5 i_clk=~i_clk;
always #80 i_clkSYM=~i_clkSYM;


initial
begin
    i_dat = 1'b0;
    #1440
    repeat(10)
    begin
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    end
    
    repeat(10)
    begin
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    end
    repeat(10)
    begin
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b0;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b1;
    #160 i_dat = 1'b0;
    end
    $stop();
end


//显示发射端带相位旋转的星座图
integer fout1;
integer fout2;
initial begin
 fout1 = $fopen("It.txt","w");
 fout2 = $fopen("Qt.txt","w"); 
end

always @ (posedge i_clk)
 begin
     if(writeen==1)
     begin
   	 $fwrite(fout1,"%d\n",o_Ifir_T);
	 $fwrite(fout2,"%d\n",o_Qfir_T);
	 end
end

显示接收端相位估计和补偿之后的星座图

integer fout3;
integer fout4;
initial begin
 fout3 = $fopen("IR.txt","w");
 fout4 = $fopen("QR.txt","w"); 
end

always @ (posedge i_clk)
 begin
     if(writeen==1)
     begin
   	 $fwrite(fout3,"%d\n",o_I_phase);
	 $fwrite(fout4,"%d\n",o_Q_phase);
	 end
end
 

endmodule
00_020m

4.完整算法代码文件

V

猜你喜欢

转载自blog.csdn.net/hlayumi1234567/article/details/131448185
今日推荐