基于FPGA的16QAM调制器verilog实现,包括testbench,并通过MATLAB显示FPGA输出信号的星座图

187 阅读2分钟

1.算法仿真效果

matlab2022a/vivado2019.2仿真结果如下:

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

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

 将FPGA仿真的数据导出,然后在matlab中将数据通过噪声之后,可以得到如下的星座图效果。

 

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

fpga工程版本信息: `

 

  

  

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

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

      16QAM全称正交幅度调制是英文Quadrature Amplitude Modulation的缩略语简称,意思是正交幅度调制,是一种数字调制方式。产生的方法有正交调幅法和复合相移法。

 

16QAM是指包含16种符号的QAM调制方式。

16QAM 调制解调原理方框图如右图1:

      16QAM 是用两路独立的正交 4ASK 信号叠加而成,4ASK 是用多电平信号去键控载波而得到的信号。它是 2ASK 调制的推广,和 2ASK 相比,这种调制的优点在于信息传输速率高。

正交幅度调制是利用多进制振幅键控(MASK)和正交载波调制相结合产生的。

16 进制的正交振幅调制是一种振幅相位联合键控信号。16QAM 的产生有 2 种方法:

(1)正交调幅法,它是有 2 路正交的四电平振幅键控信号叠加而成;

(2)复合相移法:它是用 2 路独立的四相位移相键控信号叠加而成。

这里采用正交调幅法。

        串/并变换器将速率为Rb的二进制码元序列分为两路,速率为Rb/2.2-4电平变换为Rb/2 的二进制码元序列变成速率为RS=Rb/log216 的 4 个电平信号,4 电平信号与正交载波相乘,完成正交调制,两路信号叠加后产生 16QAM信号.在两路速率为Rb/2 的二进制码元序列中,经 2-4 电平变换器输出为 4 电平信号,即M=16.经 4 电平正交幅度调制和叠加后,输出 16 个信号状态,即 16QAM.

RS=Rb/log216=RB/4.

  1. 16QAM 解调原理

       16QAM 信号采取正交相干解调的方法解调,解调器首先对收到的 16QAM 信号进行正交相干解调,一路与 cos ω c t 相乘,一路与 sin ω c t 相乘。然后经过低通滤波器,低通滤波器 LPF 滤除乘法器产生的高频分量,获得有用信号,低通滤波器LPF 输出经抽样判决可恢复出电平信号。

 

 

 

3.verilog核心程序 ``timescale 1ns / 1ns

module TEST;

 

reg clk;

reg rst;

reg start;

    wire [15:0]sin;

    wire [15:0]cos;

wire signed[19:0]  I_com;

wire signed[19:0]  Q_com;

 

// DUT

tops_16QAM_mod  top(

   .clk(clk),

   .rst(rst),

   .start(start),

   .sin(sin),

   .cos(cos),

   .I_com(I_com),

   .Q_com(Q_com)

   );

 

initial begin

clk = 0;

rst = 0;

start = 1;

#10;

rst = 1;

end

always #5

clk <= ~clk;

integer fout1;

integer fout2;

initial begin

 fout1 = $fopen("II.txt","w");

 fout2 = $fopen("QQ.txt","w");

end

 

always @ (posedge clk)

 begin

     if(rst==1)

     begin

     $fwrite(fout1,"%d\n",I_com);

 $fwrite(fout2,"%d\n",Q_com);

 end

end

 

Endmodule`