1.算法仿真效果
vivado2019.2仿真结果如下(完整代码运行后无水印):
设置SNR=1db
设置SNR=5db
设置SNR=10db
和之前开发的普通QPSK调制解调系统相比,软解调误码率更低。
基于FPGA的QPSK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR_fpga qpsk-CSDN博客
仿真操作步骤可参考程序配套的操作视频。
2.算法涉及理论知识概要
QPSK是一种常用的调制方式,通过将两个比特映射到一个复平面上的相位点,实现了高效的信号传输。软解调是一种基于接收信号的概率估计进行解调的方法,能够提供更好的性能。本文将逐步介绍QPSK软解调的实现过程,包括信号采样、相位估计、判决和解调等方面。软解调是一种通过概率估计实现解调的方法,能够在信道噪声存在的情况下提供更好的性能。QPSK是一种常用的调制方式,通过将两个比特映射到相位点,实现了高效的信号传输。本文旨在详细介绍QPSK软解调的实现过程,包括信号采样、相位估计、判决和解调等步骤。
2.1 信号采样
接收到的QPSK信号经过采样操作,得到离散时间信号序列。采样率需要满足奈奎斯特采样定理,通常为比特速率的两倍。
2.2 判决
在QPSK信号解调中,判决过程用于确定每个信号符号的二进制比特值。判决过程根据接收信号的相位进行划分,将其映射到不同的比特值。
假设接收到的信号序列为r[n],判决过程的结果为判决符号d_hat。常见的判决公式为:
if theta_hat > -pi/4 && theta_hat <= pi/4
d_hat = [1, 1]
elseif theta_hat > pi/4 && theta_hat <= 3pi/4
d_hat = [0, 1]
elseif theta_hat > 3pi/4 || theta_hat <= -3*pi/4
d_hat = [0, 0]
else
d_hat = [1, 0]
end
2.3 解调
解调过程将判决的比特值转换为原始数据比特。解调过程根据映射表将判决比特值转换为原始数据比特。假设判决比特值为d_hat,解调过程的结果为解调比特d。常见的解调公式为:
if d_hat == [1, 1]
d = [0, 0]
elseif d_hat == [0, 1]
d = [0, 1]
elseif d_hat == [0, 0]
d = [1, 0]
else
d = [1, 1]
end
2.4 软解调
软解调是QPSK软解调的关键步骤,它利用判决符号和相位估计的结果进行概率估计,以提高解调的准确性。假设判决符号为d_hat,软解调过程的结果为软解调符号d。常见的软解调公式为: d = d_hat / P(d_hat|r[n])
其中P(d_hat|r[n])表示在接收到信号r[n]的条件下,判决符号d_hat为d_hat的概率。该概率可以通过估计信号点的概率分布函数或使用最大似然估计等方法得到。软解调过程需要进行概率估计,以提高解调的准确性。这涉及到估计信号点的概率分布函数或使用其他概率估计方法,其中噪声的影响需要被适当地考虑。
3.Verilog核心程序
TQPSK TQPSKU(
.i_clk (i_clk),
.i_rst (i_rst),
.i_Ibits(i_Ibits),
.i_Qbits(i_Qbits),
.o_Ifir (o_Ifir),
.o_Qfir (o_Qfir),
.o_cos (),
.o_sin (),
.o_modc (),
.o_mods (),
.o_mod (o_mod_T)
);
//加入信道
awgns awgns_u(
.i_clk(i_clk),
.i_rst(i_rst),
.i_SNR(i_SNR), //这个地方可以设置信噪比,数值大小从-10~50,
.i_din(o_mod_T[30:15]+o_mod_T[31:16]),
.o_noise(),
.o_dout(o_Nmod_T)
);
//QPSK解调
wire signed[15:0]o_b1;
wire signed[15:0]o_b2;
RQPSK RQPSKU(
.i_clk (i_clk),
.i_clkSYM(i_clkSYM),
.i_rst (i_rst),
.i_med (o_Nmod_T),
.o_cos (),
.o_sin (),
.o_modc (o_modc),
.o_mods (o_mods),
.o_Ifir (o_rIfir),
.o_Qfir (o_rQfir),
.o_b1(o_b1),
.o_b2(o_b2)
);
//计算误码率
//I,Q两路分别计算,最后统计平均值作为误码率
//error calculate
wire [31:0]w_error_num1;
wire [31:0]w_error_num2;
Error_Chech Error_Chech_u1(
.i_clk(i_clk),
.i_rst(i_rst),
.i_trans({~i_Ibits,1'b1}),
.i_rec({~o_b1[15],1'b1}),
.o_error_num(w_error_num1),
.o_total_num()
);
//error calculate
Error_Chech Error_Chech_u2(
.i_clk(i_clk),
.i_rst(i_rst),
.i_trans({~i_Qbits,1'b1}),
.i_rec({o_b2[15],1'b1}),
.o_error_num(w_error_num2),
.o_total_num(o_total_num)
);
assign o_error_num={w_error_num1[31],w_error_num1[31:1]} + {w_error_num2[31],w_error_num2[31:1]} ;
endmodule
0sj_019m