m基于FPGA的带相位偏差16QAM调制信号相位估计和补偿算法verilog实现

目录

1.算法仿真效果

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

2.1. 16QAM调制信号的基本原理

2.2. 相位偏差的处理方法

2.3. VV算法的原理和实现步骤

3.Verilog核心程序

4.完整算法代码文件


1.算法仿真效果

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

 

将FPGA的仿真结果导入到matlab显示星座图。 

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

       从以下几个方面进行介绍:16QAM调制信号的基本原理、相位偏差的处理方法、VV算法的原理和实现步骤等。

2.1. 16QAM调制信号的基本原理

     16QAM调制是一种常见的数字调制方式,其将四个二进制比特映射到一个复平面上的16个点,如图1所示。16QAM调制信号可以表示为:

$$s(t)=A_c \sum_{n=0}^{N-1}a_np(t-nT)cos(2\pi f_ct+\phi_n)$$

       其中,$A_c$是载波幅度,$a_n$是二进制比特,$p(t)$是脉冲成形滤波器,$T$是符号间隔,$f_c$是载波频率,$\phi_n$是相位。

<center>图1. 16QAM调制信号映射图</center>


2.2. 相位偏差的处理方法


      在实际应用中,16QAM调制信号的相位可能会受到多种因素的影响,如噪声、多径衰落等,从而导致信号存在相位偏差。为了保证信号的正确解调,需要对信号进行相位估计和补偿。

相位估计和补偿的一般流程包括以下几个步骤:

选择合适的相位参考信号,例如载波信号或训练序列等。

提取接收信号的相位信息,例如使用差分解调器提取相位差等。

        对相位信息进行滤波和处理,例如使用低通滤波器平滑相位信息,使用PLL等算法进行相位跟踪等。

根据估计得到的相位信息,对信号进行相位补偿,以消除相位偏差。

2.3. VV算法的原理和实现步骤


       VV算法是一种基于相位差的相位估计算法,它可以对16QAM调制信号的相位进行高精度的估计和补偿。VV算法的原理如下:

将16QAM调制信号分为实部和虚部两路,分别进行差分解调,得到相位差$\Delta\phi$。

对相位差进行累积,并进行非线性处理,得到相位估计值。

根据相位估计值,对信号进行相位补偿。

VV算法的实现步骤如下:

对接收信号进行采样和定时,并进行载波恢复,得到16QAM调制信号的实部和虚部。

对实部和虚部分别进行差分解调,得到相位差$\Delta\phi$。

对相位差进行累积和非线性处理,得到相位估计值$\hat{\phi}$。累积和非线性处理可以表示为:

$$\hat{\phi}[k+1]=\hat{\phi}[k]+\frac{1}{2\pi}\Delta\phi[k]-sign(\hat{\phi}[k])\cdot\frac{\pi}{4}$$

其中,$k$表示采样时刻,$sign$表示符号函数。

根据相位估计值,对信号进行相位补偿。相位补偿可以表示为:
$$s'(t)=s(t)e^{-j\hat{\phi}}$$

其中$s(t)$是接收到的16QAM调制信号,$s'(t)$是补偿后的信号。

        最后,将补偿后的信号进行解调和解码,得到原始的二进制比特流。需要注意的是,VV算法的实现需要使用高精度的浮点运算,因此需要使用FPGA等硬件加速器来实现。在实现过程中,需要根据具体的硬件平台和信号特性进行优化,以达到较高的运算速度和较低的资源消耗。

3.Verilog核心程序


module TEST;

	reg clk;
	reg rst;
	reg start;

    wire  [3:0] parallel_data;
    wire [15:0]sin;
    wire [15:0]cos;
	wire signed[19:0]  I_com;
	wire signed[19:0]  Q_com;
	wire signed[19:0]  I_com2;
	wire signed[19:0]  Q_com2;
    wire signed[15:0]I_comcos;
    wire signed[15:0]Q_comsin;
	 

	// DUT
	tops_16QAM_mod  top(
	   .clk(clk),
	   .rst(rst),
	   .start(start),
	   .parallel_data(parallel_data),
	   .sin(sin),
	   .cos(cos),
	   .I_com(I_com),
	   .Q_com(Q_com),
	   .I_com2(I_com2),
	   .Q_com2(Q_com2),
	   .I_comcos(I_comcos),
	   .Q_comsin(Q_comsin)
	   );
	   
	   
wire signed[23:0]I_comcos2;
wire signed[23:0]Q_comsin2;
wire signed[7:0]o_Ifir;
wire signed[7:0]o_Qfir;
wire signed[15:0]o_Ifir_phase;
wire signed[15:0]o_Qfir_phase;
wire signed[31:0]o_phase;
tops_16QAM_phase_est  top2(
	   .clk(clk),
	   .rst(rst),
	   .start(start),
	   .I_comcos(I_comcos),
	   .Q_comsin(Q_comsin),
	   .I_comcos2(I_comcos2),
	   .Q_comsin2(Q_comsin2),
	   .o_Ifir(o_Ifir),
	   .o_Qfir(o_Qfir),
	   .o_I_phase(o_Ifir_phase),
	   .o_Q_phase(o_Qfir_phase),
	   .o_phase(o_phase)
	   );  
	   
 
	initial begin
		clk = 0;
		rst = 0;
		start = 1;
		#10;
		rst = 1;
	end
	
	always #5
	clk <= ~clk;
	
	
reg writeen;
initial
begin
    writeen = 1'b0;
    #150000
    writeen = 1'b1;
end
	
reg[4:0]divcnt;	
always @(posedge clk or negedge rst)
begin
     if(~rst)
	  begin
	  divcnt<={5{1'b0}};	
	  end
else begin
	  divcnt<=divcnt+{5{1'b1}};
     end
end 
	
	
	
integer fout1;
integer fout2;
initial begin
 fout1 = $fopen("It.txt","w");
 fout2 = $fopen("Qt.txt","w"); 
end

always @ (posedge divcnt[4])
 begin
     if(writeen==1)
     begin
   	 $fwrite(fout1,"%d\n",I_com2);
	 $fwrite(fout2,"%d\n",Q_com2);
	 end
end




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

always @ (posedge divcnt[4])
 begin
     if(writeen==1)
     begin
   	 $fwrite(fout3,"%d\n",o_Ifir_phase);
	 $fwrite(fout4,"%d\n",o_Qfir_phase);
	 end
end
 

endmodule
00_021m

4.完整算法代码文件

V

猜你喜欢

转载自blog.csdn.net/hlayumi1234567/article/details/131491791