基于FPGA的16QAM调制+软解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR

71 阅读4分钟

1.算法仿真效果

vivado2019.2仿真结果如下(完整代码运行后无水印):

 

设置SNR=8db

6460d809278525446d955f5cfc4f8efe_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.jpg

设置SNR=12db

 

5e7ec7b8cedf1c5e24da817c01708320_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.jpg

 

和之前开发的普通16QAM调制解调系统相比,软解调误码率更低。

 

基于FPGA的16QAM基带通信系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR_基于fpga的实时套刻误差测量系统的设计与实现-CSDN博客

 

仿真操作步骤可参考程序配套的操作视频。

 

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

        16QAM软解调是一种常用的数字调制解调技术,用于将接收到的16QAM调制的信号转换为原始数据。该技术结合了16种相位和振幅的调制方式,通过软判决算法对接收信号进行解调,16QAM软解调的系统原理是将接收到的16QAM调制信号转换为软判决结果,从而恢复原始数据。软解调是一种非硬判决的解调方法,它利用接收信号的采样值和相位信息来判断信号所处的调制状态,并对其进行解调。在16QAM软解调中,接收信号经过采样后,通过比较采样值和16个调制点的距离,选择最近的调制点作为解调结果。

 

       16QAM调制将每四个比特映射到一个复数点上,共有16种相位和振幅的调制方式。每个复数点对应一个调制符号,通过软解调,我们可以确定接收到的信号所对应的调制符号,进而推导出原始数据。

 

       设接收信号的采样值为rr,我们需要通过比较rr与16个调制点的距离,选择最近的调制点。

 

以下是16QAM软解调的具体步骤:

 

步骤1:接收信号采样

 

接收信号经过抽样过程,得到采样值rr

 

步骤2:计算距离

 

计算采样值rr与每个调制点的距离did_i,其中i=1,2,...,16i=1,2,...,16。距离可以使用欧氏距离或其他度量方法进行计算。

 

步骤3:选择最近的调制点

 

选择与采样值rr距离最近的调制点,记为dmind_{\min},并记录其索引imini_{\min}

 

步骤4:软判决

 

根据索引imini_{\min},确定接收信号对应的调制符号。根据调制符号,可以推导出原始数据。

 

数学公式示例

以下是16QAM软解调的数学公式示例:

 

对于接收信号的采样值rr,与每个调制点的距离did_i可以计算为:

 

a26e66bb940ea67e7517e4c70983dd33_watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=.png

根据索引imini_{\min}可以确定接收信号对应的调制符号,并进一步推导出原始数据。

 

        实现16QAM软解调的难点在于选择合适的距离度量方法和判决阈值,以及在存在噪声的情况下进行准确的判决。此外,还需要解决调制点的映射问题,确保软解调能够准确还原原始数据。            总结而言,16QAM软解调是一种通过比较采样值与调制点的距离,选择最近的调制点来解调接收信号的方法。通过软解调,可以恢复原始数据并实现高效的数据传输。

 

3.verilog核心程序 `// DUT

tops_16QAM_mod  top(

   .clk(clk),

   .rst(rst),

   .start(start),

   .parallel_data(parallel_data),

   .sin(sin),

   .cos(cos),

   .I_com(),

   .Q_com(),

   .I_comcos(I_com),//基带方式输出,即实际通信中的复数模式

   .Q_comsin(Q_com)

   );

    

//加入信道

//实部

awgns awgns_u1(

    .i_clk(clk),

    .i_rst(~rst),

    .i_SNR(i_SNR), //这个地方可以设置信噪比,数值大小从-10~50,

    .i_din(I_com),

    .o_noise(),

    .o_dout(I_Ncom)

    );  

//虚部    

awgns awgns_u2(

    .i_clk(clk),

    .i_rst(~rst),

    .i_SNR(i_SNR), //这个地方可以设置信噪比,数值大小从-10~50,

    .i_din(Q_com),

    .o_noise(),

    .o_dout(Q_Ncom)

    );

    

wire signed[15:0]o_b1;

wire signed[15:0]o_b2;

wire signed[15:0]o_b3;

wire signed[15:0]o_b4;

 

tops_16QAM_demod  top2(

   .clk(clk),

   .rst(rst),

   .start(start),

   .I_Ncom(I_Ncom),

   .Q_Ncom(Q_Ncom),

   .I_comcos2(I_comcos2),

   .Q_comsin2(Q_comsin2),

   .o_Ifir(o_Ifir),

   .o_Qfir(o_Qfir),

   .o_b1(),

   .o_b2(),

   .o_b3(),

   .o_b4(),

   .o_sdout(o_sdout)

   );  

   

//4个bit同时统计误码率    

wire signed[31:0]o_error_num1;

wire signed[31:0]o_total_num1;

Error_Chech Error_Chech_u1(

    .i_clk(clk),

    .i_rst(~rst),

    .i_trans(parallel_data),

    .i_rec(o_sdout),

    .o_error_num(o_error_num1),

    .o_total_num(o_total_num1)

    );  

 

assign o_total_num = o_total_num1;

assign o_error_num = o_error_num1;

    

endmodule

0sj_020m`